From 5dd2effd1100214a17104fc9fe751967d2d748d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 27 Jan 2018 21:11:04 +0100 Subject: [PATCH 01/44] tic for all stages --- .travis.yml | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index db722bfc5..4941d3c8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,32 @@ # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r +# Default configuration for use with tic package +# Usually you shouldn't need to change the first part of the file + +# DO NOT CHANGE THE CODE BELOW +before_install: R -q -e 'install.packages(c("remotes", "curl")); remotes::install_github("ropenscilabs/tic"); tic::prepare_all_stages(); tic::before_install()' +install: R -q -e 'tic::install()' +after_install: R -q -e 'tic::after_install()' +before_script: R -q -e 'tic::before_script()' +script: R -q -e 'tic::script()' +after_success: R -q -e 'tic::after_success()' +after_failure: R -q -e 'tic::after_failure()' +before_deploy: R -q -e 'tic::before_deploy()' +deploy: + provider: script + script: R -q -e 'tic::deploy()' + on: + all_branches: true +after_deploy: R -q -e 'tic::after_deploy()' +after_script: R -q -e 'tic::after_script()' +# DO NOT CHANGE THE CODE ABOVE + +# Custom parts: # Header language: r sudo: false cache: packages latex: false -warnings_are_errors: true #env env: @@ -35,32 +56,7 @@ notifications: on_success: change on_failure: change -#before_script -before_script: -- R -q -e 'devtools::install_github("ropenscilabs/tic"); tic::prepare_all_stages()' - -#after_success -after_success: -- R -q -e 'tic::after_success()' - -#deploy // https://github.com/travis-ci/travis-build/blob/85ef7108/lib/travis/build/addons/deploy/script.rb#L100-L107 -deploy: - provider: script - script: R -q -e 'tic::deploy()' - on: - all_branches: true - # Custom parts: -#r_github_packages -r_github_packages: -- krlmlr/roxygen@b-%23521-subsection - -#r_packages -r_packages: - #services services: - -#before_install -before_install: From 95932df92befcd824ab39cae7cfa07872cff3d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 27 Jan 2018 20:13:54 +0000 Subject: [PATCH 02/44] Deploy from Travis build 955 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/334187014 Commit: 5dd2effd1100214a17104fc9fe751967d2d748d8 --- .Rbuildignore | 1 + docs/articles/DBI-1.html | 675 ++++++ docs/articles/DBI-proposal.html | 668 ++++++ docs/articles/backend.html | 301 +++ docs/articles/biblio.bib | 295 +++ docs/articles/hierarchy.png | Bin 0 -> 75565 bytes docs/articles/index.html | 132 ++ docs/articles/spec.html | 2785 +++++++++++++++++++++++ docs/authors.html | 138 ++ docs/index.html | 188 ++ docs/jquery.sticky-kit.min.js | 9 + docs/link.svg | 12 + docs/news/index.html | 492 ++++ docs/pkgdown.css | 163 ++ docs/pkgdown.js | 45 + docs/reference/ANSI.html | 138 ++ docs/reference/DBI-package.html | 206 ++ docs/reference/DBIConnection-class.html | 171 ++ docs/reference/DBIDriver-class.html | 149 ++ docs/reference/DBIObject-class.html | 179 ++ docs/reference/DBIResult-class.html | 164 ++ docs/reference/SQL.html | 189 ++ docs/reference/Table.html | 147 ++ docs/reference/dbBind.html | 323 +++ docs/reference/dbCallProc.html | 149 ++ docs/reference/dbClearResult.html | 200 ++ docs/reference/dbColumnInfo.html | 187 ++ docs/reference/dbConnect.html | 211 ++ docs/reference/dbDataType.html | 254 +++ docs/reference/dbDisconnect.html | 193 ++ docs/reference/dbDriver.html | 205 ++ docs/reference/dbExecute.html | 218 ++ docs/reference/dbExistsTable.html | 217 ++ docs/reference/dbFetch.html | 305 +++ docs/reference/dbGetDBIVersion.html | 134 ++ docs/reference/dbGetException.html | 172 ++ docs/reference/dbGetInfo.html | 207 ++ docs/reference/dbGetQuery.html | 270 +++ docs/reference/dbGetRowCount.html | 204 ++ docs/reference/dbGetRowsAffected.html | 193 ++ docs/reference/dbGetStatement.html | 188 ++ docs/reference/dbHasCompleted.html | 210 ++ docs/reference/dbIsValid.html | 219 ++ docs/reference/dbListConnections.html | 165 ++ docs/reference/dbListFields.html | 183 ++ docs/reference/dbListResults.html | 172 ++ docs/reference/dbListTables.html | 206 ++ docs/reference/dbQuoteIdentifier.html | 232 ++ docs/reference/dbQuoteLiteral.html | 198 ++ docs/reference/dbQuoteString.html | 230 ++ docs/reference/dbReadTable.html | 260 +++ docs/reference/dbRemoveTable.html | 214 ++ docs/reference/dbSendQuery.html | 245 ++ docs/reference/dbSendStatement.html | 236 ++ docs/reference/dbSetDataMappings.html | 162 ++ docs/reference/dbWithTransaction.html | 246 ++ docs/reference/dbWriteTable.html | 343 +++ docs/reference/hidden_aliases.html | 262 +++ docs/reference/index.html | 420 ++++ docs/reference/make.db.names.html | 237 ++ docs/reference/rownames.html | 205 ++ docs/reference/sqlAppendTable.html | 217 ++ docs/reference/sqlCreateTable.html | 219 ++ docs/reference/sqlData.html | 196 ++ docs/reference/sqlInterpolate.html | 175 ++ docs/reference/sqlParseVariables.html | 204 ++ docs/reference/transactions.html | 257 +++ 67 files changed, 16990 insertions(+) create mode 100644 docs/articles/DBI-1.html create mode 100644 docs/articles/DBI-proposal.html create mode 100644 docs/articles/backend.html create mode 100644 docs/articles/biblio.bib create mode 100644 docs/articles/hierarchy.png create mode 100644 docs/articles/index.html create mode 100644 docs/articles/spec.html create mode 100644 docs/authors.html create mode 100644 docs/index.html create mode 100644 docs/jquery.sticky-kit.min.js create mode 100644 docs/link.svg create mode 100644 docs/news/index.html create mode 100644 docs/pkgdown.css create mode 100644 docs/pkgdown.js create mode 100644 docs/reference/ANSI.html create mode 100644 docs/reference/DBI-package.html create mode 100644 docs/reference/DBIConnection-class.html create mode 100644 docs/reference/DBIDriver-class.html create mode 100644 docs/reference/DBIObject-class.html create mode 100644 docs/reference/DBIResult-class.html create mode 100644 docs/reference/SQL.html create mode 100644 docs/reference/Table.html create mode 100644 docs/reference/dbBind.html create mode 100644 docs/reference/dbCallProc.html create mode 100644 docs/reference/dbClearResult.html create mode 100644 docs/reference/dbColumnInfo.html create mode 100644 docs/reference/dbConnect.html create mode 100644 docs/reference/dbDataType.html create mode 100644 docs/reference/dbDisconnect.html create mode 100644 docs/reference/dbDriver.html create mode 100644 docs/reference/dbExecute.html create mode 100644 docs/reference/dbExistsTable.html create mode 100644 docs/reference/dbFetch.html create mode 100644 docs/reference/dbGetDBIVersion.html create mode 100644 docs/reference/dbGetException.html create mode 100644 docs/reference/dbGetInfo.html create mode 100644 docs/reference/dbGetQuery.html create mode 100644 docs/reference/dbGetRowCount.html create mode 100644 docs/reference/dbGetRowsAffected.html create mode 100644 docs/reference/dbGetStatement.html create mode 100644 docs/reference/dbHasCompleted.html create mode 100644 docs/reference/dbIsValid.html create mode 100644 docs/reference/dbListConnections.html create mode 100644 docs/reference/dbListFields.html create mode 100644 docs/reference/dbListResults.html create mode 100644 docs/reference/dbListTables.html create mode 100644 docs/reference/dbQuoteIdentifier.html create mode 100644 docs/reference/dbQuoteLiteral.html create mode 100644 docs/reference/dbQuoteString.html create mode 100644 docs/reference/dbReadTable.html create mode 100644 docs/reference/dbRemoveTable.html create mode 100644 docs/reference/dbSendQuery.html create mode 100644 docs/reference/dbSendStatement.html create mode 100644 docs/reference/dbSetDataMappings.html create mode 100644 docs/reference/dbWithTransaction.html create mode 100644 docs/reference/dbWriteTable.html create mode 100644 docs/reference/hidden_aliases.html create mode 100644 docs/reference/index.html create mode 100644 docs/reference/make.db.names.html create mode 100644 docs/reference/rownames.html create mode 100644 docs/reference/sqlAppendTable.html create mode 100644 docs/reference/sqlCreateTable.html create mode 100644 docs/reference/sqlData.html create mode 100644 docs/reference/sqlInterpolate.html create mode 100644 docs/reference/sqlParseVariables.html create mode 100644 docs/reference/transactions.html diff --git a/.Rbuildignore b/.Rbuildignore index 920e9e4b0..62f22d894 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -25,3 +25,4 @@ inst\/doc\/DBI\.b..$ ^_pkgdown\.yml$ ^revdep/ ^API$ +^docs$ diff --git a/docs/articles/DBI-1.html b/docs/articles/DBI-1.html new file mode 100644 index 000000000..972cabe69 --- /dev/null +++ b/docs/articles/DBI-1.html @@ -0,0 +1,675 @@ + + + + + + + +A Common Database Interface (DBI) • DBI + + + + + + +
+
+ + + +
+
+ + + + +
+

This document describes a common interface between the S language (in its R and S-Plus implementations) and database management systems (DBMS). The interface defines a small set of classes and methods similar in spirit to Perl’s DBI, Java’s JDBC, Python’s DB-API, and Microsoft’s ODBC.

+
+

+Version

+

This document describes version 0.1-6 of the database interface API (application programming interface).

+
+
+

+Introduction

+

The database interface (DBI) separates the connectivity to the DBMS into a “front-end” and a “back-end”. Applications use only the exposed “front-end” API. The facilities that communicate with specific DBMS (Oracle, PostgreSQL, etc.) are provided by “device drivers” that get invoked automatically by the S language evaluator. The following example illustrates some of the DBI capabilities:

+
## Choose the proper DBMS driver and connect to the server
+
+drv <- dbDriver("ODBC")
+con <- dbConnect(drv, "dsn", "usr", "pwd")
+
+## The interface can work at a higher level importing tables 
+## as data.frames and exporting data.frames as DBMS tables.
+
+dbListTables(con)
+dbListFields(con, "quakes")
+if(dbExistsTable(con, "new_results"))
+   dbRemoveTable(con, "new_results")
+dbWriteTable(con, "new_results", new.output)
+
+## The interface allows lower-level interface to the DBMS
+res <- dbSendQuery(con, paste(
+            "SELECT g.id, g.mirror, g.diam, e.voltage",
+            "FROM geom_table as g, elec_measures as e",
+            "WHERE g.id = e.id and g.mirrortype = 'inside'",
+            "ORDER BY g.diam"))
+out <- NULL
+while(!dbHasCompleted(res)){
+   chunk <- fetch(res, n = 10000)
+   out <- c(out, doit(chunk))
+}
+
+## Free up resources
+dbClearResult(res)
+dbDisconnect(con)
+dbUnloadDriver(drv)
+

(only the first 2 expressions are DBMS-specific – all others are independent of the database engine itself).

+

Individual DBI drivers need not implement all the features we list below (we indicate those that are optional). Furthermore, drivers may extend the core DBI facilities, but we suggest to have these extensions clearly indicated and documented.

+

The following are the elements of the DBI:

+
    +
  1. +

    A set of classes and methods (Section [sec:DBIClasses]) that defines what operations are possible and how they are defined, e.g.:

    +
      +
    • connect/disconnect to the DBMS

    • +
    • create and execute statements in the DBMS

    • +
    • extract results/output from statements

    • +
    • error/exception handling

    • +
    • information (meta-data) from database objects

    • +
    • transaction management (optional)

    • +
    +

    Some things are left explicitly unspecified, e.g., authentication and even the query language, although it is hard to avoid references to SQL and relational database management systems (RDBMS).

    +
  2. +
  3. +

    Drivers

    +

    Drivers are collection of functions that implement the functionality defined above in the context of specific DBMS, e.g., mSQL, Informix.

    +
  4. +
  5. +

    Data type mappings (Section [sec:data-mappings].)

    +

    Mappings and conversions between DBMS data types and R/S objects. All drivers should implement the “basic” primitives (see below), but may chose to add user-defined conversion function to handle more generic objects (e.g., factors, ordered factors, time series, arrays, images).

    +
  6. +
  7. +

    Utilities (Section [sec:utilities].)

    +

    These facilities help with details such as mapping of identifiers between S and DBMS (e.g., _ is illegal in R/S names, and . is used for constructing compound SQL identifiers), etc.

    +
  8. +
+
+
+

+DBI Classes and Methods

+

The following are the main DBI classes. They need to be extended by individual database back-ends (Sybase, Oracle, etc.) Individual drivers need to provide methods for the generic functions listed here (those methods that are optional are so indicated).

+

Note: Although R releases prior to 1.4 do not have a formal concept of classes, we will use the syntax of the S Version 4 classes and methods (available in R releases 1.4 and later as library methods) to convey precisely the DBI class hierarchy, its methods, and intended behavior.

+

The DBI classes are DBIObject, DBIDriver, DBIConnection and DBIResult. All these are virtual classes. Drivers define new classes that extend these, e.g., PgSQLDriver, PgSQLConnection, and so on.

+
+Class hierarchy for the DBI. The top two layers are comprised of virtual classes and each lower layer represents a set of driver-specific implementation classes that provide the functionality defined by the virtual classes above.

Class hierarchy for the DBI. The top two layers are comprised of virtual classes and each lower layer represents a set of driver-specific implementation classes that provide the functionality defined by the virtual classes above.

+
+
+
+DBIObject:
+
+

Virtual class1 that groups all other DBI classes.

+
+
+DBIDriver:
+
+

Virtual class that groups all DBMS drivers. Each DBMS driver extends this class. Typically generator functions instantiate the actual driver objects, e.g., PgSQL, HDF5, BerkeleyDB.

+
+
+DBIConnection:
+
+

Virtual class that encapsulates connections to DBMS.

+
+
+DBIResult:
+
+

Virtual class that describes the result of a DBMS query or statement.

+

[Q: Should we distinguish between a simple result of DBMS statements e.g., as delete from DBMS queries (i.e., those that generate data).]

+
+
+

The methods format, print, show, dbGetInfo, and summary are defined (and implemented in the DBI package) for the DBIObject base class, thus available to all implementations; individual drivers, however, are free to override them as they see fit.

+
+
+format(x, ...):
+
+

produces a concise character representation (label) for the DBIObject x.

+
+
+print(x, ...)/show(x):
+
+

prints a one-line identification of the object x.

+
+
+summary(object, ...):
+
+

produces a concise description of the object. The default method for DBIObject simply invokes dbGetInfo(dbObj) and prints the name-value pairs one per line. Individual implementations may tailor this appropriately.

+
+
+dbGetInfo(dbObj, ...):
+
+

extracts information (meta-data) relevant for the DBIObject dbObj. It may return a list of key/value pairs, individual meta-data if supplied in the call, or NULL if the requested meta-data is not available.

+

Hint: Driver implementations may choose to allow an argument what to specify individual meta-data, e.g., dbGetInfo(drv, what = max.connections).

+
+
+

In the next few sub-sections we describe in detail each of these classes and their methods.

+
+

+Class DBIObject +

+

This class simply groups all DBI classes, and thus all extend it.

+
+
+

+Class DBIDriver +

+

This class identifies the database management system. It needs to be extended by individual back-ends (Oracle, PostgreSQL, etc.)

+

The DBI provides the generator dbDriver(driverName) which simply invokes the function driverName, which in turn instantiates the corresponding driver object.

+

The DBIDriver class defines the following methods:

+
+
+driverName:
+
+

[meth:driverName] initializes the driver code. The name driverName refers to the actual generator function for the DBMS, e.g., RPgSQL, RODBC, HDF5. The driver instance object is used with dbConnect (see page ) for opening one or possibly more connections to one or more DBMS.

+
+
+dbListConnections(drv, ...):
+
+

list of current connections being handled by the drv driver. May be NULL if there are no open connections. Drivers that do not support multiple connections may return the one open connection.

+
+
+dbGetInfo(dbObj, ...):
+
+

returns a list of name-value pairs of information about the driver.

+

Hint: Useful entries could include

+
+
+name:
+
+

the driver name (e.g., RODBC, RPgSQL);

+
+
+driver.version:
+
+

version of the driver;

+
+
+DBI.version:
+
+

the version of the DBI that the driver implements, e.g., 0.1-2;

+
+
+client.version:
+
+

of the client DBMS libraries (e.g., version of the libpq library in the case of RPgSQL);

+
+
+max.connections:
+
+

maximum number of simultaneous connections;

+
+
+

plus any other relevant information about the implementation, for instance, how the driver handles upper/lower case in identifiers.

+
+
+dbUnloadDriver(driverName) (optional):
+
+

frees all resources (local and remote) used by the driver. Returns a logical to indicate if it succeeded or not.

+
+
+
+
+

+Class DBIConnection +

+

This virtual class encapsulates the connection to a DBMS, and it provides access to dynamic queries, result sets, DBMS session management (transactions), etc.

+

Note: Individual drivers are free to implement single or multiple simultaneous connections.

+

The methods defined by the DBIConnection class include:

+
+
+dbConnect(drv, ...):
+
+

[meth:dbConnect] creates and opens a connection to the database implemented by the driver drv (see Section [sec:DBIDriver]). Each driver will define what other arguments are required, e.g., dbname or dsn for the database name, user, and password. It returns an object that extends DBIConnection in a driver-specific manner (e.g., the MySQL implementation could create an object of class MySQLConnection that extends DBIConnection).

+
+
+dbDisconnect(conn, ...):
+
+

closes the connection, discards all pending work, and frees resources (e.g., memory, sockets). Returns a logical indicating whether it succeeded or not.

+
+
+dbSendQuery(conn, statement, ...):
+
+

submits one statement to the DBMS. It returns a DBIResult object. This object is needed for fetching data in case the statement generates output (see fetch on page ), and it may be used for querying the state of the operation; see dbGetInfo and other meta-data methods on page .

+
+
+dbGetQuery(conn, statement, ...):
+
+

submit, execute, and extract output in one operation. The resulting object may be a data.frame if the statement generates output. Otherwise the return value should be a logical indicating whether the query succeeded or not.

+
+
+dbGetException(conn, ...):
+
+

returns a list with elements errNum and errMsg with the status of the last DBMS statement sent on a given connection (this information may also be provided by the dbGetInfo meta-data function on the conn object.

+

Hint: The ANSI SQL-92 defines both a status code and an status message that could be return as members of the list.

+
+
+dbGetInfo(dbObj, ...):
+
+

returns a list of name-value pairs describing the state of the connection; it may return one or more meta-data, the actual driver method allows to specify individual pieces of meta-data (e.g., maximum number of open results/cursors).

+

Hint: Useful entries could include

+
+
+dbname:
+
+

the name of the database in use;

+
+
+db.version:
+
+

the DBMS server version (e.g., “Oracle 8.1.7 on Solaris”;

+
+
+host:
+
+

host where the database server resides;

+
+
+user:
+
+

user name;

+
+
+password:
+
+

password (is this safe?);

+
+
+

plus any other arguments related to the connection (e.g., thread id, socket or TCP connection type).

+
+
+dbListResults(conn, ...):
+
+

list of DBIResult objects currently active on the connection conn. May be NULL if no result set is active on conn. Drivers that implement only one result set per connection could return that one object (no need to wrap it in a list).

+
+
+

Note: The following are convenience methods that simplify the import/export of (mainly) data.frames. The first five methods implement the core methods needed to attach remote DBMS to the S search path. (For details, see Chambers (1991; Chambers 1998).)

+

Hint: For relational DBMS these methods may be easily implemented using the core DBI methods dbConnect, dbSendQuery, and fetch, due to SQL reflectance (i.e., one easily gets this meta-data by querying the appropriate tables on the RDBMS).

+
+
+dbListTables(conn, ...):
+
+

returns a character vector (possibly of zero-length) of object (table) names available on the conn connection.

+
+
+dbReadTable(conn, name, ...):
+
+

imports the data stored remotely in the table name on connection conn. Use the field row.names as the row.names attribute of the output data.frame. Returns a data.frame.

+

[Q: should we spell out how row.names should be created? E.g., use a field (with unique values) as row.names? Also, should dbReadTable reproduce a data.frame exported with dbWriteTable?]

+
+
+dbWriteTable(conn, name, value, ...):
+
+

write the object value (perhaps after coercing it to data.frame) into the remote object name in connection conn. Returns a logical indicating whether the operation succeeded or not.

+
+
+dbExistsTable(conn, name, ...):
+
+

does remote object name exist on conn? Returns a logical.

+
+
+dbRemoveTable(conn, name, ...):
+
+

removes remote object name on connection conn. Returns a logical indicating whether the operation succeeded or not.

+
+
+dbListFields(conn, name, ...):
+
+

returns a character vector listing the field names of the remote table name on connection conn (see dbColumnInfo() for extracting data type on a table).

+
+
+

Note: The following methods deal with transactions and stored procedures. All these functions are optional.

+
+
+dbCommit(conn, ...)(optional):
+
+

commits pending transaction on the connection and returns TRUE or FALSE depending on whether the operation succeeded or not.

+
+
+dbRollback(conn, ...)(optional):
+
+

undoes current transaction on the connection and returns TRUE or FALSE depending on whether the operation succeeded or not.

+
+
+dbCallProc(conn, storedProc, ...)(optional):
+
+

invokes a stored procedure in the DBMS and returns a DBIResult object.

+

[Stored procedures are not part of the ANSI SQL-92 standard and vary substantially from one RDBMS to another.]

+
+
+
+
+

+Class DBIResult +

+

This virtual class describes the result and state of execution of a DBMS statement (any statement, query or non-query). The result set res keeps track of whether the statement produces output for R/S, how many rows were affected by the operation, how many rows have been fetched (if statement is a query), whether there are more rows to fetch, etc.

+

Note: Individual drivers are free to allow single or multiple active results per connection.

+

[Q: Should we distinguish between results that return no data from those that return data?]

+

The class DBIResult defines the following methods:

+
+
+fetch(res, n, ...):
+
+

[meth:fetch] fetches the next n elements (rows) from the result set res and return them as a data.frame. A value of n=-1 is interpreted as “return all elements/rows”.

+
+
+dbClearResult(res, ...):
+
+

flushes any pending data and frees all resources (local and remote) used by the object res on both sides of the connection. Returns a logical indicating success or not.

+
+
+dbGetInfo(dbObj, ...):
+
+

returns a name-value list with the state of the result set.

+

Hint: Useful entries could include

+
+
+statement:
+
+

a character string representation of the statement being executed;

+
+
+rows.affected:
+
+

number of affected records (changed, deleted, inserted, or extracted);

+
+
+row.count:
+
+

number of rows fetched so far;

+
+
+has.completed:
+
+

has the statement (query) finished?

+
+
+is.select:
+
+

a logical describing whether or not the statement generates output;

+
+
+

plus any other relevant driver-specific meta-data.

+
+
+dbColumnInfo(res, ...):
+
+

produces a data.frame that describes the output of a query. The data.frame should have as many rows as there are output fields in the result set, and each column in the data.frame should describe an aspect of the result set field (field name, type, etc.)

+

Hint: The data.frame columns could include

+
+
+field.name:
+
+

DBMS field label;

+
+
+field.type:
+
+

DBMS field type (implementation-specific);

+
+
+data.type:
+
+

corresponding R/S data type, e.g., integer;

+
+
+precision/scale:
+
+

(as in ODBC terminology), display width and number of decimal digits, respectively;

+
+
+nullable:
+
+

whether the corresponding field may contain (DBMS) NULL values;

+
+
+

plus other driver-specific information.

+
+
+dbSetDataMappings(flds, ...)(optional):
+
+

defines a conversion between internal DBMS data types and R/S classes. We expect the default mappings (see Section [sec:data-mappings]) to be by far the most common ones, but users that need more control may specify a class generator for individual fields in the result set. [This topic needs further discussion.]

+
+
+

Note: The following are convenience methods that extract information from the result object (they may be implemented by invoking dbGetInfo with appropriate arguments).

+
+
+dbGetStatement(res, ...)(optional):
+
+

returns the DBMS statement (as a character string) associated with the result res.

+
+
+dbGetRowsAffected(res, ...)(optional):
+
+

returns the number of rows affected by the executed statement (number of records deleted, modified, extracted, etc.)

+
+
+dbHasCompleted(res, ...)(optional):
+
+

returns a logical that indicates whether the operation has been completed (e.g., are there more records to be fetched?).

+
+
+dbGetRowCount(res, ...)(optional):
+
+

returns the number of rows fetched so far.

+
+
+
+
+
+

+Data Type Mappings

+

The data types supported by databases are different than the data types in R and S, but the mapping between the “primitive” types is straightforward: Any of the many fixed and varying length character types are mapped to R/S character. Fixed-precision (non-IEEE) numbers are mapped into either doubles (numeric) or long (integer). Notice that many DBMS do not follow the so-called IEEE arithmetic, so there are potential problems with under/overflows and loss of precision, but given the R/S primitive types we cannot do too much but identify these situations and warn the application (how?).

+

By default dates and date-time objects are mapped to character using the appropriate TO_CHAR function in the DBMS (which should take care of any locale information). Some RDBMS support the type CURRENCY or MONEY which should be mapped to numeric (again with potential round off errors). Large objects (character, binary, file, etc.) also need to be mapped. User-defined functions may be specified to do the actual conversion (as has been done in other inter-systems packages2).

+

Specifying user-defined conversion functions still needs to be defined.

+
+
+

+Utilities

+

The core DBI implementation should make available to all drivers some common basic utilities. For instance:

+
+
+dbGetDBIVersion:
+
+

returns the version of the currently attached DBI as a string.

+
+
+dbDataType(dbObj, obj, ...):
+
+

returns a string with the (approximately) appropriate data type for the R/S object obj. The DBI can implement this following the ANSI-92 standard, but individual drivers may want/need to extend it to make use of DBMS-specific types.

+
+
+make.db.names(dbObj, snames, ...):
+
+

maps R/S names (identifiers) to SQL identifiers replacing illegal characters (as .) by the legal SQL _.

+
+
+SQLKeywords(dbObj, ...):
+
+

returns a character vector of SQL keywords (reserved words). The default method returns the list of .SQL92Keywords, but drivers should update this vector with the DBMS-specific additional reserved words.

+
+
+isSQLKeyword(dbObj, name, ...):
+
+

for each element in the character vector name determine whether or not it is an SQL keyword, as reported by the generic function SQLKeywords. Returns a logical vector parallel to the input object name.

+
+
+
+
+

+Open Issues and Limitations

+

There are a number of issues and limitations that the current DBI conscientiously does not address on the interest of simplicity. We do list here the most important ones.

+
+
Non-SQL:
+
+

Is it realistic to attempt to encompass non-relational databases, like HDF5, Berkeley DB, etc.?

+
+
Security:
+
+

allowing users to specify their passwords on R/S scripts may be unacceptable for some applications. We need to consider alternatives where users could store authentication on files (perhaps similar to ODBC’s odbc.ini) with more stringent permissions.

+
+
Exceptions:
+
+

the exception mechanism is a bit too simple, and it does not provide for information when problems stem from the DBMS interface itself. For instance, under/overflow or loss of precision as we move numeric data from DBMS to the more limited primitives in R/S.

+
+
Asynchronous communication:
+
+

most DBMS support both synchronous and asynchronous communications, allowing applications to submit a query and proceed while the database server process the query. The application is then notified (or it may need to poll the server) when the query has completed. For large computations, this could be very useful, but the DBI would need to specify how to interrupt the server (if necessary) plus other details. Also, some DBMS require applications to use threads to implement asynchronous communication, something that neither R nor S-Plus currently addresses.

+
+
SQL scripts:
+
+

the DBI only defines how to execute one SQL statement at a time, forcing users to split SQL scripts into individual statements. We need a mechanism by which users can submit SQL scripts that could possibly generate multiple result sets; in this case we may need to introduce new methods to loop over multiple results (similar to Python’s nextResultSet).

+
+
BLOBS/CLOBS:
+
+

large objects (both character and binary) present some challenges both to R and S-Plus. It is becoming more common to store images, sounds, and other data types as binary objects in DBMS, some of which can be in principle quite large. The SQL-92 ANSI standard allows up to 2 gigabytes for some of these objects. We need to carefully plan how to deal with binary objects.

+
+
Transactions:
+
+

transaction management is not fully described.

+
+
Additional methods:
+
+

Do we need any additional methods? (e.g., dbListDatabases(conn), dbListTableIndices(conn, name), how do we list all available drivers?)

+
+
Bind variables:
+
+

the interface is heavily biased towards queries, as opposed to general purpose database development. In particular we made no attempt to define “bind variables”; this is a mechanism by which the contents of R/S objects are implicitly moved to the database during SQL execution. For instance, the following embedded SQL statement

+
  /* SQL */
+  SELECT * from emp_table where emp_id = :sampleEmployee
+

would take the vector sampleEmployee and iterate over each of its elements to get the result. Perhaps the DBI could at some point in the future implement this feature.

+
+
+
+
+

+Resources

+

The idea of a common interface to databases has been successfully implemented in various environments, for instance:

+

Java’s Database Connectivity (JDBC) (www.javasoft.com).

+

In C through the Open Database Connectivity (ODBC) (www.unixodbc.org).

+

Python’s Database Application Programming Interface (www.python.org).

+

Perl’s Database Interface (dbi.perl.org).

+
+
+

Chambers, John M. 1991. “Data Management in S.” Bell Labs, Lucent Technologies.

+
+
+

———. 1998. “Database Classes.” Bell Labs, Lucent Technologies.

+
+
+
+
+
+
    +
  1. A virtual class allows us to group classes that share some common characteristics, even if their implementations are radically different.

  2. +
  3. Duncan Temple Lang has volunteered to port the data conversion code found in R-Java, R-Perl, and R-Python packages to the DBI

  4. +
+
+
+
+ + + +
+ + +
+ +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/articles/DBI-proposal.html b/docs/articles/DBI-proposal.html new file mode 100644 index 000000000..3e01362df --- /dev/null +++ b/docs/articles/DBI-proposal.html @@ -0,0 +1,668 @@ + + + + + + + +A Common Interface to Relational Databases from R and S – A Proposal • DBI + + + + + + +
+
+ + + +
+
+ + + + +
+

For too long S and similar data analysis environments have lacked good interfaces to relational database systems (RDBMS). For the last twenty years or so these RDBMS have evolved into highly optimized client-server systems for data storage and manipulation, and currently they serve as repositories for most of the business, industrial, and research “raw” data that analysts work with. Other analysis packages, such as SAS, have traditionally provided good data connectivity, but S and GNU R have relied on intermediate text files as means of importing data (but see (R Data Import/Export 2001) and (Using Relational Database Systems with R 2000).) Although this simple approach works well for relatively modest amounts of mostly static data, it does not scale up to larger amounts of data distributed over machines and locations, nor does it scale up to data that is highly dynamic – situations that are becoming increasingly common.

+

We want to propose a common interface between R/S and RDBMS that would allow users to access data stored on database servers in a uniform and predictable manner irrespective of the database engine. The interface defines a small set of classes and methods similar in spirit to Python’s DB-API, Java’s JDBC, Microsoft’s ODBC, Perl’s DBI, etc., but it conforms to the “whole-object” philosophy so natural in S and R.

+
+

+Computing with Distributed Data

+

As data analysts, we are increasingly faced with the challenge of larger data sources distributed over machines and locations; most of these data sources reside in relational database management systems (RDBMS). These relational databases represent a mature client-server distributed technology that we as analysts could be exploiting more that we’ve done in the past. The relational technology provides a well-defined standard, the ANSI SQL-92 (X/Open CAE Specification: SQL and RDA 1994), both for defining and manipulating data in a highly optimized fashion from virtually any application.

+

In contrast, S and Splus have provided somewhat limited tools for coping with the challenges of larger and distributed data sets (Splus does provide an import function to import from databases, but it is quite limited in terms of SQL facilities). The R community has been more resourceful and has developed a number of good libraries for connecting to mSQL, MySQL, PostgreSQL, and ODBC; each library, however, has defined its own interface to each database engine a bit differently. We think it would be to everybody’s advantage to coordinate the definition of a common interface, an effort not unlike those taken in the Python and Perl communities.

+

The goal of a common, seamless access to distributed data is a modest one in our evolution towards a fully distributed computing environment. We recognize the greater goal of distributed computing as the means to fully integrate diverse systems – not just databases – into a truly flexible analysis environment. Good connectivity to databases, however, is of immediate necessity both in practical terms and as a means to help us transition from monolithic, self-contained systems to those in which computations, not only the data, can be carried out in parallel over a wide number of computers and/or systems Temple Lang (2000). Issues of reliability, security, location transparency, persistence, etc., will be new to most of us and working with distributed data may provide a more gradual change to ease in the ultimate goal of full distributed computing.

+
+
+

+A Common Interface

+

We believe that a common interface to databases can help users easily access data stored in RDBMS. A common interface would describe, in a uniform way, how to connect to RDBMS, extract meta-data (such as list of available databases, tables, etc.) as well as a uniform way to execute SQL statements and import their output into R and S. The current emphasis is on querying databases and not so much in a full low-level interface for database development as in JDBC or ODBC, but unlike these, we want to approach the interface from the “whole-object” perspective J. M. Chambers (1998) so natural to R/S and Python – for instance, by fetching all fields and records simultaneously into a single object.

+

The basic idea is to split the interface into a front-end consisting of a few classes and generic functions that users invoke and a back-end set of database-specific classes and methods that implement the actual communication. (This is a very well-known pattern in software engineering, and another good verbatim is the device-independent graphics in R/S where graphics functions produce similar output on a variety of different devices, such X displays, Postscript, etc.)

+

The following verbatim shows the front-end:

+
> mgr <- dbManager("Oracle")  
+> con <- dbConnect(mgr, user = "user", passwd = "passwd")
+> rs <- dbExecStatement(con, 
+          "select fld1, fld2, fld3 from MY_TABLE")
+> tbls <- fetch(rs, n = 100)
+> hasCompleted(rs)
+[1] T
+> close(rs)
+> rs <- dbExecStatement(con, 
+          "select id_name, q25, q50 from liv2")
+> res <- fetch(rs)
+> getRowCount(rs)
+[1] 73
+> close(con)
+

Such scripts should work with other RDBMS (say, MySQL) by replacing the first line with

+
> mgr <- dbManager("MySQL")
+
+

+Interface Classes

+

The following are the main RS-DBI classes. They need to be extended by individual database back-ends (MySQL, Oracle, etc.)

+
+
dbManager
+
+

Virtual class1 extended by actual database managers, e.g., Oracle, MySQL, Informix.

+
+
dbConnection
+
+

Virtual class that captures a connection to a database instance2.

+
+
dbResult
+
+

Virtual class that describes the result of an SQL statement.

+
+
dbResultSet
+
+

Virtual class, extends dbResult to fully describe the output of those statements that produce output records, i.e., SELECT (or SELECT-like) SQL statement.

+
+
+

All these classes should implement the methods show, describe, and getInfo:

+
+
show
+
+

(print in R) prints a one-line identification of the object.

+
+
describe
+
+

prints a short summary of the meta-data of the specified object (like summary in R/S).

+
+
getInfo
+
+

takes an object of one of the above classes and a string specifying a meta-data item, and it returns the corresponding information (NULL if unavailable).

+
> mgr <- dbManager("MySQL")
+> getInfo(mgr, "version")
+> con <- dbConnect(mgr, ...)
+> getInfo(con, "type")
+
+
+

The reason we implement the meta-data through getInfo in this way is to simplify the writing of database back-ends. We don’t want to overwhelm the developers of drivers (ourselves, most likely) with hundreds of methods as in the case of JDBC.

+

In addition, the following methods should also be implemented:

+
+
getDatabases
+
+

lists all available databases known to the dbManager.

+
+
getTables
+
+

lists tables in a database.

+
+
getTableFields
+
+

lists the fields in a table in a database.

+
+
getTableIndices
+
+

lists the indices defined for a table in a database.

+
+
+

These methods may be implemented using the appropriate getInfo method above.

+

In the next few sections we describe in detail each of these classes and their methods.

+
+

+Class dbManager +

+

This class identifies the relational database management system. It needs to be extended by individual back-ends (Oracle, PostgreSQL, etc.) The dbManager class defines the following methods:

+
+
load
+
+

initializes the driver code. We suggest having the generator, dbManager(driver), automatically load the driver.

+
+
unload
+
+

releases whatever resources the driver is using.

+
+
getVersion
+
+

returns the version of the RS-DBI currently implemented, plus any other relevant information about the implementation itself and the RDBMS being used.

+
+
+
+
+

+Class dbConnection +

+

This virtual class captures a connection to a RDBMS, and it provides access to dynamic SQL, result sets, RDBMS session management (transactions), etc. Note that the dbManager may or may not allow multiple simultaneous connections. The methods it defines include:

+
+
dbConnect
+
+

opens a connection to the database dbname. Other likely arguments include host, user, and password. It returns an object that extends dbConnection in a driver-specific manner (e.g., the MySQL implementation creates a connection of class MySQLConnection that extends dbConnection). Note that we could separate the steps of connecting to a RDBMS and opening a database there (i.e., opening an instance). For simplicity we do the 2 steps in this method. If the user needs to open another instance in the same RDBMS, just open a new connection.

+
+
close
+
+

closes the connection and discards all pending work.

+
+
dbExecStatement
+
+

submits one SQL statement. It returns a dbResult object, and in the case of a SELECT statement, the object also inherits from dbResultSet. This dbResultSet object is needed for fetching the output rows of SELECT statements. The result of a non-SELECT statement (e.g., UPDATE, DELETE, CREATE, ALTER, …) is defined as the number of rows affected (this seems to be common among RDBMS).

+
+
commit
+
+

commits pending transaction (optional).

+
+
rollback
+
+

undoes current transaction (optional).

+
+
callProc
+
+

invokes a stored procedure in the RDBMS (tentative). Stored procedures are not part of the ANSI SQL-92 standard and possibly vary substantially from one RDBMS to another. For instance, Oracle seems to have a fairly decent implementation of stored procedures, but MySQL currently does not support them.

+
+
dbExec
+
+

submit an SQL “script” (multiple statements). May be implemented by looping with dbExecStatement.

+
+
dbNextResultSet
+
+

When running SQL scripts (multiple statements), it closes the current result set in the dbConnection, executes the next statement and returns its result set.

+
+
+
+
+

+Class dbResult +

+

This virtual class describes the result of an SQL statement (any statement) and the state of the operation. Non-query statements (e.g., CREATE, UPDATE, DELETE) set the “completed” state to 1, while SELECT statements to 0. Error conditions set this slot to a negative number. The dbResult class defines the following methods:

+
+
getStatement
+
+

returns the SQL statement associated with the result set.

+
+
getDBConnection
+
+

returns the dbConnection associated with the result set.

+
+
getRowsAffected
+
+

returns the number of rows affected by the operation.

+
+
hasCompleted
+
+

was the operation completed? SELECT’s, for instance, are not completed until their output rows are all fetched.

+
+
getException
+
+

returns the status of the last SQL statement on a given connection as a list with two members, status code and status description.

+
+
+
+
+

+Class dbResultSet +

+

This virtual class extends dbResult, and it describes additional information from the result of a SELECT statement and the state of the operation. The completed state is set to 0 so long as there are pending rows to fetch. The dbResultSet class defines the following additional methods:

+
+
getRowCount
+
+

returns the number of rows fetched so far.

+
+
getNullOk
+
+

returns a logical vector with as many elements as there are fields in the result set, each element describing whether the corresponding field accepts NULL values.

+
+
getFields
+
+

describes the SELECTed fields. The description includes field names, RDBMS internal data types, internal length, internal precision and scale, null flag (i.e., column allows NULL’s), and corresponding S classes (which can be over-ridden with user-provided classes). The current MySQL and Oracle implementations define a dbResultSet as a named list with the following elements:

+
+
+connection:
+
+

the connection object associated with this result set;

+
+
+statement:
+
+

a string with the SQL statement being processed;

+
+
+description:
+
+

a field description data.frame with as many rows as there are fields in the SELECT output, and columns specifying the name, type, length, precision, scale, Sclass of the corresponding output field.

+
+
+rowsAffected:
+
+

the number of rows that were affected;

+
+
+rowCount:
+
+

the number of rows so far fetched;

+
+
+completed:
+
+

a logical value describing whether the operation has completed or not.

+
+
+nullOk:
+
+

a logical vector specifying whether the corresponding column may take NULL values.

+
+
+

The methods above are implemented as accessor functions to this list in the obvious way.

+
+
setDataMappings
+
+

defines a conversion between internal RDBMS data types and R/S classes. We expect the default mappings to be by far the most common ones, but users that need more control may specify a class generator for individual fields in the result set. (See Section [sec:mappings] for details.)

+
+
close
+
+

closes the result set and frees resources both in R/S and the RDBMS.

+
+
fetch
+
+

extracts the next max.rec records (-1 means all).

+
+
+
+
+
+

+Data Type Mappings

+

The data types supported by databases are slightly different than the data types in R and S, but the mapping between them is straightforward: Any of the many fixed and varying length character types are mapped to R/S character. Fixed-precision (non-IEEE) numbers are mapped into either doubles (numeric) or long (integer). Dates are mapped to character using the appropriate TO_CHAR function in the RDBMS (which should take care of any locale information). Some RDBMS support the type CURRENCY or MONEY which should be mapped to numeric. Large objects (character, binary, file, etc.) also need to be mapped. User-defined functions may be specified to do the actual conversion as follows:

+
    +
  1. +

    run the query (either with dbExec or dbExecStatement):

    +
    > rs <- dbExecStatement(con, "select whatever-You-need")
    +
  2. +
  3. +

    extract the output field definitions

    +
    > flds <- getFields(rs)
    +
  4. +
  5. +

    replace the class generator in the, say 3rd field, by the user own generator:

    +
    > flds[3, "Sclass"]            # default mapping
    +[1] "character"
    +

    by

    +
    > flds[3, "Sclass"] <- "myOwnGeneratorFunction"
    +
  6. +
  7. +

    set the new data mapping prior to fetching

    +
    > setDataMappings(resutlSet, flds)
    +
  8. +
  9. +

    fetch the rows and store in a data.frame

    +
    > data <- fetch(resultSet)
    +
  10. +
+
+
+

+Open Issues

+

We may need to provide some additional utilities, for instance to convert dates, to escape characters such as quotes and slashes in query strings, to strip excessive blanks from some character fields, etc. We need to decide whether we provide hooks so these conversions are done at the C level, or do all the post-processing in R or S.

+

Another issue is what kind of data object is the output of an SQL query. Currently the MySQL and Oracle implementations return data as a data.frame; data frames have the slight inconvenience that they automatically re-label the fields according to R/S syntax, changing the actual RDBMS labels of the variables; the issue of non-numeric data being coerced into factors automatically “at the drop of a hat” (as someone in s-news wrote) is also annoying.

+

The execution of SQL scripts is not fully described. The method that executes scripts could run individual statements without returning until it encounters a query (SELECT-like) statement. At that point it could return that one result set. The application is then responsible for fetching these rows, and then for invoking dbNextResultSet on the opened dbConnection object to repeat the dbExec/fetch loop until it encounters the next dbResultSet. And so on. Another (potentially very expensive) alternative would be to run all statements sequentially and return a list of data.frames, each element of the list storing the result of each statement.

+

Binary objects and large objects present some challenges both to R and S. It is becoming more common to store images, sounds, and other data types as binary objects in RDBMS, some of which can be in principle quite large. The SQL-92 ANSI standard allows up to 2 gigabytes for some of these objects. We need to carefully plan how to deal with binary objects – perhaps tentatively not in full generality. Large objects could be fetched by repeatedly invoking a specified R/S function that takes as argument chunks of a specified number of raw bytes. In the case of S4 (and Splus5.x) the RS-DBI implementation can write into an opened connection for which the user has defined a reader (but can we guarantee that we won’t overflow the connection?). In the case of R it is not clear what data type binary large objects (BLOB) should be mapped into.

+
+
+

+Limitations

+

These are some of the limitations of the current interface definition:

+
    +
  • we only allow one SQL statement at a time, forcing users to split SQL scripts into individual statements;

  • +
  • transaction management is not fully described;

  • +
  • +

    the interface is heavily biased towards queries, as opposed to general purpose database development. In particular we made no attempt to define “bind variables”; this is a mechanism by which the contents of S objects are implicitly moved to the database during SQL execution. For instance, the following embedded SQL statement

    +
      /* SQL */
    +  SELECT * from emp_table where emp_id = :sampleEmployee
    +

    would take the vector sampleEmployee and iterate over each of its elements to get the result. Perhaps RS-DBI could at some point in the future implement this feature.

    +
  • +
+
+
+
+

+Other Approaches

+

The high-level, front-end description of RS-DBI is the more critical aspect of the interface. Details on how to actually implement this interface may change over time. The approach described in this document based on one back-end driver per RDBMS is reasonable, but not the only approach – we simply felt that a simpler approach based on well-understood and self-contained tools (R, S, and C API’s) would be a better start. Nevertheless we want to briefly mention a few alternatives that we considered and tentatively decided against, but may quite possibly re-visit in the near future.

+
+

+Open Database Connectivity (ODBC)

+

The ODBC protocol was developed by Microsoft to allow connectivity among C/C++ applications and RDBMS. As you would expect, originally implementations of the ODBC were only available under Windows environments. There are various effort to create a Unix implementation (see the Unix ODBC web-site and Harvey (1999)). This approach looks promising because it allows us to write only one back-end, instead of one per RDBMS. Since most RDBMS already provide ODBC drivers, this could greatly simplify development. Unfortunately, the Unix implementation of ODBC was not mature enough at the time we looked at it, a situation we expect will change in the next year or so. At that point we will need to re-evaluate it to make sure that such an ODBC interface does not penalize the interface in terms of performance, ease of use, portability among the various Unix versions, etc.

+
+
+

+Java Database Connectivity (JDBC)

+

Another protocol, the Java database connectivity, is very well-done and supported by just about every RDBMS. The issue with JDBC is that as of today neither S nor R (which are written in C) interfaces cleanly with Java. There are several efforts (some in a quite fairly advanced state) to allow S and R to invoke Java methods. Once this interface is widely available in Splus5x and R we will need to re-visit this issue again and study the performance, usability, etc., of JDBC as a common back-end to the RS-DBI.

+
+
+

+CORBA and a 3-tier Architecture

+

Yet another approach is to move the interface to RDBMS out of R and S altogether into a separate system or server that would serve as a proxy between R/S and databases. The communication to this middle-layer proxy could be done through CORBA (John M. Chambers et al. 1998, Siegel (1996)), Java’s RMI, or some other similar technology. Such a design could be very flexible, but the CORBA facilities both in R and S are not widely available yet, and we do not know whether this will be made available to Splus5 users from MathSoft. Also, my experience with this technology is rather limited.

+

On the other hand, this 3-tier architecture seem to offer the most flexibility to cope with very large distributed databases, not necessarily relational.

+
+
+
+

+Resources

+

The latest documentation and software on the RS-DBI was available at www.omegahat.net (link dead now: http://www.omegahat.net/contrib/RS-DBI/index.html). The R community has developed interfaces to some databases: RmSQL is an interface to the mSQL database written by Torsten Hothorn; RPgSQL is an interface to PostgreSQL and was written by Timothy H. Keitt; RODBC is an interface to ODBC, and it was written by Michael Lapsley. (For more details on all these see (R Data Import/Export 2001).)

+

The are R and S-Plus interfaces to MySQL that follow the propose RS-DBI API described here; also, there’s an S-Plus interface SOracle James (In preparation) to Oracle (we expect to have an R implementation soon.)

+

The idea of a common interface to databases has been successfully implemented in Java’s Database Connectivity (JDBC) (www.javasoft.com), in C through the Open Database Connectivity (ODBC) (www.unixodbc.org), in Python’s Database Application Programming Interface (www.python.org), and in Perl’s Database Interface (www.cpan.org).

+
+
+

+Acknowledgements

+

The R/S database interface came about from suggestions, comments, and discussions with John M. Chambers and Duncan Temple Lang in the context of the Omega Project for Statistical Computing. Doug Bates and Saikat DebRoy ported (and greatly improved) the first MySQL implementation to R.

+
+
+

+The S Version 4 Definitions

+

The following code is meant to serve as a detailed description of the R/S to database interface. We decided to use S4 (instead of R or S version 3) because its clean syntax help us to describe easily the classes and methods that form the RS-DBI, and also to convey the inter-class relationships.

+
## Define all the classes and methods to be used by an
+## implementation of the RS-DataBase Interface.  Mostly, 
+## these classes are virtual and each driver should extend
+## them to provide the actual implementation.
+
+## Class: dbManager 
+## This class identifies the DataBase Management System
+## (Oracle, MySQL, Informix, PostgreSQL, etc.)
+
+setClass("dbManager", VIRTUAL)
+
+setGeneric("load", 
+   def = function(dbMgr,...) 
+   standardGeneric("load")
+   )
+setGeneric("unload", 
+   def = function(dbMgr,...)
+   standardGeneric("unload")
+   )
+setGeneric("getVersion", 
+   def = function(dbMgr,...) 
+   standardGeneric("getVersion")
+   )
+
+## Class: dbConnections 
+## This class captures a connection to a database instance. 
+
+setClass("dbConnection", VIRTUAL)
+
+setGeneric("dbConnection", 
+   def = function(dbMgr, ...) 
+   standardGeneric("dbConnection")
+   )
+setGeneric("dbConnect", 
+   def = function(dbMgr, ...) 
+   standardGeneric("dbConnect")
+   )
+setGeneric("dbExecStatement", 
+   def = function(con, statement, ...)
+   standardGeneric("dbExecStatement")
+   )
+setGeneric("dbExec", 
+   def = function(con, statement, ...) 
+   standardGeneric("dbExec")
+   )
+setGeneric("getResultSet", 
+   def = function(con, ..) 
+   standardGeneric("getResultSet")
+   )
+setGeneric("commit", 
+   def = function(con, ...) 
+   standardGeneric("commit")
+   )
+setGeneric("rollback", 
+   def = function(con, ...) 
+   standardGeneric("rollback")
+   )
+setGeneric("callProc", 
+   def = function(con, ...) 
+   standardGeneric("callProc")
+   )
+setMethod("close", 
+   signature = list(con="dbConnection", type="missing"),
+   def = function(con, type) NULL
+   )
+
+## Class: dbResult
+## This is a base class for arbitrary results from the RDBMS 
+## (INSERT, UPDATE, DELETE).  SELECTs (and SELECT-like) 
+## statements produce "dbResultSet" objects, which extend 
+## dbResult.
+
+setClass("dbResult", VIRTUAL)
+
+setMethod("close", 
+   signature = list(con="dbResult", type="missing"),
+   def = function(con, type) NULL
+   )
+
+## Class: dbResultSet
+## Note that we define a resultSet as the result of a 
+## SELECT  SQL statement.
+
+setClass("dbResultSet", "dbResult")
+
+setGeneric("fetch", 
+   def = function(resultSet,n,...) 
+   standardGeneric("fetch")
+   )
+setGeneric("hasCompleted",
+   def = function(object, ...) 
+   standardGeneric("hasCompleted")
+   )
+setGeneric("getException",
+   def = function(object, ...) 
+   standardGeneric("getException")
+   )
+setGeneric("getDBconnection",
+   def = function(object, ...) 
+   standardGeneric("getDBconnection")
+   )
+setGeneric("setDataMappings", 
+   def = function(resultSet, ...) 
+   standardGeneric("setDataMappings")
+   )
+setGeneric("getFields",
+   def = function(object, table, dbname,  ...) 
+   standardGeneric("getFields")
+   )
+setGeneric("getStatement", 
+   def = function(object, ...) 
+   standardGeneric("getStatement")
+   )
+setGeneric("getRowsAffected",
+   def = function(object, ...) 
+   standardGeneric("getRowsAffected")
+   )
+setGeneric("getRowCount",
+   def = function(object, ...) 
+   standardGeneric("getRowCount")
+   )
+setGeneric("getNullOk",
+   def = function(object, ...) 
+   standardGeneric("getNullOk")
+   )
+
+## Meta-data: 
+setGeneric("getInfo", 
+   def = function(object, ...) 
+   standardGeneric("getInfo")
+   )
+setGeneric("describe", 
+   def = function(object, verbose=F, ...)
+   standardGeneric("describe")
+   )
+setGeneric("getCurrentDatabase",
+   def = function(object, ...)
+   standardGeneric("getCurrentDatabase")
+   )
+setGeneric("getDatabases", 
+   def = function(object, ...)
+   standardGeneric("getDatabases")
+   )
+setGeneric("getTables", 
+   def = function(object, dbname, ...)
+   standardGeneric("getTables")
+   )
+setGeneric("getTableFields", 
+   def = function(object, table, dbname, ...)
+   standardGeneric("getTableFields")
+   )
+setGeneric("getTableIndices", 
+   def = function(object, table, dbname, ...) 
+   standardGeneric("getTableIndices")
+   )
+
+
+

Chambers, J. M. 1998. Programming with Data: A Guide to the S Language. New York: Springer.

+
+
+

Chambers, John M., Mark H. Hansen, David A. James, and Duncan Temple Lang. 1998. “Distributed Computing with Data: A CORBA-Based Approach.” In Computing Science and Statistics. Inteface Foundation of North America.

+
+
+

Harvey, Peter. 1999. “Open Database Connectivity.” Linux Journal Nov. (67): 68–72.

+
+
+

James, David A. In preparation. “An R/S Interface to the Oracle Database.” www.omegahat.org: Bell Labs, Lucent Technologies.

+
+
+

R Data Import/Export. 2001. R-Development Core Team.

+
+
+

Siegel, Jon. 1996. CORBA Fundamentals and Programming. New York: Wiley.

+
+
+

Temple Lang, Duncan. 2000. “The Omegahat Environment: New Possibilities for Statistical Computing.” Journal of Computational and Graphical Statistics to appear.

+
+
+

Using Relational Database Systems with R. 2000. R-Developemt Core Team.

+
+
+

X/Open CAE Specification: SQL and RDA. 1994. Reading, UK: X/Open Company Ltd.

+
+
+
+
+
+
    +
  1. A virtual class allows us to group classes that share some common functionality, e.g., the virtual class “dbConnection” groups all the connection implementations by Informix, Ingres, DB/2, Oracle, etc. Although the details will vary from one RDBMS to another, the defining characteristic of these objects is what a virtual class captures. R and S version 3 do not explicitly define virtual classes, but they can easily implement the idea through inheritance.

  2. +
  3. The term “database” is sometimes (confusingly) used both to denote the RDBMS, such as Oracle, MySQL, and also to denote a particular database instance under a RDBMS, such as “opto” or “sales” databases under the same RDBMS.

  4. +
+
+
+
+ + + +
+ + +
+ +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/articles/backend.html b/docs/articles/backend.html new file mode 100644 index 000000000..7962a3106 --- /dev/null +++ b/docs/articles/backend.html @@ -0,0 +1,301 @@ + + + + + + + +Implementing a new backend • DBI + + + + + + +
+
+ + + +
+
+ + + + +
+

The goal of this document is to help you implement a new backend for DBI.

+

If you are writing a package that connects a database to R, I highly recommend that you make it DBI compatible because it makes your life easier by spelling out exactly what you need to do. The consistent interface provided by DBI makes it easier for you to implement the package (because you have fewer arbitrary choices to make), and easier for your users (because it follows a familiar pattern). In addition, the DBItest package provides test cases which you can easily incorporate in your package.

+

I’ll illustrate the process using a fictional database called Kazam.

+
+

+Getting started

+

Start by creating a package. It’s up to you what to call the package, but following the existing pattern of RSQLite, RMySQL, RPostgres and ROracle will make it easier for people to find it. For this example, I’ll call my package RKazam.

+

In your DESCRIPTION, make sure to include:

+
Imports:
+  DBI (>= 0.3.0),
+  methods
+Suggests:
+  DBItest, testthat
+

Importing DBI is fine, because your users are not supposed to attach your package anyway; the preferred method is to attach DBI and use explicit qualification via :: to access the driver in your package (which needs to be done only once).

+
+
+

+Testing

+

Why testing at this early stage? Because testing should be an integral part of the software development cycle. Test right from the start, add automated tests as you go, finish faster (because tests are automated) while maintaining superb code quality (because tests also check corner cases that you might not be aware of). Don’t worry: if some test cases are difficult or impossible to satisfy, or take too long to run, you can just turn them off.

+

Take the time now to head over to the DBItest vignette. You will find a vast amount of ready-to-use test cases that will help you in the process of implementing your new DBI backend.

+
vignette("test", package = "DBItest")
+

Add custom tests that are not covered by DBItest at your discretion, or enhance DBItest and file a pull request if the test is generic enough to be useful for many DBI backends.

+
+
+

+Driver

+

Start by making a driver class which inherits from DBIDriver. This class doesn’t need to do anything, it’s just used to dispatch other generics to the right method. Users don’t need to know about this, so you can remove it from the default help listing with @keywords internal:

+
#' Driver for Kazam database.
+#' 
+#' @keywords internal
+#' @export
+#' @import DBI
+#' @import methods
+setClass("KazamDriver", contains = "DBIDriver")
+

The driver class was more important in older versions of DBI, so you should also provide a dummy dbUnloadDriver() method.

+
#' @export
+#' @rdname Kazam-class
+setMethod("dbUnloadDriver", "KazamDriver", function(drv, ...) {
+  TRUE
+})
+#> [1] "dbUnloadDriver"
+

If your package needs global setup or tear down, do this in the .onLoad() and .onUnload() functions.

+

You might also want to add a show method so the object prints nicely:

+
setMethod("show", "KazamDriver", function(object) {
+  cat("<KazamDriver>\n")
+})
+#> [1] "show"
+

Next create Kazam() which instantiates this class.

+
#' @export
+Kazam <- function() {
+  new("KazamDriver")
+}
+
+Kazam()
+#> <KazamDriver>
+
+
+

+Connection

+

Next create a connection class that inherits from DBIConnection. This should store all the information needed to connect to the database. If you’re talking to a C api, this will include a slot that holds an external pointer.

+
#' Kazam connection class.
+#' 
+#' @export
+#' @keywords internal
+setClass("KazamConnection", 
+  contains = "DBIConnection", 
+  slots = list(
+    host = "character", 
+    username = "character", 
+    # and so on
+    ptr = "externalptr"
+  )
+)
+

Now you have some of the boilerplate out of the way, you can start work on the connection. The most important method here is dbConnect() which allows you to connect to a specified instance of the database. Note the use of @rdname Kazam. This ensures that Kazam() and the connect method are documented together.

+
#' @param drv An object created by \code{Kazam()} 
+#' @rdname Kazam
+#' @export
+#' @examples
+#' \dontrun{
+#' db <- dbConnect(RKazam::Kazam())
+#' dbWriteTable(db, "mtcars", mtcars)
+#' dbGetQuery(db, "SELECT * FROM mtcars WHERE cyl == 4")
+#' }
+setMethod("dbConnect", "KazamDriver", function(drv, ...) {
+  # ...
+  
+  new("KazamConnection", host = host, ...)
+})
+#> [1] "dbConnect"
+
    +
  • Replace ... with the arguments needed to connect to your database. You’ll always need to include ... in the arguments, even if you don’t use it, for compatibility with the generic.

  • +
  • This is likely to be where people first come for help, so the examples should show how to connect to the database, and how to query it. (Obviously these examples won’t work yet.) Ideally, include examples that can be run right away (perhaps relying on a publicly hosted database), but failing that surround in \dontrun{} so people can at least see the code.

  • +
+

Next, implement show() and dbDisconnect() methods.

+
+
+

+Results

+

Finally, you’re ready to implement the meat of the system: fetching results of a query into a data frame. First define a results class:

+
#' Kazam results class.
+#' 
+#' @keywords internal
+#' @export
+setClass("KazamResult", 
+  contains = "DBIResult",
+  slots = list(ptr = "externalptr")
+)
+

Then write a dbSendQuery() method. This takes a connection and SQL string as arguments, and returns a result object. Again ... is needed for compatibility with the generic, but you can add other arguments if you need them.

+
#' Send a query to Kazam.
+#' 
+#' @export
+#' @examples 
+#' # This is another good place to put examples
+setMethod("dbSendQuery", "KazamConnection", function(conn, statement, ...) {
+  # some code
+  new("KazamResult", ...)
+})
+#> [1] "dbSendQuery"
+

Next, implement dbClearResult(), which should close the result set and free all resources associated with it:

+
#' @export
+setMethod("dbClearResult", "KazamResult", function(res, ...) {
+  # free resources
+  TRUE
+})
+#> [1] "dbClearResult"
+

The hardest part of every DBI package is writing the dbFetch() method. This needs to take a result set and (optionally) number of records to return, and create a dataframe. Mapping R’s data types to those of your database may require a custom implementation of the dbDataType() method for your connection class:

+
#' Retrieve records from Kazam query
+#' @export
+setMethod("dbFetch", "KazamResult", function(res, n = -1, ...) {
+  ...
+})
+#> [1] "dbFetch"
+
+# (optionally)
+
+#' Find the database data type associated with an R object
+#' @export
+setMethod("dbDataType", "KazamConnection", function(dbObj, obj, ...) {
+  ...
+})
+#> [1] "dbDataType"
+

Next, implement dbHasCompleted() which should return a logical indicating if there are any rows remaining to be fetched.

+
#' @export
+setMethod("dbHasCompleted", "KazamResult", function(res, ...) { 
+  
+})
+#> [1] "dbHasCompleted"
+

With these four methods in place, you can now use the default dbGetQuery() to send a query to the database, retrieve results if available and then clean up. Spend some time now making sure this works with an existing database, or relax and let the DBItest package do the work for you.

+
+
+

+SQL methods

+

You’re now on the home stretch, and can make your wrapper substantially more useful by implementing methods that wrap around variations in SQL across databases:

+
    +
  • dbQuoteString() and dbQuoteIdentifer() are used to safely quote strings and identifiers to avoid SQL injection attacks. Note that the former must be vectorized, but not the latter.

  • +
  • dbWriteTable() creates a database table given an R dataframe. I’d recommend using the functions prefixed with sql in this package to generate the SQL. These functions are still a work in progress so please let me know if you have problems.

  • +
  • dbReadTable(): a simple wrapper around SELECT * FROM table. Use dbQuoteIdentifer() to safely quote the table name and prevent mismatches between the names allowed by R and the database.

  • +
  • dbListTables() and dbExistsTable() let you determine what tables are available. If not provided by your database’s API, you may need to generate sql that inspects the system tables.

  • +
  • dbListFields() shows which fields are available in a given table.

  • +
  • dbRemoveTable() wraps around DROP TABLE. Start with SQL::sqlTableDrop().

  • +
  • dbBegin(), dbCommit() and dbRollback(): implement these three functions to provide basic transaction support. This functionality is currently not tested in the DBItest package.

  • +
+
+
+

+Metadata methods

+

There are a lot of extra metadata methods for result sets (and one for the connection) that you might want to implement. They are described in the following.

+
    +
  • dbIsValid() returns if a connection or a result set is open (TRUE) or closed (FALSE). All further methods in this section are valid for result sets only.

  • +
  • dbGetStatement() returns the issued query as a character value.

  • +
  • dbColumnInfo() lists the names and types of the result set’s columns.

  • +
  • dbGetRowCount() and dbGetRowsAffected() returns the number of rows returned or altered in a SELECT or INSERT/UPDATE query, respectively.

  • +
  • dbBind() allows using parametrised queries. Take a look at sqlInterpolate() and sqlParseVariables() if your SQL engine doesn’t offer native parametrised queries.

  • +
+
+
+

+Full DBI compliance

+

By now, your package should implement all methods defined in the DBI specification. If you want to walk the extra mile, offer a read-only mode that allows your users to be sure that their valuable data doesn’t get destroyed inadvertently.

+
+
+
+ + + +
+ + +
+ +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/articles/biblio.bib b/docs/articles/biblio.bib new file mode 100644 index 000000000..ecf526dc0 --- /dev/null +++ b/docs/articles/biblio.bib @@ -0,0 +1,295 @@ +@string{jcgs="Journal of Computational and Graphical Statistics"} +@inproceedings{s-corba.98, + author = "Chambers, John M. and Hansen, Mark H. and James, David A. and Temple Lang, Duncan", + title = "Distributed Computing with Data: A CORBA-based Approach", + booktitle = "Computing Science and Statistics", + year = 1998, + organization = "Inteface Foundation of North America" +} + +@book{S.88, + author = "Becker, R. A. and Chambers, J. M. and Wilks, A. R", + year = "1988", + title = "The New S Language", + publisher = "Wadsworth", + address = "Pacific Grove, California" +} +@book{S.92, + editor = "Chambers, J. M. and Hastie, T.", + year = 1992, + title = "Statistical Models in S", + publisher = "Wadsworth", + address = "Pacific Grove, California" +} +@book{S4, + author = "Chambers, J. M.", + title = "Programming with Data: A Guide to the S Language", + publisher = "Springer", + address = "New York", + year = 1998 +} +@article{R.96, + author = "Ihaka, Ross and Gentleman, Robert", + title = "R: A Language for Data Analysis and Graphics", + journal = jcgs, + volume = 5, + number = 3, + year = 1996, + pages = "299-314" +} +@book{corba:siegel.96, + author = "Siegel, Jon", + title = "CORBA Fundamentals and Programming", + publisher = "Wiley", + address = "New York", + year = 1996 +} +@book{pvm, + title = "PVM: Parallel Virtual Machine. A User's Guide and + Tutorial for Networked Parallel Computing", + author="Geist, A. and Beguelin, A. and Dongarra, J. and + Jiang, W. and Mancheck, R. and Sunderam, V.", + year = 1994, + publisher = "MIT Press", + address = "Cambridge, MA" +} +@manual{splus, + title = "S-PLUS Software Documentation", + key = "S-PLUS", + organization = "StatSci Division of MathSoft Inc.", + note = "Version 3.3", + year = 1995, + address = "Seattle, WA", +} +@book{tierney.90, + author = "Tierney, Luke", + year = 1990, + title = "LISP-STAT: An Object-Oriented Environment for Statistical + Computing and Dynamic Graphics", + publisher = "Wiley", + address = "New York" +} +@article{tierney.96, + author = "Tierney, Luke", + title = "Recent Development and Future Directions in {LispStat}", + journal = jcgs, + volume = 5, + number = 3, + year = 1996, + pages = "250-262" +} + +@article{odbc.lj, + author = "Harvey, Peter", + title = "{Open Database Connectivity}", + journal = "{Linux Journal}", + year = 1999, + volume = "Nov.", + number = 67, + pages = "68-72" +} +@article{duncan2000, + author = "Temple Lang, Duncan", + title = "{The Omegahat Environment: New Possibilities for Statistical Computing}", + journal = jcgs, + volume = "to appear", + year = 2000, + number = "" +} + +@manual{sql92, + title = "{X/Open CAE Specification: SQL and RDA}", + organization = "X/Open Company Ltd.", + address = "Reading, UK", + year = 1994 +} + +@book{MySQL, + author = "DuBois, Paul", + title = "{MySQL}", + publisher = "New Riders Publishing", + year = 2000 +} +@manual{R.ext, + title = "Writing {R} Extensions", + organization = "{R} Development Core Team", + note = "Version 1.2.1 (2001-01-15)", + year = 2001 +} +@manual{R.imp-exp, + title = "{R} Data Import/Export", + organization = "R-Development Core Team", + note = "Version 1.2.1 (2001-01-15)", + year = 2001 +} +@manual{R-dbms, + title = "Using Relational Database Systems with {R}", + organization = "R-Developemt Core Team", + note = "Draft", + year = 2000 +} +@manual{bates.mysql, + title = "Using Relational Database Systems with {R}", + organization = "R-Developemt Core Team", + note = "Draft", + year = 2000 +} +@techreport{proxyDBMS, + author = "James, David A.", + title = "Proxy Database Object in the S Language", + institution = "Bell Labs, Lucent Technologies", + year = "In preparation" +} +@techreport{RS-DBI, + author = "James, David A.", + title = "A Common Interface to Relational Database Management Sysmtems from +{R} and {S} --- A Proposal", + institution = "Bell Labs, Lucent Technologies", + year = "2000", + address = "www.omegahat.org" +} +@techreport{RS-MySQL, + author = "James, David A.", + title = "An {R}/{S} Interface to the {MySQL} Database", + institution = "Bell Labs, Lucent Technologies", + year = "2001", + address = "www.omegahat.org" +} +@techreport{RS-Oracle, + author = "James, David A.", + title = "An {R}/{S} Interface to the {Oracle} Database", + institution = "Bell Labs, Lucent Technologies", + year = "In preparation", + address = "www.omegahat.org" +} + +@manual{r-data-imp:2001, + author = {R Development Core Team}, + title = {R Data Import/Export}, + year = {2001}, + address = {\url{http://www.r-project.org}} +} + +@manual{mysql:2000, + author = "Axmark, David and Widenius, Michael and Cole, Jeremy and DuBois, Paul", + title = {MySQL Reference Manual}, + year = {2001}, + address = {\url{http://www.mysql.com/documentation/mysql}} +} + +@manual{jdbc:2000, + author = "Ellis, Jon and Ho, Linda and Fisher, Maydene", + title = {JDBC 3.0 Specification}, + organization = {Sun Microsystems, Inc}, + year = {2000}, + address = {\url{http://java.sun.com/Download4}} +} + + +@article{using-data:2001, + author = "Ripley, Brian D.", + title = {Using Databases with {R}}, + journal = {R {N}ews}, + year = {2001}, + month = {January}, + volume = {1}, + number = {1}, + pages = {18--20}, + address = {\url{http://www.r-project.org/doc/Rnews/}} +} + + +@Manual{odbc:2001, + title = {Microsoft {ODBC}}, + organization = {Microsoft Inc}, + address = {\url{http://www.microsoft.com/data/odbc/}}, + year = 2001 +} + + +@Book{PerlDBI:2000, + author = "Descartes, Alligator and Bunce, Tim", + title = {Programming the {P}erl {DBI}}, + publisher = {O'Reilly}, + year = 2000 +} + +@Book{Reese:2000, + author = "Reese, George", + title = {Database Programming with {JDBC} and {J}ava}, + publisher = {O'Reilly}, + year = 2000, + edition = {second} +} + +@book{Xopen-sql, + author = {X/Open Company Ltd.}, + title = {X/Open SQL and RDA Specification}, + publisher = {X/Open Company Ltd.}, + year = 1994 +} +@book{mysql-dubois, + author = "DuBois, Paul", + title = {MySQL}, + publisher = {New Riders}, + year = 2000 +} + +@techreport{data-management:1991, + author = "Chambers, John M.", + title = {Data Management in {S}}, + institution = {Bell Labs, Lucent Technologies}, + year = 1991 +} + +@techreport{database-classes:1999, + author = "Chambers, John M.", + title = {Database Classes}, + institution = {Bell Labs, Lucent Technologies}, + year = 1998 +} + +@inproceedings{R-dcom, + author = "Neuwirth, Erich and Baier, Thomas", + title = {Embedding {R} in Standard Software, and the other way around}, + organization = {Vienna University of Technology}, + year = 2001, + booktitle = {Proceedings of the Distributed Statistical Computing 2001 Workshop}, + address = {\url{http://www.ci.tuwien.ac.at/Conferences/DSC-2001}} +} + +@inproceedings{R-tcltk, + author = "Dalgaard, Peter", + title = {The {R}-{T}cl/{T}k Interface}, + organization = {Vienna University of Technology}, + year = 2001, + booktitle = {Proceedings of the Distributed Statistical Computing 2001 Workshop}, + address = {\url{http://www.ci.tuwien.ac.at/Conferences/DSC-2001}} +} + +@inproceedings{duncan-dsc2001, + author = "Temple Lang, Duncan", + title = {Embedding {S} in Other Languages and Environments}, + organization = {Vienna University of Technology}, + year = 2001, + booktitle = {Proceedings of the Distributed Statistical Computing 2001 Workshop}, + address = {\url{http://www.ci.tuwien.ac.at/Conferences/DSC-2001}} +} + +@inproceedings{BDR-RMR, + author = "Ripley, B. D. and Ripley, R. M.", + title = {Applications of {R} Clients and Servers}, + organization = {Vienna University of Technology}, + year = 2001, + booktitle = {Proceedings of the Distributed Statistical Computing 2001 Workshop}, + address = {\url{http://www.ci.tuwien.ac.at/Conferences/DSC-2001}} +} +@inproceedings{rsdbi-dsc2001, + author = "Hothorn, Torsten and James, David A. and Ripley, Brian D.", + title = {{R}/{S} Interfaces to Databases}, + organization = {Vienna University of Technology}, + year = 2001, + booktitle = {Proceedings of the Distributed Statistical Computing 2001 Workshop}, + address = {\url{http://www.ci.tuwien.ac.at/Conferences/DSC-2001}} +} + diff --git a/docs/articles/hierarchy.png b/docs/articles/hierarchy.png new file mode 100644 index 0000000000000000000000000000000000000000..cf043df037ca8030a748bcbe234a2d9007b26913 GIT binary patch literal 75565 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 + + + + + + + +Articles • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + +
+ + +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/articles/spec.html b/docs/articles/spec.html new file mode 100644 index 000000000..a5e4ea100 --- /dev/null +++ b/docs/articles/spec.html @@ -0,0 +1,2785 @@ + + + + + + + +DBI specification • DBI + + + + + + +
+
+ + + +
+
+ + + +
+

Abstract

+

The DBI package defines the generic DataBase Interface for R. The connection to individual DBMS is provided by other packages that import DBI (so-called DBI backends). This document formalizes the behavior expected by the methods declared in DBI and implemented by the individual backends. To ensure maximum portability and exchangeability, and to reduce the effort for implementing a new DBI backend, the DBItest package defines a comprehensive set of test cases that test conformance to the DBI specification. This document is derived from comments in the test definitions of the DBItest package. Any extensions or updates to the tests will be reflected in this document.

+
+ +
+ +

+DBI: R Database Interface +

+

+DBI defines an interface for communication between R and relational database management systems. All classes in this package are virtual and need to be extended by the various R/DBMS implementations (so-called DBI backends). +

+

+Definition +

+

+A DBI backend is an R package which imports the DBI and methods packages. For better or worse, the names of many existing backends start with ‘R’, e.g., RSQLite, RMySQL, RSQLServer; it is up to the backend author to adopt this convention or not. +

+

+DBI classes and methods +

+

+A backend defines three classes, which are subclasses of DBIDriver, DBIConnection, and DBIResult. The backend provides implementation for all methods of these base classes that are defined but not implemented by DBI. All methods defined in DBI are reexported (so that the package can be used without having to attach DBI), and have an ellipsis in their formals for extensibility. +

+

+Construction of the DBIDriver object +

+

+The backend must support creation of an instance of its DBIDriver subclass with a constructor function. By default, its name is the package name without the leading ‘R’ (if it exists), e.g., SQLite for the RSQLite package. However, backend authors may choose a different name. The constructor must be exported, and it must be a function that is callable without arguments. DBI recommends to define a constructor with an empty argument list. +

+

+Examples +

+
+RSQLite::SQLite()
+
+ + +

+Determine the SQL data type of an object +

+

+This section describes the behavior of the following method: +

+
+dbDataType(dbObj, obj, ...)
+
+

+Description +

+

+Returns an SQL string that describes the SQL data type to be used for an object. The default implementation of this generic determines the SQL type of an R object according to the SQL 92 specification, which may serve as a starting point for driver implementations. DBI also provides an implementation for data.frame which will return a character vector giving the type for each column in the dataframe. +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbDataType(“DBIObject”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+dbObj + +

+A object inheriting from DBIDriver or DBIConnection +

+
+obj + +

+An R object whose SQL type we want to determine. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Details +

+

+The data types supported by databases are different than the data types in R, but the mapping between the primitive types is straightforward: +

+
    +
  • +

    +Any of the many fixed and varying length character types are mapped to character vectors +

    +
  • +
  • +

    +Fixed-precision (non-IEEE) numbers are mapped into either numeric or integer vectors. +

    +
  • +
+

+Notice that many DBMS do not follow IEEE arithmetic, so there are potential problems with under/overflows and loss of precision. +

+

+Value +

+

+dbDataType() returns the SQL type that corresponds to the obj argument as a non-empty character string. For data frames, a character vector with one element per column is returned. An error is raised for invalid values for the obj argument such as a NULL value. +

+

+Specification +

+

+The backend can override the dbDataType() generic for its driver class. +

+

+This generic expects an arbitrary object as second argument. To query the values returned by the default implementation, run example(dbDataType, package = “DBI”). If the backend needs to override this generic, it must accept all basic R data types as its second argument, namely logical, integer, numeric, character, dates (see Dates), date-time (see DateTimeClasses), and difftime. If the database supports blobs, this method also must accept lists of raw vectors, and blob::blob objects. As-is objects (i.e., wrapped by I()) must be supported and return the same results as their unwrapped counterparts. The SQL data type for factor and ordered is the same as for character. The behavior for other object types is not specified. +

+

+All data types returned by dbDataType() are usable in an SQL statement of the form “CREATE TABLE test (a …)”. +

+

+Examples +

+
+dbDataType(ANSI(), 1:5)
+dbDataType(ANSI(), 1)
+dbDataType(ANSI(), TRUE)
+dbDataType(ANSI(), Sys.Date())
+dbDataType(ANSI(), Sys.time())
+dbDataType(ANSI(), Sys.time() - as.POSIXct(Sys.Date()))
+dbDataType(ANSI(), c("x", "abc"))
+dbDataType(ANSI(), list(raw(10), raw(20)))
+dbDataType(ANSI(), I(3))
+
+dbDataType(ANSI(), iris)
+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbDataType(con, 1:5)
+dbDataType(con, 1)
+dbDataType(con, TRUE)
+dbDataType(con, Sys.Date())
+dbDataType(con, Sys.time())
+dbDataType(con, Sys.time() - as.POSIXct(Sys.Date()))
+dbDataType(con, c("x", "abc"))
+dbDataType(con, list(raw(10), raw(20)))
+dbDataType(con, I(3))
+
+dbDataType(con, iris)
+
+dbDisconnect(con)
+
+ + +

+Create a connection to a DBMS +

+

+This section describes the behavior of the following method: +

+
+dbConnect(drv, ...)
+
+

+Description +

+

+Connect to a DBMS going through the appropriate authentication procedure. Some implementations may allow you to have multiple connections open, so you may invoke this function repeatedly assigning its output to different objects. The authentication mechanism is left unspecified, so check the documentation of individual drivers for details. +

+

+Arguments +

+ + + + + + + + + +
+drv + +

+an object that inherits from DBIDriver, or an existing DBIConnection object (in order to clone an existing connection). +

+
+ + +

+authentication arguments needed by the DBMS instance; these typically include user, password, host, port, dbname, etc. For details see the appropriate DBIDriver. +

+
+

+Value +

+

+dbConnect() returns an S4 object that inherits from DBIConnection. This object is used to communicate with the database engine. +

+

+Specification +

+

+DBI recommends using the following argument names for authentication parameters, with NULL default: +

+
    +
  • +

    +user for the user name (default: current user) +

    +
  • +
  • +

    +password for the password +

    +
  • +
  • +

    +host for the host name (default: local connection) +

    +
  • +
  • +

    +port for the port number (default: local connection) +

    +
  • +
  • +

    +dbname for the name of the database on the host, or the database file name +

    +
  • +
+

+The defaults should provide reasonable behavior, in particular a local connection for host = NULL. For some DBMS (e.g., PostgreSQL), this is different to a TCP/IP connection to localhost. +

+

+Examples +

+
+# SQLite only needs a path to the database. (Here, ":memory:" is a special
+# path that creates an in-memory database.) Other database drivers
+# will require more details (like user, password, host, port, etc.)
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+con
+
+dbListTables(con)
+
+dbDisconnect(con)
+
+ + +

+Disconnect (close) a connection +

+

+This section describes the behavior of the following method: +

+
+dbDisconnect(conn, ...)
+
+

+Description +

+

+This closes the connection, discards all pending work, and frees resources (e.g., memory, sockets). +

+

+Arguments +

+ + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Value +

+

+dbDisconnect() returns TRUE, invisibly. +

+

+Specification +

+

+A warning is issued on garbage collection when a connection has been released without calling dbDisconnect(), but this cannot be tested automatically. A warning is issued immediately when calling dbDisconnect() on an already disconnected or invalid connection. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+dbDisconnect(con)
+
+ + +

+Execute a query on a given database connection +

+

+This section describes the behavior of the following method: +

+
+dbSendQuery(conn, statement, ...)
+
+

+Description +

+

+The dbSendQuery() method only submits and synchronously executes the SQL query to the database engine. It does not extract any records — for that you need to use the dbFetch() method, and then you must call dbClearResult() when you finish fetching the records you need. For interactive use, you should almost always prefer dbGetQuery(). +

+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+statement + +

+a character string containing SQL. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Details +

+

+This method is for SELECT queries only. Some backends may support data manipulation queries through this method for compatibility reasons. However, callers are strongly encouraged to use dbSendStatement() for data manipulation statements. +

+

+The query is submitted to the database server and the DBMS executes it, possibly generating vast amounts of data. Where these data live is driver-specific: some drivers may choose to leave the output on the server and transfer them piecemeal to R, others may transfer all the data to the client – but not necessarily to the memory that R manages. See individual drivers’ dbSendQuery() documentation for details. +

+

+Value +

+

+dbSendQuery() returns an S4 object that inherits from DBIResult. The result set can be used with dbFetch() to extract records. Once you have finished using a result, make sure to clear it with dbClearResult(). An error is raised when issuing a query over a closed or invalid connection, if the syntax of the query is invalid, or if the query is not a non-NA string. +

+

+Specification +

+

+No warnings occur under normal conditions. When done, the DBIResult object must be cleared with a call to dbClearResult(). Failure to clear the result set leads to a warning when the connection is closed. +

+

+If the backend supports only one open result set per connection, issuing a second query invalidates an already open result set and raises a warning. The newly opened result set is valid and must be cleared with dbClearResult(). +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4;")
+dbFetch(rs)
+dbClearResult(rs)
+
+dbDisconnect(con)
+
+ + +

+Fetch records from a previously executed query +

+

+This section describes the behavior of the following methods: +

+
+dbFetch(res, n = -1, ...)
+
+fetch(res, n = -1, ...)
+
+

+Description +

+

+Fetch the next n elements (rows) from the result set and return them as a data.frame. +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbFetch(“DBIResult”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+res + +

+An object inheriting from DBIResult, created by dbSendQuery(). +

+
+n + +

+maximum number of records to retrieve per fetch. Use n = -1 or n = Inf to retrieve all pending records. Some implementations may recognize other special values. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Details +

+

+fetch() is provided for compatibility with older DBI clients - for all new code you are strongly encouraged to use dbFetch(). The default implementation for dbFetch() calls fetch() so that it is compatible with existing code. Modern backends should implement for dbFetch() only. +

+

+Value +

+

+dbFetch() always returns a data.frame with as many rows as records were fetched and as many columns as fields in the result set, even if the result is a single value or has one or zero rows. An attempt to fetch from a closed result set raises an error. If the n argument is not an atomic whole number greater or equal to -1 or Inf, an error is raised, but a subsequent call to dbFetch() with proper n argument succeeds. Calling dbFetch() on a result set from a data manipulation query created by dbSendStatement() can be fetched and return an empty data frame, with a warning. +

+

+Specification +

+

+Fetching multi-row queries with one or more columns by default returns the entire result. Multi-row queries can also be fetched progressively by passing a whole number (integer or numeric) as the n argument. A value of Inf for the n argument is supported and also returns the full result. If more rows than available are fetched, the result is returned in full without warning. If fewer rows than requested are returned, further fetches will return a data frame with zero rows. If zero rows are fetched, the columns of the data frame are still fully typed. Fetching fewer rows than available is permitted, no warning is issued when clearing the result set. +

+

+A column named row_names is treated like any other column. +

+

+The column types of the returned data frame depend on the data returned: +

+
    +
  • +

    +integer (or coercible to an integer) for integer values between -2^31 and 2^31 - 1, with NA for SQL NULL values +

    +
  • +
  • +

    +numeric for numbers with a fractional component, with NA for SQL NULL values +

    +
  • +
  • +

    +logical for Boolean values (some backends may return an integer); with NA for SQL NULL values +

    +
  • +
  • +

    +character for text, with NA for SQL NULL values +

    +
  • +
  • +

    +lists of raw for blobs with NULL entries for SQL NULL values +

    +
  • +
  • +

    +coercible using as.Date() for dates, with NA for SQL NULL values (also applies to the return value of the SQL function current_date) +

    +
  • +
  • +

    +coercible using hms::as.hms() for times, with NA for SQL NULL values (also applies to the return value of the SQL function current_time) +

    +
  • +
  • +

    +coercible using as.POSIXct() for timestamps, with NA for SQL NULL values (also applies to the return value of the SQL function current_timestamp) +

    +
  • +
+

+If dates and timestamps are supported by the backend, the following R types are used: +

+
    +
  • +

    +Date for dates (also applies to the return value of the SQL function current_date) +

    +
  • +
  • +

    +POSIXct for timestamps (also applies to the return value of the SQL function current_timestamp) +

    +
  • +
+

+R has no built-in type with lossless support for the full range of 64-bit or larger integers. If 64-bit integers are returned from a query, the following rules apply: +

+
    +
  • +

    +Values are returned in a container with support for the full range of valid 64-bit values (such as the integer64 class of the bit64 package) +

    +
  • +
  • +

    +Coercion to numeric always returns a number that is as close as possible to the true value +

    +
  • +
  • +

    +Loss of precision when converting to numeric gives a warning +

    +
  • +
  • +

    +Conversion to character always returns a lossless decimal representation of the data +

    +
  • +
+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+
+# Fetch all results
+rs <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4")
+dbFetch(rs)
+dbClearResult(rs)
+
+# Fetch in chunks
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+while (!dbHasCompleted(rs)) {
+  chunk <- dbFetch(rs, 10)
+  print(nrow(chunk))
+}
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+Clear a result set +

+

+This section describes the behavior of the following method: +

+
+dbClearResult(res, ...)
+
+

+Description +

+

+Frees all resources (local and remote) associated with a result set. In some cases (e.g., very large result sets) this can be a critical step to avoid exhausting resources (memory, file descriptors, etc.) +

+

+Arguments +

+ + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbClearResult() returns TRUE, invisibly, for result sets obtained from both dbSendQuery() and dbSendStatement(). An attempt to close an already closed result set issues a warning in both cases. +

+

+Specification +

+

+dbClearResult() frees all resources associated with retrieving the result of a query or update operation. The DBI backend can expect a call to dbClearResult() for each dbSendQuery() or dbSendStatement() call. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+rs <- dbSendQuery(con, "SELECT 1")
+print(dbFetch(rs))
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+Bind values to a parameterized/prepared statement +

+

+This section describes the behavior of the following method: +

+
+dbBind(res, params, ...)
+
+

+Description +

+

+For parametrized or prepared statements, the dbSendQuery() and dbSendStatement() functions can be called with statements that contain placeholders for values. The dbBind() function binds these placeholders to actual values, and is intended to be called on the result set before calling dbFetch() or dbGetRowsAffected(). +

+

+Arguments +

+ + + + + + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+params + +

+A list of bindings, named or unnamed. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Details +

+

+DBI supports parametrized (or prepared) queries and statements via the dbBind() generic. Parametrized queries are different from normal queries in that they allow an arbitrary number of placeholders, which are later substituted by actual values. Parametrized queries (and statements) serve two purposes: +

+
    +
  • +

    +The same query can be executed more than once with different values. The DBMS may cache intermediate information for the query, such as the execution plan, and execute it faster. +

    +
  • +
  • +

    +Separation of query syntax and parameters protects against SQL injection. +

    +
  • +
+

+The placeholder format is currently not specified by DBI; in the future, a uniform placeholder syntax may be supported. Consult the backend documentation for the supported formats. For automated testing, backend authors specify the placeholder syntax with the placeholder_pattern tweak. Known examples are: +

+
    +
  • +

    +? (positional matching in order of appearance) in RMySQL and RSQLite +

    +
  • +
  • +

    +$1 (positional matching by index) in RPostgres and RSQLite +

    +
  • +
  • +

    +:name and $name (named matching) in RSQLite +

    +
  • +
+

+Value +

+

+dbBind() returns the result set, invisibly, for queries issued by dbSendQuery() and also for data manipulation statements issued by dbSendStatement(). Calling dbBind() for a query without parameters raises an error. Binding too many or not enough values, or parameters with wrong names or unequal length, also raises an error. If the placeholders in the query are named, all parameter values must have names (which must not be empty or NA), and vice versa, otherwise an error is raised. The behavior for mixing placeholders of different types (in particular mixing positional and named placeholders) is not specified. +

+

+Calling dbBind() on a result set already cleared by dbClearResult() also raises an error. +

+

+Specification +

+

+DBI clients execute parametrized statements as follows: +

+
    +
  1. +

    +Call dbSendQuery() or dbSendStatement() with a query or statement that contains placeholders, store the returned DBIResult object in a variable. Mixing placeholders (in particular, named and unnamed ones) is not recommended. It is good practice to register a call to dbClearResult() via on.exit() right after calling dbSendQuery() or dbSendStatement() (see the last enumeration item). Until dbBind() has been called, the returned result set object has the following behavior: +

    + +
  2. +
  3. +

    +Construct a list with parameters that specify actual values for the placeholders. The list must be named or unnamed, depending on the kind of placeholders used. Named values are matched to named parameters, unnamed values are matched by position in the list of parameters. All elements in this list must have the same lengths and contain values supported by the backend; a data.frame is internally stored as such a list. The parameter list is passed to a call to dbBind() on the DBIResult object. +

    +
  4. +
  5. +

    +Retrieve the data or the number of affected rows from the DBIResult object. +

    +
      +
    • +

      +For queries issued by dbSendQuery(), call dbFetch(). +

      +
    • +
    • +

      +For statements issued by dbSendStatements(), call dbGetRowsAffected(). (Execution begins immediately after the dbBind() call, the statement is processed entirely before the function returns.) +

      +
    • +
    +
  6. +
  7. +

    +Repeat 2. and 3. as necessary. +

    +
  8. +
  9. +

    +Close the result set via dbClearResult(). +

    +
  10. +
+

+The elements of the params argument do not need to be scalars, vectors of arbitrary length (including length 0) are supported. For queries, calling dbFetch() binding such parameters returns concatenated results, equivalent to binding and fetching for each set of values and connecting via rbind(). For data manipulation statements, dbGetRowsAffected() returns the total number of rows affected if binding non-scalar parameters. dbBind() also accepts repeated calls on the same result set for both queries and data manipulation statements, even if no results are fetched between calls to dbBind(). +

+

+At least the following data types are accepted on input (including NA): +

+
    +
  • +

    +integer +

    +
  • +
  • +

    +numeric +

    +
  • +
  • +

    +logical for Boolean values +

    +
  • +
  • +

    +character +

    +
  • +
  • +

    +factor (bound as character, with warning) +

    +
  • +
  • +

    +Date +

    +
  • +
  • +

    +POSIXct timestamps +

    +
  • +
  • +

    +POSIXlt timestamps +

    +
  • +
  • +

    +lists of raw for blobs (with NULL entries for SQL NULL values) +

    +
  • +
  • +

    +objects of type blob::blob +

    +
  • +
+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "iris", iris)
+
+# Using the same query for different values
+iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > ?")
+dbBind(iris_result, list(2.3))
+dbFetch(iris_result)
+dbBind(iris_result, list(3))
+dbFetch(iris_result)
+dbClearResult(iris_result)
+
+# Executing the same statement with different values at once
+iris_result <- dbSendStatement(con, "DELETE FROM iris WHERE [Species] = $species")
+dbBind(iris_result, list(species = c("setosa", "versicolor", "unknown")))
+dbGetRowsAffected(iris_result)
+dbClearResult(iris_result)
+
+nrow(dbReadTable(con, "iris"))
+
+dbDisconnect(con)
+
+ + +

+Send query, retrieve results and then clear result set +

+

+This section describes the behavior of the following method: +

+
+dbGetQuery(conn, statement, ...)
+
+

+Description +

+

+Returns the result of a query as a data frame. dbGetQuery() comes with a default implementation (which should work with most backends) that calls dbSendQuery(), then dbFetch(), ensuring that the result is always free-d by dbClearResult(). +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbGetQuery(“DBIConnection”, “character”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+statement + +

+a character string containing SQL. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Details +

+

+This method is for SELECT queries only. Some backends may support data manipulation statements through this method for compatibility reasons. However, callers are strongly advised to use dbExecute() for data manipulation statements. +

+

+Value +

+

+dbGetQuery() always returns a data.frame with as many rows as records were fetched and as many columns as fields in the result set, even if the result is a single value or has one or zero rows. An error is raised when issuing a query over a closed or invalid connection, if the syntax of the query is invalid, or if the query is not a non-NA string. If the n argument is not an atomic whole number greater or equal to -1 or Inf, an error is raised, but a subsequent call to dbGetQuery() with proper n argument succeeds. +

+

+Implementation notes +

+

+Subclasses should override this method only if they provide some sort of performance optimization. +

+

+Specification +

+

+Fetching multi-row queries with one or more columns be default returns the entire result. A value of Inf for the n argument is supported and also returns the full result. If more rows than available are fetched, the result is returned in full without warning. If zero rows are fetched, the columns of the data frame are still fully typed. Fetching fewer rows than available is permitted, no warning is issued. +

+

+A column named row_names is treated like any other column. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+dbGetQuery(con, "SELECT * FROM mtcars")
+
+dbDisconnect(con)
+
+ + +

+Execute a data manipulation statement on a given database connection +

+

+This section describes the behavior of the following method: +

+
+dbSendStatement(conn, statement, ...)
+
+

+Description +

+

+The dbSendStatement() method only submits and synchronously executes the SQL data manipulation statement (e.g., UPDATE, DELETE, INSERT INTO, DROP TABLE, …) to the database engine. To query the number of affected rows, call dbGetRowsAffected() on the returned result object. You must also call dbClearResult() after that. For interactive use, you should almost always prefer dbExecute(). +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbSendStatement(“DBIConnection”, “character”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+statement + +

+a character string containing SQL. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Details +

+

+dbSendStatement() comes with a default implementation that simply forwards to dbSendQuery(), to support backends that only implement the latter. +

+

+Value +

+

+dbSendStatement() returns an S4 object that inherits from DBIResult. The result set can be used with dbGetRowsAffected() to determine the number of rows affected by the query. Once you have finished using a result, make sure to clear it with dbClearResult(). An error is raised when issuing a statement over a closed or invalid connection, if the syntax of the statement is invalid, or if the statement is not a non-NA string. +

+

+Specification +

+

+No warnings occur under normal conditions. When done, the DBIResult object must be cleared with a call to dbClearResult(). Failure to clear the result set leads to a warning when the connection is closed. If the backend supports only one open result set per connection, issuing a second query invalidates an already open result set and raises a warning. The newly opened result set is valid and must be cleared with dbClearResult(). +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "cars", head(cars, 3))
+rs <- dbSendStatement(con,
+  "INSERT INTO cars (speed, dist) VALUES (1, 1), (2, 2), (3, 3);")
+dbHasCompleted(rs)
+dbGetRowsAffected(rs)
+dbClearResult(rs)
+dbReadTable(con, "cars")   # there are now 6 rows
+
+dbDisconnect(con)
+
+ + +

+Execute an update statement, query number of rows affected, and then close result set +

+

+This section describes the behavior of the following method: +

+
+dbExecute(conn, statement, ...)
+
+

+Description +

+

+Executes a statement and returns the number of rows affected. dbExecute() comes with a default implementation (which should work with most backends) that calls dbSendStatement(), then dbGetRowsAffected(), ensuring that the result is always free-d by dbClearResult(). +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbExecute(“DBIConnection”, “character”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+statement + +

+a character string containing SQL. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Value +

+

+dbExecute() always returns a scalar numeric that specifies the number of rows affected by the statement. An error is raised when issuing a statement over a closed or invalid connection, if the syntax of the statement is invalid, or if the statement is not a non-NA string. +

+

+Implementation notes +

+

+Subclasses should override this method only if they provide some sort of performance optimization. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "cars", head(cars, 3))
+dbReadTable(con, "cars")   # there are 3 rows
+dbExecute(con,
+  "INSERT INTO cars (speed, dist) VALUES (1, 1), (2, 2), (3, 3);")
+dbReadTable(con, "cars")   # there are now 6 rows
+
+dbDisconnect(con)
+
+ + +

+Quote literal strings +

+

+This section describes the behavior of the following method: +

+
+dbQuoteString(conn, x, ...)
+
+

+Description +

+

+Call this method to generate a string that is suitable for use in a query as a string literal, to make sure that you generate valid SQL and avoid SQL injection. +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbQuoteString(“DBIConnection”, “ANY”) +

    +
  • +
  • +

    +DBI::dbQuoteString(“DBIConnection”, “character”) +

    +
  • +
  • +

    +DBI::dbQuoteString(“DBIConnection”, “SQL”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A subclass of DBIConnection, representing an active connection to an DBMS. +

+
+x + +

+A character vector to quote as string. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbQuoteString() returns an object that can be coerced to character, of the same length as the input. For an empty character vector this function returns a length-0 object. +

+

+When passing the returned object again to dbQuoteString() as x argument, it is returned unchanged. Passing objects of class SQL should also return them unchanged. (For backends it may be most convenient to return SQL objects to achieve this behavior, but this is not required.) +

+

+Specification +

+

+The returned expression can be used in a SELECT … query, and for any scalar character x the value of dbGetQuery(paste0(“SELECT”, dbQuoteString(x)))[[1]] must be identical to x, even if x contains spaces, tabs, quotes (single or double), backticks, or newlines (in any combination) or is itself the result of a dbQuoteString() call coerced back to character (even repeatedly). If x is NA, the result must merely satisfy is.na(). The strings “NA” or “NULL” are not treated specially. +

+

+NA should be translated to an unquoted SQL NULL, so that the query SELECT * FROM (SELECT 1) a WHERE … IS NULL returns one row. +

+

+Examples +

+
+# Quoting ensures that arbitrary input is safe for use in a query
+name <- "Robert'); DROP TABLE Students;--"
+dbQuoteString(ANSI(), name)
+
+# NAs become NULL
+dbQuoteString(ANSI(), c("x", NA))
+
+# SQL vectors are always passed through as is
+var_name <- SQL("select")
+var_name
+dbQuoteString(ANSI(), var_name)
+
+# This mechanism is used to prevent double escaping
+dbQuoteString(ANSI(), dbQuoteString(ANSI(), name))
+
+ + +

+Quote identifiers +

+

+This section describes the behavior of the following method: +

+
+dbQuoteIdentifier(conn, x, ...)
+
+

+Description +

+

+Call this method to generate a string that is suitable for use in a query as a column name, to make sure that you generate valid SQL and avoid SQL injection. +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbQuoteIdentifier(“DBIConnection”, “ANY”) +

    +
  • +
  • +

    +DBI::dbQuoteIdentifier(“DBIConnection”, “character”) +

    +
  • +
  • +

    +DBI::dbQuoteIdentifier(“DBIConnection”, “SQL”) +

    +
  • +
  • +

    +DBI::dbQuoteIdentifier(“DBIConnection”, “Table”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A subclass of DBIConnection, representing an active connection to an DBMS. +

+
+x + +

+A character vector to quote as identifier. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbQuoteIdentifier() returns an object that can be coerced to character, of the same length as the input. For an empty character vector this function returns a length-0 object. An error is raised if the input contains NA, but not for an empty string. +

+

+When passing the returned object again to dbQuoteIdentifier() as x argument, it is returned unchanged. Passing objects of class SQL should also return them unchanged. (For backends it may be most convenient to return SQL objects to achieve this behavior, but this is not required.) +

+

+Specification +

+

+Calling dbGetQuery() for a query of the format SELECT 1 AS … returns a data frame with the identifier, unquoted, as column name. Quoted identifiers can be used as table and column names in SQL queries, in particular in queries like SELECT 1 AS … and SELECT * FROM (SELECT 1) …. The method must use a quoting mechanism that is unambiguously different from the quoting mechanism used for strings, so that a query like SELECT … FROM (SELECT 1 AS …) throws an error if the column names do not match. +

+

+The method can quote column names that contain special characters such as a space, a dot, a comma, or quotes used to mark strings or identifiers, if the database supports this. In any case, checking the validity of the identifier should be performed only when executing a query, and not by dbQuoteIdentifier(). +

+

+Examples +

+
+# Quoting ensures that arbitrary input is safe for use in a query
+name <- "Robert'); DROP TABLE Students;--"
+dbQuoteIdentifier(ANSI(), name)
+
+# SQL vectors are always passed through as is
+var_name <- SQL("select")
+var_name
+
+dbQuoteIdentifier(ANSI(), var_name)
+
+# This mechanism is used to prevent double escaping
+dbQuoteIdentifier(ANSI(), dbQuoteIdentifier(ANSI(), name))
+
+ + +

+Copy data frames from database tables +

+

+This section describes the behavior of the following method: +

+
+dbReadTable(conn, name, ...)
+
+

+Description +

+

+Reads a database table to a data frame, optionally converting a column to row names and converting the column names to valid R identifiers. +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbReadTable(“DBIConnection”, “character”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+name + +

+A character string specifying the unquoted DBMS table name, or the result of a call to dbQuoteIdentifier(). +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Additional arguments +

+

+The following arguments are not part of the dbReadTable() generic (to improve compatibility across backends) but are part of the DBI specification: +

+
    +
  • +

    +row.names +

    +
  • +
  • +

    +check.names +

    +
  • +
+

+They must be provided as named arguments. See the “Value” section for details on their usage. +

+

+Specification +

+

+The name argument is processed as follows, to support databases that allow non-syntactic names for their objects: +

+ +

+Value +

+

+dbReadTable() returns a data frame that contains the complete data from the remote table, effectively the result of calling dbGetQuery() with SELECT * FROM <name>. An error is raised if the table does not exist. An empty table is returned as a data frame with zero rows. +

+

+The presence of rownames depends on the row.names argument, see sqlColumnToRownames() for details: +

+
    +
  • +

    +If FALSE or NULL, the returned data frame doesn’t have row names. +

    +
  • +
  • +

    +If TRUE, a column named “row_names” is converted to row names, an error is raised if no such column exists. +

    +
  • +
  • +

    +If NA, a column named “row_names” is converted to row names if it exists, otherwise no translation occurs. +

    +
  • +
  • +

    +If a string, this specifies the name of the column in the remote table that contains the row names, an error is raised if no such column exists. +

    +
  • +
+

+The default is row.names = FALSE. +

+

+If the database supports identifiers with special characters, the columns in the returned data frame are converted to valid R identifiers if the check.names argument is TRUE, otherwise non-syntactic column names can be returned unquoted. +

+

+An error is raised when calling this method for a closed or invalid connection. An error is raised if name cannot be processed with dbQuoteIdentifier() or if this results in a non-scalar. Unsupported values for row.names and check.names (non-scalars, unsupported data types, NA for check.names) also raise an error. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars[1:10, ])
+dbReadTable(con, "mtcars")
+
+dbDisconnect(con)
+
+ + +

+Copy data frames to database tables +

+

+This section describes the behavior of the following method: +

+
+dbWriteTable(conn, name, value, ...)
+
+

+Description +

+

+Writes, overwrites or appends a data frame to a database table, optionally converting row names to a column and specifying SQL data types for fields. +

+

+Arguments +

+ + + + + + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+name + +

+A character string specifying the unquoted DBMS table name, or the result of a call to dbQuoteIdentifier(). +

+
+value + +

+a data.frame (or coercible to data.frame). +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Additional arguments +

+

+The following arguments are not part of the dbWriteTable() generic (to improve compatibility across backends) but are part of the DBI specification: +

+
    +
  • +

    +row.names (default: NA) +

    +
  • +
  • +

    +overwrite (default: FALSE) +

    +
  • +
  • +

    +append (default: FALSE) +

    +
  • +
  • +

    +field.types (default: NULL) +

    +
  • +
  • +

    +temporary (default: FALSE) +

    +
  • +
+

+They must be provided as named arguments. See the “Specification” and “Value” sections for details on their usage. +

+

+Specification +

+

+The name argument is processed as follows, to support databases that allow non-syntactic names for their objects: +

+ +

+If the overwrite argument is TRUE, an existing table of the same name will be overwritten. This argument doesn’t change behavior if the table does not exist yet. +

+

+If the append argument is TRUE, the rows in an existing table are preserved, and the new data are appended. If the table doesn’t exist yet, it is created. +

+

+If the temporary argument is TRUE, the table is not available in a second connection and is gone after reconnecting. Not all backends support this argument. A regular, non-temporary table is visible in a second connection and after reconnecting to the database. +

+

+SQL keywords can be used freely in table names, column names, and data. Quotes, commas, and spaces can also be used in the data, and, if the database supports non-syntactic identifiers, also for table names and column names. +

+

+The following data types must be supported at least, and be read identically with dbReadTable(): +

+
    +
  • +

    +integer +

    +
  • +
  • +

    +numeric (the behavior for Inf and NaN is not specified) +

    +
  • +
  • +

    +logical +

    +
  • +
  • +

    +NA as NULL +

    +
  • +
  • +

    +64-bit values (using “bigint” as field type); the result can be converted to a numeric, which may lose precision, +

    +
  • +
  • +

    +character (in both UTF-8 and native encodings), supporting empty strings +

    +
  • +
  • +

    +factor (returned as character) +

    +
  • +
  • +

    +list of raw (if supported by the database) +

    +
  • +
  • +

    +objects of type blob::blob (if supported by the database) +

    +
  • +
  • +

    +date (if supported by the database; returned as Date) +

    +
  • +
  • +

    +time (if supported by the database; returned as objects that inherit from difftime) +

    +
  • +
  • +

    +timestamp (if supported by the database; returned as POSIXct respecting the time zone but not necessarily preserving the input time zone) +

    +
  • +
+

+Mixing column types in the same table is supported. +

+

+The field.types argument must be a named character vector with at most one entry for each column. It indicates the SQL data type to be used for a new column. +

+

+The interpretation of rownames depends on the row.names argument, see sqlRownamesToColumn() for details: +

+
    +
  • +

    +If FALSE or NULL, row names are ignored. +

    +
  • +
  • +

    +If TRUE, row names are converted to a column named “row_names”, even if the input data frame only has natural row names from 1 to nrow(…). +

    +
  • +
  • +

    +If NA, a column named “row_names” is created if the data has custom row names, no extra column is created in the case of natural row names. +

    +
  • +
  • +

    +If a string, this specifies the name of the column in the remote table that contains the row names, even if the input data frame only has natural row names. +

    +
  • +
+

+Value +

+

+dbWriteTable() returns TRUE, invisibly. If the table exists, and both append and overwrite arguments are unset, or append = TRUE and the data frame with the new data has different column names, an error is raised; the remote table remains unchanged. +

+

+An error is raised when calling this method for a closed or invalid connection. An error is also raised if name cannot be processed with dbQuoteIdentifier() or if this results in a non-scalar. Invalid values for the additional arguments row.names, overwrite, append, field.types, and temporary (non-scalars, unsupported data types, NA, incompatible values, duplicate or missing names, incompatible columns) also raise an error. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars[1:5, ])
+dbReadTable(con, "mtcars")
+
+dbWriteTable(con, "mtcars", mtcars[6:10, ], append = TRUE)
+dbReadTable(con, "mtcars")
+
+dbWriteTable(con, "mtcars", mtcars[1:10, ], overwrite = TRUE)
+dbReadTable(con, "mtcars")
+
+# No row names
+dbWriteTable(con, "mtcars", mtcars[1:10, ], overwrite = TRUE, row.names = FALSE)
+dbReadTable(con, "mtcars")
+
+
+ + +

+List remote tables +

+

+This section describes the behavior of the following method: +

+
+dbListTables(conn, ...)
+
+

+Description +

+

+Returns the unquoted names of remote tables accessible through this connection. This should, where possible, include temporary tables, and views. +

+

+Arguments +

+ + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Additional arguments +

+

+TBD: temporary = NA +

+

+This must be provided as named argument. See the “Specification” section for details on their usage. +

+

+Value +

+

+dbListTables() returns a character vector that enumerates all tables and views in the database. Tables added with dbWriteTable() are part of the list, including temporary tables if supported by the database. As soon a table is removed from the database, it is also removed from the list of database tables. +

+

+The returned names are suitable for quoting with dbQuoteIdentifier(). An error is raised when calling this method for a closed or invalid connection. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbListTables(con)
+dbWriteTable(con, "mtcars", mtcars)
+dbListTables(con)
+
+dbDisconnect(con)
+
+ + +

+Does a table exist? +

+

+This section describes the behavior of the following method: +

+
+dbExistsTable(conn, name, ...)
+
+

+Description +

+

+Returns if a table given by name exists in the database. +

+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+name + +

+A character string specifying a DBMS table name. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Additional arguments +

+

+TBD: temporary = NA +

+

+This must be provided as named argument. See the “Specification” section for details on their usage. +

+

+Specification +

+

+The name argument is processed as follows, to support databases that allow non-syntactic names for their objects: +

+ +

+For all tables listed by dbListTables(), dbExistsTable() returns TRUE. +

+

+Value +

+

+dbExistsTable() returns a logical scalar, TRUE if the table or view specified by the name argument exists, FALSE otherwise. This includes temporary tables if supported by the database. +

+

+An error is raised when calling this method for a closed or invalid connection. An error is also raised if name cannot be processed with dbQuoteIdentifier() or if this results in a non-scalar. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbExistsTable(con, "iris")
+dbWriteTable(con, "iris", iris)
+dbExistsTable(con, "iris")
+
+dbDisconnect(con)
+
+ + +

+Remove a table from the database +

+

+This section describes the behavior of the following method: +

+
+dbRemoveTable(conn, name, ...)
+
+

+Description +

+

+Remove a remote table (e.g., created by dbWriteTable()) from the database. +

+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+name + +

+A character string specifying a DBMS table name. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Value +

+

+dbRemoveTable() returns TRUE, invisibly. If the table does not exist, an error is raised. An attempt to remove a view with this function may result in an error. +

+

+An error is raised when calling this method for a closed or invalid connection. An error is also raised if name cannot be processed with dbQuoteIdentifier() or if this results in a non-scalar. +

+

+Specification +

+

+A table removed by dbRemoveTable() doesn’t appear in the list of tables returned by dbListTables(), and dbExistsTable() returns FALSE. The removal propagates immediately to other connections to the same database. This function can also be used to remove a temporary table. +

+

+The name argument is processed as follows, to support databases that allow non-syntactic names for their objects: +

+ +

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbExistsTable(con, "iris")
+dbWriteTable(con, "iris", iris)
+dbExistsTable(con, "iris")
+dbRemoveTable(con, "iris")
+dbExistsTable(con, "iris")
+
+dbDisconnect(con)
+
+ + +

+Is this DBMS object still valid? +

+

+This section describes the behavior of the following method: +

+
+dbIsValid(dbObj, ...)
+
+

+Description +

+

+This generic tests whether a database object is still valid (i.e. it hasn’t been disconnected or cleared). +

+

+Arguments +

+ + + + + + + + + +
+dbObj + +

+An object inheriting from DBIObject, i.e. DBIDriver, DBIConnection, or a DBIResult +

+
+ + +

+Other arguments to methods. +

+
+

+Value +

+

+dbIsValid() returns a logical scalar, TRUE if the object specified by dbObj is valid, FALSE otherwise. A DBIConnection object is initially valid, and becomes invalid after disconnecting with dbDisconnect(). For an invalid connection object (e.g., for some drivers if the object is saved to a file and then restored), the method also returns FALSE. A DBIResult object is valid after a call to dbSendQuery(), and stays valid even after all rows have been fetched; only clearing it with dbClearResult() invalidates it. A DBIResult object is also valid after a call to dbSendStatement(), and stays valid after querying the number of rows affected; only clearing it with dbClearResult() invalidates it. If the connection to the database system is dropped (e.g., due to connectivity problems, server failure, etc.), dbIsValid() should return FALSE. This is not tested automatically. +

+

+Examples +

+
+dbIsValid(RSQLite::SQLite())
+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+dbIsValid(con)
+
+rs <- dbSendQuery(con, "SELECT 1")
+dbIsValid(rs)
+
+dbClearResult(rs)
+dbIsValid(rs)
+
+dbDisconnect(con)
+dbIsValid(con)
+
+ + +

+Completion status +

+

+This section describes the behavior of the following method: +

+
+dbHasCompleted(res, ...)
+
+

+Description +

+

+This method returns if the operation has completed. A SELECT query is completed if all rows have been fetched. A data manipulation statement is always completed. +

+

+Arguments +

+ + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbHasCompleted() returns a logical scalar. For a query initiated by dbSendQuery() with non-empty result set, dbHasCompleted() returns FALSE initially and TRUE after calling dbFetch() without limit. For a query initiated by dbSendStatement(), dbHasCompleted() always returns TRUE. Attempting to query completion status for a result set cleared with dbClearResult() gives an error. +

+

+Specification +

+

+The completion status for a query is only guaranteed to be set to FALSE after attempting to fetch past the end of the entire result. Therefore, for a query with an empty result set, the initial return value is unspecified, but the result value is TRUE after trying to fetch only one row. Similarly, for a query with a result set of length n, the return value is unspecified after fetching n rows, but the result value is TRUE after trying to fetch only one more row. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+
+dbHasCompleted(rs)
+ret1 <- dbFetch(rs, 10)
+dbHasCompleted(rs)
+ret2 <- dbFetch(rs)
+dbHasCompleted(rs)
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+Get the statement associated with a result set +

+

+This section describes the behavior of the following method: +

+
+dbGetStatement(res, ...)
+
+

+Description +

+

+Returns the statement that was passed to dbSendQuery() or dbSendStatement(). +

+

+Arguments +

+ + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbGetStatement() returns a string, the query used in either dbSendQuery() or dbSendStatement(). Attempting to query the statement for a result set cleared with dbClearResult() gives an error. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+dbGetStatement(rs)
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+The number of rows fetched so far +

+

+This section describes the behavior of the following method: +

+
+dbGetRowCount(res, ...)
+
+

+Description +

+

+Returns the total number of rows actually fetched with calls to dbFetch() for this result set. +

+

+Arguments +

+ + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbGetRowCount() returns a scalar number (integer or numeric), the number of rows fetched so far. After calling dbSendQuery(), the row count is initially zero. After a call to dbFetch() without limit, the row count matches the total number of rows returned. Fetching a limited number of rows increases the number of rows by the number of rows returned, even if fetching past the end of the result set. For queries with an empty result set, zero is returned even after fetching. For data manipulation statements issued with dbSendStatement(), zero is returned before and after calling dbFetch(). Attempting to get the row count for a result set cleared with dbClearResult() gives an error. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+
+dbGetRowCount(rs)
+ret1 <- dbFetch(rs, 10)
+dbGetRowCount(rs)
+ret2 <- dbFetch(rs)
+dbGetRowCount(rs)
+nrow(ret1) + nrow(ret2)
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+The number of rows affected +

+

+This section describes the behavior of the following method: +

+
+dbGetRowsAffected(res, ...)
+
+

+Description +

+

+This method returns the number of rows that were added, deleted, or updated by a data manipulation statement. +

+

+Arguments +

+ + + + + + + + + +
+res + +

+An object inheriting from DBIResult. +

+
+ + +

+Other arguments passed on to methods. +

+
+

+Value +

+

+dbGetRowsAffected() returns a scalar number (integer or numeric), the number of rows affected by a data manipulation statement issued with dbSendStatement(). The value is available directly after the call and does not change after calling dbFetch(). For queries issued with dbSendQuery(), zero is returned before and after the call to dbFetch(). Attempting to get the rows affected for a result set cleared with dbClearResult() gives an error. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendStatement(con, "DELETE FROM mtcars")
+dbGetRowsAffected(rs)
+nrow(mtcars)
+
+dbClearResult(rs)
+dbDisconnect(con)
+
+ + +

+Begin/commit/rollback SQL transactions +

+

+This section describes the behavior of the following methods: +

+
+dbBegin(conn, ...)
+
+dbCommit(conn, ...)
+
+dbRollback(conn, ...)
+
+

+Description +

+

+A transaction encapsulates several SQL statements in an atomic unit. It is initiated with dbBegin() and either made persistent with dbCommit() or undone with dbRollback(). In any case, the DBMS guarantees that either all or none of the statements have a permanent effect. This helps ensuring consistency of write operations to multiple tables. +

+

+Arguments +

+ + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Details +

+

+Not all database engines implement transaction management, in which case these methods should not be implemented for the specific DBIConnection subclass. +

+

+Value +

+

+dbBegin(), dbCommit() and dbRollback() return TRUE, invisibly. The implementations are expected to raise an error in case of failure, but this is not tested. In any way, all generics throw an error with a closed or invalid connection. In addition, a call to dbCommit() or dbRollback() without a prior call to dbBegin() raises an error. Nested transactions are not supported by DBI, an attempt to call dbBegin() twice yields an error. +

+

+Specification +

+

+Actual support for transactions may vary between backends. A transaction is initiated by a call to dbBegin() and committed by a call to dbCommit(). Data written in a transaction must persist after the transaction is committed. For example, a record that is missing when the transaction is started but is created during the transaction must exist both during and after the transaction, and also in a new connection. +

+

+A transaction can also be aborted with dbRollback(). All data written in such a transaction must be removed after the transaction is rolled back. For example, a record that is missing when the transaction is started but is created during the transaction must not exist anymore after the rollback. +

+

+Disconnection from a connection with an open transaction effectively rolls back the transaction. All data written in such a transaction must be removed after the transaction is rolled back. +

+

+The behavior is not specified if other arguments are passed to these functions. In particular, RSQLite issues named transactions with support for nesting if the name argument is set. +

+

+The transaction isolation level is not specified by DBI. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "cash", data.frame(amount = 100))
+dbWriteTable(con, "account", data.frame(amount = 2000))
+
+# All operations are carried out as logical unit:
+dbBegin(con)
+withdrawal <- 300
+dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
+dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
+dbCommit(con)
+
+dbReadTable(con, "cash")
+dbReadTable(con, "account")
+
+# Rolling back after detecting negative value on account:
+dbBegin(con)
+withdrawal <- 5000
+dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
+dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
+if (dbReadTable(con, "account")$amount >= 0) {
+  dbCommit(con)
+} else {
+  dbRollback(con)
+}
+
+dbReadTable(con, "cash")
+dbReadTable(con, "account")
+
+dbDisconnect(con)
+
+ + +

+Self-contained SQL transactions +

+

+This section describes the behavior of the following methods: +

+
+dbWithTransaction(conn, code, ...)
+
+dbBreak()
+
+

+Description +

+

+Given that transactions are implemented, this function allows you to pass in code that is run in a transaction. The default method of dbWithTransaction() calls dbBegin() before executing the code, and dbCommit() after successful completion, or dbRollback() in case of an error. The advantage is that you don’t have to remember to do dbBegin() and dbCommit() or dbRollback() – that is all taken care of. The special function dbBreak() allows an early exit with rollback, it can be called only inside dbWithTransaction(). +

+

+Methods in other packages +

+
    +
  • +

    +DBI::dbWithTransaction(“DBIConnection”) +

    +
  • +
+

+Arguments +

+ + + + + + + + + + + + + +
+conn + +

+A DBIConnection object, as returned by dbConnect(). +

+
+code + +

+An arbitrary block of R code. +

+
+ + +

+Other parameters passed on to methods. +

+
+

+Details +

+

+DBI implements dbWithTransaction(), backends should need to override this generic only if they implement specialized handling. +

+

+Value +

+

+dbWithTransaction() returns the value of the executed code. Failure to initiate the transaction (e.g., if the connection is closed or invalid of if dbBegin() has been called already) gives an error. +

+

+Specification +

+

+dbWithTransaction() initiates a transaction with dbBegin(), executes the code given in the code argument, and commits the transaction with dbCommit(). If the code raises an error, the transaction is instead aborted with dbRollback(), and the error is propagated. If the code calls dbBreak(), execution of the code stops and the transaction is silently aborted. All side effects caused by the code (such as the creation of new variables) propagate to the calling environment. +

+

+Examples +

+
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbWriteTable(con, "cash", data.frame(amount = 100))
+dbWriteTable(con, "account", data.frame(amount = 2000))
+
+# All operations are carried out as logical unit:
+dbWithTransaction(
+  con,
+  {
+    withdrawal <- 300
+    dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
+    dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
+  }
+)
+
+# The code is executed as if in the curent environment:
+withdrawal
+
+# The changes are committed to the database after successful execution:
+dbReadTable(con, "cash")
+dbReadTable(con, "account")
+
+# Rolling back with dbBreak():
+dbWithTransaction(
+  con,
+  {
+    withdrawal <- 5000
+    dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
+    dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
+    if (dbReadTable(con, "account")$amount < 0) {
+      dbBreak()
+    }
+  }
+)
+
+# These changes were not committed to the database:
+dbReadTable(con, "cash")
+dbReadTable(con, "account")
+
+dbDisconnect(con)
+
+ +
+
+ + + +
+ + +
+ +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/authors.html b/docs/authors.html new file mode 100644 index 000000000..391ed2332 --- /dev/null +++ b/docs/authors.html @@ -0,0 +1,138 @@ + + + + + + + + +Authors • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+ + +
    +
  • +

    R Special Interest Group on Databases (R-SIG-DB). Author. +

    +
  • +
  • +

    Hadley Wickham. Author. +

    +
  • +
  • +

    Kirill Müller. Author, maintainer. +

    +
  • +
+ +
+ +
+ + +
+ + +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..b9e7adb13 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,188 @@ + + + + + + + +R Database Interface • DBI + + + + + + +
+
+ + + +
+
+
+ + +

The DBI package defines a common interface between the R and database management systems (DBMS). The interface defines a small set of classes and methods similar in spirit to Perl’s DBI, Java’s JDBC, Python’s DB-API, and Microsoft’s ODBC. It defines a set of classes and methods defines what operations are possible and how they are performed:

+
    +
  • connect/disconnect to the DBMS
  • +
  • create and execute statements in the DBMS
  • +
  • extract results/output from statements
  • +
  • error/exception handling
  • +
  • information (meta-data) from database objects
  • +
  • transaction management (optional)
  • +
+

DBI separates the connectivity to the DBMS into a “front-end” and a “back-end”. Applications use only the exposed “front-end” API. The facilities that communicate with specific DBMSs (SQLite, MySQL, PostgreSQL, MonetDB, etc.) are provided by “drivers” (other packages) that get invoked automatically through S4 methods.

+

The following example illustrates some of the DBI capabilities:

+
library(DBI)
+# Create an ephemeral in-memory RSQLite database
+con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")
+
+dbListTables(con)
+dbWriteTable(con, "mtcars", mtcars)
+dbListTables(con)
+
+dbListFields(con, "mtcars")
+dbReadTable(con, "mtcars")
+
+# You can fetch all results:
+res <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4")
+dbFetch(res)
+dbClearResult(res)
+
+# Or a chunk at a time
+res <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4")
+while(!dbHasCompleted(res)){
+  chunk <- dbFetch(res, n = 5)
+  print(nrow(chunk))
+}
+dbClearResult(res)
+
+dbDisconnect(con)
+

To install DBI:

+ +

Discussions associated with DBI and related database packages take place on R-SIG-DB. The website Databases using R describes the tools and best practices in this ecosystem.

+
+

+Class structure

+

There are four main DBI classes. Three which are each extended by individual database backends:

+
    +
  • DBIObject: a common base class for all DBI.

  • +
  • DBIDriver: a base class representing overall DBMS properties. Typically generator functions instantiate the driver objects like RSQLite(), RPostgreSQL(), RMySQL() etc.

  • +
  • DBIConnection: represents a connection to a specific database

  • +
  • DBIResult: the result of a DBMS query or statement.

  • +
+

All classes are virtual: they cannot be instantiated directly and instead must be subclassed.

+
+
+

+History

+

The following history of DBI was contributed by David James, the driving force behind the development of DBI, and many of the packages that implement it.

+

The idea/work of interfacing S (originally S3 and S4) to RDBMS goes back to the mid- and late 1990’s in Bell Labs. The first toy interface I did was to implement John Chamber’s early concept of “Data Management in S” (1991). The implementation followed that interface pretty closely and immediately showed some of the limitations when dealing with very large databases; if my memory serves me, the issue was the instance-based of the language back then, e.g., if you attached an RDBMS to the search() path and then needed to resolve a symbol “foo”, you effectively had to bring all the objects in the database to check their mode/class, i.e., the instance object had the metadata in itself as attributes. The experiment showed that the S3 implementation of “data management” was not really suitable to large external RDBMS (probably it was never intended to do that anyway). (Note however, that since then, John and Duncan Temple Lang generalized the data management in S4 a lot, including Duncan’s implementation in his RObjectTables package where he considered a lot of synchronization/caching issues relevant to DBI and, more generally, to most external interfaces).

+

Back then we were working very closely with Lucent’s microelectronics manufacturing — our colleagues there had huge Oracle (mostly) databases that we needed to constantly query via SQL*Plus. My colleague Jake Luciani was developing advanced applications in C and SQL, and the two of us came up with the first implementation of S3 directly connecting with Oracle. What I remember is that the Linux PRO*C pre-compiler (that embedded SQL in C code) was very buggy — we spent a lot of time looking for workarounds and tricks until we got the C interface running. At the time, other projects within Bell Labs began using MySQL, and we moved to MySQL (with the help of Doug Bates’ student Saikat DebRoy, then a summer intern) with no intentions of looking back at the very difficult Oracle interface. It was at this time that I moved all the code from S3 methods to S4 classes and methods and begun reaching out to the S/R community for suggestions, ideas, etc. All (most) of this work was on Bell Labs versions of S3 and S4, but I made sure it worked with S-Plus. At some point around 2000 (I don’t remember exactly when), I ported all the code to R regressing to S3 methods, and later on (once S4 classes and methods were available in R) I re-implemented everything back to S4 classes and methods in R (a painful back-and-forth). It was at this point that I decided to drop S-Plus altogether. Around that time, I came across a very early implementation of SQLite and I was quite interested and thought it was a very nice RDBMS that could be used for all kinds of experimentation, etc., so it was pretty easy to implement on top of the DBI.

+

Within the R community, there were quite a number of people that showed interest on defining a common interface to databases, but only a few folks actually provided code/suggestions/etc. (Tim Keitt was most active with the dbi/PostgreSQL packages — he also was considering what he called “proxy” objects, which was reminiscent of what Duncan had been doing). Kurt Hornick, Vincent Carey, Robert Gentleman, and others provided suggestions/comments/support for the DBI definition. By around 2003, the DBI was more or less implemented as it is today.

+

I’m sure I’ll forget some (most should be in the THANKS sections of the various packages), but the names that come to my mind at this moment are Jake Luciani (ROracle), Don MacQueen and other early ROracle users (super helpful), Doug Bates and his student Saikat DebRoy for RMySQL, Fei Chen (at the time a student of Prof. Ripley) also contributed to RMySQL, Tim Keitt (working on an early S3 interface to PostgrSQL), Torsten Hothorn (worked with mSQL and also MySQL), Prof. Ripley working/extending the RODBC package, in addition to John Chambers and Duncan Temple-Lang who provided very important comments and suggestions.

+

Actually, the real impetus behind the DBI was always to do distributed statistical computing — not to provide a yet-another import/export mechanism — and this perspective was driven by John and Duncan’s vision and work on inter-system computing, COM, CORBA, etc. I’m not sure many of us really appreciated (even now) the full extent of those ideas and concepts. Just like in other languages (C’s ODBC, Java’s JDBC, Perl’s DBI/DBD, Python dbapi), R/S DBI was meant to unify the interfacing to RDBMS so that R/S applications could be developed on top of the DBI and not be hard coded to any one relation database. The interface I tried to follow the closest was the Python’s DBAPI — I haven’t worked on this topic for a while, but I still feel Python’s DBAPI is the cleanest and most relevant for the S language.

+
+
+
+ + +
+ + +
+ +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/jquery.sticky-kit.min.js b/docs/jquery.sticky-kit.min.js new file mode 100644 index 000000000..e2a3c6de9 --- /dev/null +++ b/docs/jquery.sticky-kit.min.js @@ -0,0 +1,9 @@ +/* + Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net +*/ +(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); +if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, +u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), +a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", +y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n + + + + + diff --git a/docs/news/index.html b/docs/news/index.html new file mode 100644 index 000000000..42f5f7924 --- /dev/null +++ b/docs/news/index.html @@ -0,0 +1,492 @@ + + + + + + + + +All news • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + +
+
+

+DBI 0.7-14 (2018-01-27)

+
    +
  • The SQL() function gains a names argument which can be used to assign names to SQL strings.
  • +
  • +dbListResults() is deprecated by documentation (#58).
  • +
  • +dbGetException() is soft-deprecated by documentation (#51).
  • +
  • Help pages for generics now contain a dynamic list of methods implemented by DBI backends (#162).
  • +
  • +sqlInterpolate() now supports both named and positional variables (#216, @hannesmuehleisen).
  • +
  • Specialized methods for dbQuoteString() and dbQuoteIdentifier() are available again, for compatibility with clients that use getMethod() to access them (#218).
  • +
+
+
+

+DBI 0.7-13 (2017-11-27)

+
    +
  • The deprecated print.list.pairs() has been removed.
  • +
  • Fix dbDataType() for AsIs object (#198, @yutannihilation).
  • +
  • Point to db.rstudio.com (@wibeasley, #209).
  • +
  • Reflect new ‘r-dbi’ organization in DESCRIPTION (@wibeasley, #207).
  • +
  • Using switchpatch on the second argument for default implementations of dbQuoteString() and dbQuoteIdentifier().
  • +
  • New dbQuoteLiteral() generic. The default implementation uses switchpatch to avoid dispatch ambiguities, and forwards to dbQuoteString() for character vectors. Backends may override methods that also dispatch on the second argument, but in this case also an override for the "SQL" class is necessary (#172).
  • +
  • Fix dbQuoteString() and dbQuoteIdentifier() to ignore invalid UTF-8 strings (r-dbi/DBItest#156).
  • +
+
+
+

+DBI 0.7-12 (2017-08-10)

+ +
+
+

+DBI 0.7-11 (2017-08-08)

+
    +
  • The default implementation of dbReadTable() now has row.names = FALSE as default and also supports row.names = NULL (#186).
  • +
+
+
+

+DBI 0.7 (2017-06-17)

+
    +
  • Import updated specs from DBItest.
  • +
  • The default implementation of dbGetQuery() now accepts an n argument and forwards it to dbFetch(). No warning about pending rows is issued anymore (#76).
  • +
  • Require R >= 3.0.0 (for slots argument of setClass()) (#169, @mvkorpel).
  • +
+
+
+

+DBI 0.6-1 (2017-04-01)

+
    +
  • Fix dbReadTable() for backends that do not provide their own implementation (#171).
  • +
+
+
+

+DBI 0.6 (2017-03-08)

+
    +
  • Interface changes + +
  • +
  • Interface enhancements +
      +
    • Removed valueClass = "logical" for those generics where the return value is meaningless, to allow backends to return invisibly (#135).
    • +
    • Avoiding using braces in the definitions of generics if possible, so that standard generics can be detected (#146).
    • +
    • Added default implementation for dbReadTable().
    • +
    • All standard generics are required to have an ellipsis (with test), for future extensibility. - Improved default implementation of dbQuoteString() and dbQuoteIdentifier() (#77).
    • +
    • Removed tryCatch() call in dbGetQuery() (#113).
    • +
    +
  • +
  • Documentation improvements +
      +
    • Finalized first draft of DBI specification, now in a vignette.
    • +
    • Most methods now draw documentation from DBItest, only those where the behavior is not finally decided don’t do this yet yet.
    • +
    • Removed max.connections requirement from documentation (#56).
    • +
    • Improved dbBind() documentation and example (#136).
    • +
    • Change omegahat.org URL to omegahat.net, the particular document still doesn’t exist below the new domain.
    • +
    +
  • +
  • Internal +
      +
    • Use roxygen2 inheritance to copy DBI specification to this package.
    • +
    • Use tic package for building documentation.
    • +
    • Use markdown in documentation.
    • +
    +
  • +
+
+
+

+DBI 0.5-1 (2016-09-09)

+
    +
  • Documentation and example updates.
  • +
+
+
+

+DBI 0.5 (2016-08-11, CRAN release)

+
    +
  • Interface changes +
      +
    • +dbDataType() maps character values to "TEXT" by default (#102).
    • +
    • The default implementation of dbQuoteString() doesn’t call encodeString() anymore: Neither SQLite nor Postgres understand e.g. \n in a string literal, and all of SQLite, Postgres, and MySQL accept an embedded newline (#121).
    • +
    +
  • +
  • Interface enhancements + +
  • +
  • Documentation improvements: +
      +
    • One example per function (except functions scheduled for deprecation) (#67).
    • +
    • Consistent layout and identifier naming.
    • +
    • Better documentation of generics by adding links to the class and related generics in the “See also” section under “Other DBI… generics” (#130). S4 documentation is directed to a hidden page to unclutter documentation index (#59).
    • +
    • Fix two minor vignette typos (#124, @mdsumner).
    • +
    • Add package documentation.
    • +
    • Remove misleading parts in dbConnect() documentation (#118).
    • +
    • Remove misleading link in dbDataType() documentation.
    • +
    • Remove full stop from documentation titles.
    • +
    • New help topic “DBIspec” that contains the full DBI specification (currently work in progress) (#129).
    • +
    • HTML documentation generated by staticdocs is now uploaded to http://rstats-db.github.io/DBI for each build of the “production” branch (#131).
    • +
    • Further minor changes and fixes.
    • +
    +
  • +
  • Internal +
      +
    • Use contains argument instead of representation() to denote base classes (#93).
    • +
    • Remove redundant declaration of transaction methods (#110, @bborgesr).
    • +
    +
  • +
+
+
+

+DBI 0.4-1 (2016-05-07, CRAN release)

+
    +
  • The default show() implementations silently ignore all errors. Some DBI drivers (e.g., RPostgreSQL) might fail to implement dbIsValid() or the other methods used.
  • +
+
+
+

+DBI 0.4 (2016-04-30)

+
    +
  • New package maintainer: Kirill Müller.

  • +
  • dbGetInfo() gains a default method that extracts the information from dbGetStatement(), dbGetRowsAffected(), dbHasCompleted(), and dbGetRowCount(). This means that most drivers should no longer need to implement dbGetInfo() (which may be deprecated anyway at some point) (#55).

  • +
  • dbDataType() and dbQuoteString() are now properly exported.

  • +
  • The default implementation for dbDataType() (powered by dbiDataType()) now also supports difftime and AsIs objects and lists of raw (#70).

  • +
  • Default dbGetQuery() method now always calls dbFetch(), in a tryCatch() block.

  • +
  • New generic dbBind() for binding values to a parameterised query.

  • +
  • +

    DBI gains a number of SQL generation functions. These make it easier to write backends by implementing common operations that are slightly tricky to do absolutely correctly.

    +
      +
    • sqlCreateTable() and sqlAppendTable() create tables from a data frame and insert rows into an existing table. These will power most implementations of dbWriteTable(). sqlAppendTable() is useful for databases that support parameterised queries.

    • +
    • sqlRownamesToColumn() and sqlColumnToRownames() provide a standard way of translating row names to and from the database.

    • +
    • sqlInterpolate() and sqlParseVariables() allows databases without native parameterised queries to use parameterised queries to avoid SQL injection attacks.

    • +
    • sqlData() is a new generic that converts a data frame into a data frame suitable for sending to the database. This is used to (e.g.) ensure all character vectors are encoded as UTF-8, or to convert R varible types (like factor) to types supported by the database.

    • +
    • The sqlParseVariablesImpl() is now implemented purely in R, with full test coverage (#83, @hannesmuehleisen).

    • +
    +
  • +
  • dbiCheckCompliance() has been removed, the functionality is now available in the DBItest package (#80).

  • +
  • Added default show() methods for driver, connection and results.

  • +
  • New concrete ANSIConnection class and ANSI() function to generate a dummy ANSI compliant connection useful for testing.

  • +
  • Default dbQuoteString() and dbQuoteIdentifer() methods now use encodeString() so that special characters like \n are correctly escaped. dbQuoteString() converts NA to (unquoted) NULL.

  • +
  • The initial DBI proposal and DBI version 1 specification are now included as a vignette. These are there mostly for historical interest.

  • +
  • The new DBItest package is described in the vignette.

  • +
  • Deprecated print.list.pairs().

  • +
  • Removed unused dbi_dep().

  • +
+
+
+

+Version 0.3.1

+ +
+
+

+Version 0.3.0

+
+

+New and enhanced generics

+ +
+
+

+New default methods

+ +
+
+

+Deprecated features

+
    +
  • +

    The following functions are soft-deprecated. They are going away, and developers who use the DBI should begin preparing. The formal deprecation process will begin in July 2015, where these function will emit warnings on use.

    + +
  • +
  • dbGetDBIVersion() is deprecated since it’s now just a thin wrapper around packageVersion("DBI").

  • +
  • dbSetDataMappings() (#9) and dbCallProc() (#7) are deprecated as no implementations were ever provided.

  • +
+
+
+

+Other improvements

+
    +
  • dbiCheckCompliance() makes it easier for implementors to check that their package is in compliance with the DBI specification.

  • +
  • All examples now use the RSQLite package so that you can easily try out the code samples (#4).

  • +
  • dbDriver() gains a more effective search mechanism that doesn’t rely on packages being loaded (#1).

  • +
  • DBI has been converted to use roxygen2 for documentation, and now most functions have their own documentation files. I would love your feedback on how we could make the documentation better!

  • +
+
+
+
+

+Version 0.2-7

+
    +
  • Trivial changes (updated package fields, daj)
  • +
+
+
+

+Version 0.2-6

+
    +
  • Removed deprecated \synopsis in some Rd files (thanks to Prof. Ripley)
  • +
+
+
+

+Version 0.2-5

+
    +
  • Code cleanups contributed by Matthias Burger: avoid partial argument name matching and use TRUE/FALSE, not T/F.

  • +
  • Change behavior of make.db.names.default to quote SQL keywords if allow.keywords is FALSE. Previously, SQL keywords would be name mangled with underscores and a digit. Now they are quoted using ’“’.

  • +
+
+
+

+Version 0.2-4

+
    +
  • Changed license from GPL to LPGL

  • +
  • Fixed a trivial typo in documentation

  • +
+
+
+

+Version 0.1-10

+
    +
  • Fixed documentation typos.
  • +
+
+
+

+Version 0.1-9

+
    +
  • Trivial changes.
  • +
+
+
+

+Version 0.1-8

+
    +
  • A trivial change due to package.description() being deprecated in 1.9.0.
  • +
+
+
+

+Version 0.1-7

+
    +
  • Had to do a substantial re-formatting of the documentation due to incompatibilities introduced in 1.8.0 S4 method documentation. The contents were not changed (modulo fixing a few typos). Thanks to Kurt Hornik and John Chambers for their help.
  • +
+
+
+

+Version 0.1-6

+
    +
  • Trivial documentation changes (for R CMD check’s sake)
  • +
+
+
+

+Version 0.1-5

+
    +
  • Removed duplicated setGeneric(“dbSetDataMappings”)
  • +
+
+
+

+Version 0.1-4

+
    +
  • Removed the “valueClass” from some generic functions, namely, dbListConnections, dbListResults, dbGetException, dbGetQuery, and dbGetInfo. The reason is that methods for these generics could potentially return different classes of objects (e.g., the call dbGetInfo(res) could return a list of name-value pairs, while dbGetInfo(res, “statement”) could be a character vector).

  • +
  • Added 00Index to inst/doc

  • +
  • Added dbGetDBIVersion() (simple wrapper to package.description).

  • +
+
+
+

+Version 0.1-3

+
    +
  • ??? Minor changes?
  • +
+
+
+

+Version 0.1-2

+
    +
  • An implementation based on version 4 classes and methods.
  • +
  • Incorporated (mostly Tim Keitt’s) comments.
  • +
+
+
+
+ + + +
+ +
+ + +
+

Site built with pkgdown.

+
+ +
+
+ + + diff --git a/docs/pkgdown.css b/docs/pkgdown.css new file mode 100644 index 000000000..209ce57fe --- /dev/null +++ b/docs/pkgdown.css @@ -0,0 +1,163 @@ +/* Sticker footer */ +body > .container { + display: flex; + padding-top: 60px; + min-height: calc(100vh); + flex-direction: column; +} + +body > .container .row { + flex: 1; +} + +footer { + margin-top: 45px; + padding: 35px 0 36px; + border-top: 1px solid #e5e5e5; + color: #666; + display: flex; +} +footer p { + margin-bottom: 0; +} +footer div { + flex: 1; +} +footer .pkgdown { + text-align: right; +} +footer p { + margin-bottom: 0; +} + +img.icon { + float: right; +} + +img { + max-width: 100%; +} + +/* Section anchors ---------------------------------*/ + +a.anchor { + margin-left: -30px; + display:inline-block; + width: 30px; + height: 30px; + visibility: hidden; + + background-image: url(./link.svg); + background-repeat: no-repeat; + background-size: 20px 20px; + background-position: center center; +} + +.hasAnchor:hover a.anchor { + visibility: visible; +} + +@media (max-width: 767px) { + .hasAnchor:hover a.anchor { + visibility: hidden; + } +} + + +/* Fixes for fixed navbar --------------------------*/ + +.contents h1, .contents h2, .contents h3, .contents h4 { + padding-top: 60px; + margin-top: -60px; +} + +/* Static header placement on mobile devices */ +@media (max-width: 767px) { + .navbar-fixed-top { + position: absolute; + } + .navbar { + padding: 0; + } +} + + +/* Sidebar --------------------------*/ + +#sidebar { + margin-top: 30px; +} +#sidebar h2 { + font-size: 1.5em; + margin-top: 1em; +} + +#sidebar h2:first-child { + margin-top: 0; +} + +#sidebar .list-unstyled li { + margin-bottom: 0.5em; +} + +/* Reference index & topics ----------------------------------------------- */ + +.ref-index th {font-weight: normal;} +.ref-index h2 {font-size: 20px;} + +.ref-index td {vertical-align: top;} +.ref-index .alias {width: 40%;} +.ref-index .title {width: 60%;} + +.ref-index .alias {width: 40%;} +.ref-index .title {width: 60%;} + +.ref-arguments th {text-align: right; padding-right: 10px;} +.ref-arguments th, .ref-arguments td {vertical-align: top;} +.ref-arguments .name {width: 20%;} +.ref-arguments .desc {width: 80%;} + +/* Nice scrolling for wide elements --------------------------------------- */ + +table { + display: block; + overflow: auto; +} + +/* Syntax highlighting ---------------------------------------------------- */ + +pre { + word-wrap: normal; + word-break: normal; + border: 1px solid #eee; +} + +pre, code { + background-color: #f8f8f8; + color: #333; +} + +pre .img { + margin: 5px 0; +} + +pre .img img { + background-color: #fff; + display: block; + height: auto; +} + +code a, pre a { + color: #375f84; +} + +.fl {color: #1514b5;} +.fu {color: #000000;} /* function */ +.ch,.st {color: #036a07;} /* string */ +.kw {color: #264D66;} /* keyword */ +.co {color: #888888;} /* comment */ + +.message { color: black; font-weight: bolder;} +.error { color: orange; font-weight: bolder;} +.warning { color: #6A0366; font-weight: bolder;} + diff --git a/docs/pkgdown.js b/docs/pkgdown.js new file mode 100644 index 000000000..4b8171328 --- /dev/null +++ b/docs/pkgdown.js @@ -0,0 +1,45 @@ +$(function() { + $("#sidebar").stick_in_parent({offset_top: 40}); + $('body').scrollspy({ + target: '#sidebar', + offset: 60 + }); + + var cur_path = paths(location.pathname); + $("#navbar ul li a").each(function(index, value) { + if (value.text == "Home") + return; + if (value.getAttribute("href") === "#") + return; + + var path = paths(value.pathname); + if (is_prefix(cur_path, path)) { + // Add class to parent
  • , and enclosing
  • if in dropdown + var menu_anchor = $(value); + menu_anchor.parent().addClass("active"); + menu_anchor.closest("li.dropdown").addClass("active"); + } + }); +}); + +function paths(pathname) { + var pieces = pathname.split("/"); + pieces.shift(); // always starts with / + + var end = pieces[pieces.length - 1]; + if (end === "index.html" || end === "") + pieces.pop(); + return(pieces); +} + +function is_prefix(needle, haystack) { + if (needle.length > haystack.lengh) + return(false); + + for (var i = 0; i < haystack.length; i++) { + if (needle[i] != haystack[i]) + return(false); + } + + return(true); +} diff --git a/docs/reference/ANSI.html b/docs/reference/ANSI.html new file mode 100644 index 000000000..396d20a5f --- /dev/null +++ b/docs/reference/ANSI.html @@ -0,0 +1,138 @@ + + + + + + + + +A dummy DBI connector that simulates ANSI-SQL compliance — ANSI • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    A dummy DBI connector that simulates ANSI-SQL compliance

    + + +
    ANSI()
    + + +

    Examples

    +
    ANSI()
    #> <AnsiConnection>
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/DBI-package.html b/docs/reference/DBI-package.html new file mode 100644 index 000000000..50091dffe --- /dev/null +++ b/docs/reference/DBI-package.html @@ -0,0 +1,206 @@ + + + + + + + + +DBI: R Database Interface — DBI-package • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    DBI defines an interface for communication between R and relational database +management systems. +All classes in this package are virtual and need to be extended by +the various R/DBMS implementations (so-called DBI backends).

    + + + +

    Definition

    + + +

    A DBI backend is an R package +which imports the DBI +and methods +packages. +For better or worse, the names of many existing backends start with +‘R’, e.g., RSQLite, RMySQL, RSQLServer; it is up +to the backend author to adopt this convention or not.

    + +

    DBI classes and methods

    + + +

    A backend defines three classes, +which are subclasses of +DBIDriver, +DBIConnection, +and DBIResult. +The backend provides implementation for all methods +of these base classes +that are defined but not implemented by DBI. +All methods defined in DBI are reexported (so that the package can +be used without having to attach DBI), +and have an ellipsis ... in their formals for extensibility.

    + +

    Construction of the DBIDriver object

    + + +

    The backend must support creation of an instance of its DBIDriver +subclass +with a constructor function. +By default, its name is the package name without the leading ‘R’ +(if it exists), e.g., SQLite for the RSQLite package. +However, backend authors may choose a different name. +The constructor must be exported, and +it must be a function +that is callable without arguments. +DBI recommends to define a constructor with an empty argument list.

    + +

    See also

    + +

    Important generics: dbConnect(), dbGetQuery(), +dbReadTable(), dbWriteTable(), dbDisconnect()

    +

    Formal specification (currently work in progress and incomplete): +vignette("spec", package = "DBI")

    + + +

    Examples

    +
    RSQLite::SQLite()
    #> <SQLiteDriver>
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/DBIConnection-class.html b/docs/reference/DBIConnection-class.html new file mode 100644 index 000000000..c0c2513ec --- /dev/null +++ b/docs/reference/DBIConnection-class.html @@ -0,0 +1,171 @@ + + + + + + + + +DBIConnection class — DBIConnection-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This virtual class encapsulates the connection to a DBMS, and it provides +access to dynamic queries, result sets, DBMS session management +(transactions), etc.

    + + + +

    Implementation note

    + + +

    Individual drivers are free to implement single or multiple simultaneous +connections.

    + +

    See also

    + +

    Other DBI classes: DBIDriver-class, + DBIObject-class, + DBIResult-class

    +

    Other DBIConnection generics: dbDataType, + dbDisconnect, dbExecute, + dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") +con
    #> <SQLiteConnection> +#> Path: :memory: +#> Extensions: TRUE
    # NOT RUN { +con <- dbConnect(RPostgreSQL::PostgreSQL(), "username", "passsword") +con +dbDisconnect(con) +# }
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/DBIDriver-class.html b/docs/reference/DBIDriver-class.html new file mode 100644 index 000000000..d4032354c --- /dev/null +++ b/docs/reference/DBIDriver-class.html @@ -0,0 +1,149 @@ + + + + + + + + +DBIDriver class — DBIDriver-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Base class for all DBMS drivers (e.g., RSQLite, MySQL, PostgreSQL). +The virtual class DBIDriver defines the operations for creating +connections and defining data type mappings. Actual driver classes, for +instance RPgSQL, RMySQL, etc. implement these operations in a +DBMS-specific manner.

    + + + +

    See also

    + +

    Other DBI classes: DBIConnection-class, + DBIObject-class, + DBIResult-class

    +

    Other DBIDriver generics: dbConnect, + dbDataType, dbDriver, + dbGetInfo, dbIsValid, + dbListConnections

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/DBIObject-class.html b/docs/reference/DBIObject-class.html new file mode 100644 index 000000000..b624f57d7 --- /dev/null +++ b/docs/reference/DBIObject-class.html @@ -0,0 +1,179 @@ + + + + + + + + +DBIObject class — DBIObject-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Base class for all other DBI classes (e.g., drivers, connections). This +is a virtual Class: No objects may be created from it.

    + + + +

    Details

    + +

    More generally, the DBI defines a very small set of classes and generics that +allows users and applications access DBMS with a common interface. The +virtual classes are DBIDriver that individual drivers extend, +DBIConnection that represent instances of DBMS connections, and +DBIResult that represent the result of a DBMS statement. These three +classes extend the basic class of DBIObject, which serves as the root +or parent of the class hierarchy.

    + +

    Implementation notes

    + + +

    An implementation MUST provide methods for the following generics:

      +
    • dbGetInfo().

    • +
    +

    It MAY also provide methods for:

      +
    • summary(). Print a concise description of the +object. The default method invokes dbGetInfo(dbObj) and prints +the name-value pairs one per line. Individual implementations may +tailor this appropriately.

    • +
    + +

    See also

    + +

    Other DBI classes: DBIConnection-class, + DBIDriver-class, + DBIResult-class

    + + +

    Examples

    +
    drv <- RSQLite::SQLite() +con <- dbConnect(drv) + +rs <- dbSendQuery(con, "SELECT 1") +is(drv, "DBIObject") ## True
    #> [1] TRUE
    is(con, "DBIObject") ## True
    #> [1] TRUE
    is(rs, "DBIObject")
    #> [1] TRUE
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/DBIResult-class.html b/docs/reference/DBIResult-class.html new file mode 100644 index 000000000..809fd2c33 --- /dev/null +++ b/docs/reference/DBIResult-class.html @@ -0,0 +1,164 @@ + + + + + + + + +DBIResult class — DBIResult-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This virtual class describes the result and state of execution of +a DBMS statement (any statement, query or non-query). The result set +keeps track of whether the statement produces output how many rows were +affected by the operation, how many rows have been fetched (if statement is +a query), whether there are more rows to fetch, etc.

    + + + +

    Implementation notes

    + + +

    Individual drivers are free to allow single or multiple +active results per connection.

    +

    The default show method displays a summary of the query using other +DBI generics.

    + +

    See also

    + +

    Other DBI classes: DBIConnection-class, + DBIDriver-class, + DBIObject-class

    +

    Other DBIResult generics: dbBind, + dbClearResult, dbColumnInfo, + dbFetch, dbGetInfo, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/SQL.html b/docs/reference/SQL.html new file mode 100644 index 000000000..37da2e0fe --- /dev/null +++ b/docs/reference/SQL.html @@ -0,0 +1,189 @@ + + + + + + + + +SQL quoting — SQL • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This set of classes and generics make it possible to flexibly deal with SQL +escaping needs. By default, any user supplied input to a query should be +escaped using either dbQuoteIdentifier() or dbQuoteString() +depending on whether it refers to a table or variable name, or is a literal +string. +These functions may return an object of the SQL class, +which tells DBI functions that a character string does not need to be escaped +anymore, to prevent double escaping. +The SQL class has associated the SQL() constructor function.

    + + +
    SQL(x, ..., names = NULL)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    x

    A character vector to label as being escaped SQL.

    ...

    Other arguments passed on to methods. Not otherwise used.

    names

    Names for the returned object, must have the same length as x.

    + +

    Value

    + +

    An object of class SQL.

    + +

    Implementation notes

    + + +

    DBI provides default generics for SQL-92 compatible quoting. If the database +uses a different convention, you will need to provide your own methods. +Note that because of the way that S4 dispatch finds methods and because +SQL inherits from character, if you implement (e.g.) a method for +dbQuoteString(MyConnection, character), you will also need to +implement dbQuoteString(MyConnection, SQL) - this should simply +return x unchanged.

    + + +

    Examples

    +
    dbQuoteIdentifier(ANSI(), "SELECT")
    #> <SQL> "SELECT"
    dbQuoteString(ANSI(), "SELECT")
    #> <SQL> 'SELECT'
    +# SQL vectors are always passed through as is +var_name <- SQL("SELECT") +var_name
    #> <SQL> SELECT
    +dbQuoteIdentifier(ANSI(), var_name)
    #> <SQL> SELECT
    dbQuoteString(ANSI(), var_name)
    #> <SQL> SELECT
    +# This mechanism is used to prevent double escaping +dbQuoteString(ANSI(), dbQuoteString(ANSI(), "SELECT"))
    #> <SQL> 'SELECT'
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/Table.html b/docs/reference/Table.html new file mode 100644 index 000000000..3f478daef --- /dev/null +++ b/docs/reference/Table.html @@ -0,0 +1,147 @@ + + + + + + + + +Refer to a table nested in a hierarchy (e.g. within a schema) — Table-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Refer to a table nested in a hierarchy (e.g. within a schema)

    + + +
    Table(...)
    + +

    Arguments

    + + + + + + +
    ...

    Components of the hierarchy, e.g. schema, table, +or cluster, catalog, schema, table. +For more on these concepts, see +http://stackoverflow.com/questions/7022755/

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbBind.html b/docs/reference/dbBind.html new file mode 100644 index 000000000..5989447c3 --- /dev/null +++ b/docs/reference/dbBind.html @@ -0,0 +1,323 @@ + + + + + + + + +Bind values to a parameterized/prepared statement — dbBind • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    For parametrized or prepared statements, +the dbSendQuery() and dbSendStatement() functions can be called with +statements that contain placeholders for values. The dbBind() function +binds these placeholders +to actual values, and is intended to be called on the result set +before calling dbFetch() or dbGetRowsAffected().

    + + +
    dbBind(res, params, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    params

    A list of bindings, named or unnamed.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbBind() returns the result set, +invisibly, +for queries issued by dbSendQuery() +and also for data manipulation statements issued by +dbSendStatement(). +Calling dbBind() for a query without parameters +raises an error. +Binding too many +or not enough values, +or parameters with wrong names +or unequal length, +also raises an error. +If the placeholders in the query are named, +all parameter values must have names +(which must not be empty +or NA), +and vice versa, +otherwise an error is raised. +The behavior for mixing placeholders of different types +(in particular mixing positional and named placeholders) +is not specified.

    +

    Calling dbBind() on a result set already cleared by dbClearResult() +also raises an error.

    + +

    Details

    + +

    DBI supports parametrized (or prepared) queries and statements +via the dbBind() generic. +Parametrized queries are different from normal queries +in that they allow an arbitrary number of placeholders, +which are later substituted by actual values. +Parametrized queries (and statements) serve two purposes:

      +
    • The same query can be executed more than once with different values. +The DBMS may cache intermediate information for the query, +such as the execution plan, +and execute it faster.

    • +
    • Separation of query syntax and parameters protects against SQL injection.

    • +
    +

    The placeholder format is currently not specified by DBI; +in the future, a uniform placeholder syntax may be supported. +Consult the backend documentation for the supported formats. +For automated testing, backend authors specify the placeholder syntax with +the placeholder_pattern tweak. +Known examples are:

      +
    • ? (positional matching in order of appearance) in RMySQL and RSQLite

    • +
    • $1 (positional matching by index) in RPostgres and RSQLite

    • +
    • :name and $name (named matching) in RSQLite

    • +
    + +

    Specification

    + + +

    DBI clients execute parametrized statements as follows:

      +
    1. Call dbSendQuery() or dbSendStatement() with a query or statement +that contains placeholders, +store the returned DBIResult object in a variable. +Mixing placeholders (in particular, named and unnamed ones) is not +recommended. +It is good practice to register a call to dbClearResult() via +on.exit() right after calling dbSendQuery() or dbSendStatement() +(see the last enumeration item). +Until dbBind() has been called, the returned result set object has the +following behavior:

    2. +
    3. Construct a list with parameters +that specify actual values for the placeholders. +The list must be named or unnamed, +depending on the kind of placeholders used. +Named values are matched to named parameters, unnamed values +are matched by position in the list of parameters. +All elements in this list must have the same lengths and contain values +supported by the backend; a data.frame is internally stored as such +a list. +The parameter list is passed to a call to dbBind() on the DBIResult +object.

    4. +
    5. Retrieve the data or the number of affected rows from the DBIResult object.

        +
      • For queries issued by dbSendQuery(), +call dbFetch().

      • +
      • For statements issued by dbSendStatements(), +call dbGetRowsAffected(). +(Execution begins immediately after the dbBind() call, +the statement is processed entirely before the function returns.)

      • +
    6. +
    7. Repeat 2. and 3. as necessary.

    8. +
    9. Close the result set via dbClearResult().

    10. +
    +

    The elements of the params argument do not need to be scalars, +vectors of arbitrary length +(including length 0) +are supported. +For queries, calling dbFetch() binding such parameters returns +concatenated results, equivalent to binding and fetching for each set +of values and connecting via rbind(). +For data manipulation statements, dbGetRowsAffected() returns the +total number of rows affected if binding non-scalar parameters. +dbBind() also accepts repeated calls on the same result set +for both queries +and data manipulation statements, +even if no results are fetched between calls to dbBind().

    +

    At least the following data types are accepted on input (including NA):

      +
    • integer

    • +
    • numeric

    • +
    • logical for Boolean values

    • +
    • character

    • +
    • factor (bound as character, +with warning)

    • +
    • Date

    • +
    • POSIXct timestamps

    • +
    • POSIXlt timestamps

    • +
    • lists of raw for blobs (with NULL entries for SQL NULL values)

    • +
    • objects of type blob::blob

    • +
    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbClearResult, dbColumnInfo, + dbFetch, dbGetInfo, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:")
    #> Warning: replacing previous import ‘DBI::.__C__oldClass’ by ‘methods::.__C__oldClass’ when loading ‘RSQLite’
    #> Warning: replacing previous import ‘DBI::coerce’ by ‘methods::coerce’ when loading ‘RSQLite’
    #> Warning: replacing previous import ‘DBI::.__C__character’ by ‘methods::.__C__character’ when loading ‘RSQLite’
    #> Warning: replacing previous import ‘DBI::.__C__vector’ by ‘methods::.__C__vector’ when loading ‘RSQLite’
    +dbWriteTable(con, "iris", iris) + +# Using the same query for different values +iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > ?") +dbBind(iris_result, list(2.3)) +dbFetch(iris_result)
    #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 6.3 3.3 6.0 2.5 virginica +#> 2 7.2 3.6 6.1 2.5 virginica +#> 3 5.8 2.8 5.1 2.4 virginica +#> 4 6.3 3.4 5.6 2.4 virginica +#> 5 6.7 3.1 5.6 2.4 virginica +#> 6 6.7 3.3 5.7 2.5 virginica
    dbBind(iris_result, list(3)) +dbFetch(iris_result)
    #> [1] Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> <0 rows> (or 0-length row.names)
    dbClearResult(iris_result) + +# Executing the same statement with different values at once +iris_result <- dbSendStatement(con, "DELETE FROM iris WHERE [Species] = $species") +dbBind(iris_result, list(species = c("setosa", "versicolor", "unknown"))) +dbGetRowsAffected(iris_result)
    #> [1] 100
    dbClearResult(iris_result) + +nrow(dbReadTable(con, "iris"))
    #> [1] 50
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbCallProc.html b/docs/reference/dbCallProc.html new file mode 100644 index 000000000..9f81afc12 --- /dev/null +++ b/docs/reference/dbCallProc.html @@ -0,0 +1,149 @@ + + + + + + + + +Call an SQL stored procedure — dbCallProc • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    DEPRECATED

    + + +
    dbCallProc(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbClearResult.html b/docs/reference/dbClearResult.html new file mode 100644 index 000000000..5dca9a184 --- /dev/null +++ b/docs/reference/dbClearResult.html @@ -0,0 +1,200 @@ + + + + + + + + +Clear a result set — dbClearResult • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Frees all resources (local and remote) associated with a result set. In some +cases (e.g., very large result sets) this can be a critical step to avoid +exhausting resources (memory, file descriptors, etc.) + +

    Methods in other packages

    + +
      +
    • RSQLite::dbClearResult("SQLiteResult")

    • +

    + + +
    dbClearResult(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbClearResult() returns TRUE, invisibly, for result sets obtained from +both dbSendQuery() +and dbSendStatement(). +An attempt to close an already closed result set issues a warning +in both cases.

    + +

    Specification

    + + +

    dbClearResult() frees all resources associated with retrieving +the result of a query or update operation. +The DBI backend can expect a call to dbClearResult() for each +dbSendQuery() or dbSendStatement() call.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbColumnInfo, + dbFetch, dbGetInfo, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +rs <- dbSendQuery(con, "SELECT 1") +print(dbFetch(rs))
    #> 1 +#> 1 1
    +dbClearResult(rs) +dbDisconnect(con)
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbColumnInfo.html b/docs/reference/dbColumnInfo.html new file mode 100644 index 000000000..ac6445bf4 --- /dev/null +++ b/docs/reference/dbColumnInfo.html @@ -0,0 +1,187 @@ + + + + + + + + +Information about result types — dbColumnInfo • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Produces a data.frame that describes the output of a query. The data.frame +should have as many rows as there are output fields in the result set, and +each column in the data.frame should describe an aspect of the result set +field (field name, type, etc.)

    + + +
    dbColumnInfo(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    A data.frame with one row per output field in res. Methods +MUST include name, field.type (the SQL type), +and data.type (the R data type) columns, and MAY contain other +database specific information like scale and precision or whether the +field can store NULLs.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbFetch, dbGetInfo, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +rs <- dbSendQuery(con, "SELECT 1 AS a, 2 AS b") +dbColumnInfo(rs)
    #> name type +#> 1 a integer +#> 2 b integer
    #> a b +#> 1 1 2
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbConnect.html b/docs/reference/dbConnect.html new file mode 100644 index 000000000..aa855209f --- /dev/null +++ b/docs/reference/dbConnect.html @@ -0,0 +1,211 @@ + + + + + + + + +Create a connection to a DBMS — dbConnect • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Connect to a DBMS going through the appropriate authentication procedure. +Some implementations may allow you to have multiple connections open, so you +may invoke this function repeatedly assigning its output to different +objects. +The authentication mechanism is left unspecified, so check the +documentation of individual drivers for details. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbConnect("SQLiteConnection")

    • +
    • RSQLite::dbConnect("SQLiteDriver")

    • +

    + + +
    dbConnect(drv, ...)
    + +

    Arguments

    + + + + + + + + + + +
    drv

    an object that inherits from DBIDriver, +or an existing DBIConnection +object (in order to clone an existing connection).

    ...

    authentication arguments needed by the DBMS instance; these +typically include user, password, host, port, dbname, etc. +For details see the appropriate DBIDriver.

    + +

    Value

    + +

    dbConnect() returns an S4 object that inherits from DBIConnection. +This object is used to communicate with the database engine.

    + +

    Specification

    + + +

    DBI recommends using the following argument names for authentication +parameters, with NULL default:

      +
    • user for the user name (default: current user)

    • +
    • password for the password

    • +
    • host for the host name (default: local connection)

    • +
    • port for the port number (default: local connection)

    • +
    • dbname for the name of the database on the host, or the database file +name

    • +
    +

    The defaults should provide reasonable behavior, in particular a +local connection for host = NULL. For some DBMS (e.g., PostgreSQL), +this is different to a TCP/IP connection to localhost.

    + +

    See also

    + +

    dbDisconnect() to disconnect from a database.

    +

    Other DBIDriver generics: DBIDriver-class, + dbDataType, dbDriver, + dbGetInfo, dbIsValid, + dbListConnections

    + + +

    Examples

    +
    # SQLite only needs a path to the database. (Here, ":memory:" is a special +# path that creates an in-memory database.) Other database drivers +# will require more details (like user, password, host, port, etc.) +con <- dbConnect(RSQLite::SQLite(), ":memory:") +con
    #> <SQLiteConnection> +#> Path: :memory: +#> Extensions: TRUE
    #> character(0)
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbDataType.html b/docs/reference/dbDataType.html new file mode 100644 index 000000000..81e169f71 --- /dev/null +++ b/docs/reference/dbDataType.html @@ -0,0 +1,254 @@ + + + + + + + + +Determine the SQL data type of an object — dbDataType • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns an SQL string that describes the SQL data type to be used for an +object. +The default implementation of this generic determines the SQL type of an +R object according to the SQL 92 specification, which may serve as a starting +point for driver implementations. DBI also provides an implementation +for data.frame which will return a character vector giving the type for each +column in the dataframe. + +

    Methods in other packages

    + +

    + + +
    dbDataType(dbObj, obj, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    dbObj

    A object inheriting from DBIDriver +or DBIConnection

    obj

    An R object whose SQL type we want to determine.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbDataType() returns the SQL type that corresponds to the obj argument +as a non-empty +character string. +For data frames, a character vector with one element per column +is returned. +An error is raised for invalid values for the obj argument such as a +NULL value.

    + +

    Details

    + +

    The data types supported by databases are different than the data types in R, +but the mapping between the primitive types is straightforward:

      +
    • Any of the many fixed and varying length character types are mapped to +character vectors

    • +
    • Fixed-precision (non-IEEE) numbers are mapped into either numeric or +integer vectors.

    • +
    +

    Notice that many DBMS do not follow IEEE arithmetic, so there are potential +problems with under/overflows and loss of precision.

    + +

    Specification

    + + +

    The backend can override the dbDataType() generic +for its driver class.

    +

    This generic expects an arbitrary object as second argument. +To query the values returned by the default implementation, +run example(dbDataType, package = "DBI"). +If the backend needs to override this generic, +it must accept all basic R data types as its second argument, namely +logical, +integer, +numeric, +character, +dates (see Dates), +date-time (see DateTimeClasses), +and difftime. +If the database supports blobs, +this method also must accept lists of raw vectors, +and blob::blob objects. +As-is objects (i.e., wrapped by I()) must be +supported and return the same results as their unwrapped counterparts. +The SQL data type for factor +and ordered is the same as for character. +The behavior for other object types is not specified.

    +

    All data types returned by dbDataType() are usable in an SQL statement +of the form +"CREATE TABLE test (a ...)".

    + +

    See also

    + +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDriver, + dbGetInfo, dbIsValid, + dbListConnections

    +

    Other DBIConnection generics: DBIConnection-class, + dbDisconnect, dbExecute, + dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

    + + +

    Examples

    +
    dbDataType(ANSI(), 1:5)
    #> [1] "INT"
    dbDataType(ANSI(), 1)
    #> [1] "DOUBLE"
    dbDataType(ANSI(), TRUE)
    #> [1] "SMALLINT"
    dbDataType(ANSI(), Sys.Date())
    #> [1] "DATE"
    dbDataType(ANSI(), Sys.time())
    #> [1] "TIMESTAMP"
    dbDataType(ANSI(), Sys.time() - as.POSIXct(Sys.Date()))
    #> [1] "TIME"
    dbDataType(ANSI(), c("x", "abc"))
    #> [1] "TEXT"
    dbDataType(ANSI(), list(raw(10), raw(20)))
    #> [1] "BLOB"
    dbDataType(ANSI(), I(3))
    #> [1] "DOUBLE"
    +dbDataType(ANSI(), iris)
    #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> "DOUBLE" "DOUBLE" "DOUBLE" "DOUBLE" "TEXT"
    +con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbDataType(con, 1:5)
    #> [1] "INTEGER"
    dbDataType(con, 1)
    #> [1] "REAL"
    dbDataType(con, TRUE)
    #> [1] "INTEGER"
    dbDataType(con, Sys.Date())
    #> [1] "REAL"
    dbDataType(con, Sys.time())
    #> [1] "REAL"
    dbDataType(con, Sys.time() - as.POSIXct(Sys.Date()))
    #> [1] "REAL"
    dbDataType(con, c("x", "abc"))
    #> [1] "TEXT"
    dbDataType(con, list(raw(10), raw(20)))
    #> [1] "BLOB"
    dbDataType(con, I(3))
    #> [1] "REAL"
    +dbDataType(con, iris)
    #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> "DOUBLE" "DOUBLE" "DOUBLE" "DOUBLE" "TEXT"
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbDisconnect.html b/docs/reference/dbDisconnect.html new file mode 100644 index 000000000..44323f747 --- /dev/null +++ b/docs/reference/dbDisconnect.html @@ -0,0 +1,193 @@ + + + + + + + + +Disconnect (close) a connection — dbDisconnect • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This closes the connection, discards all pending work, and frees +resources (e.g., memory, sockets). + +

    Methods in other packages

    + +
      +
    • RSQLite::dbDisconnect("SQLiteConnection")

    • +

    + + +
    dbDisconnect(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbDisconnect() returns TRUE, invisibly.

    + +

    Specification

    + + +

    A warning is issued on garbage collection when a connection has been +released without calling dbDisconnect(), +but this cannot be tested automatically. +A warning is issued immediately when calling dbDisconnect() on an +already disconnected +or invalid connection.

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbExecute, + dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") +dbDisconnect(con)
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbDriver.html b/docs/reference/dbDriver.html new file mode 100644 index 000000000..bee942a65 --- /dev/null +++ b/docs/reference/dbDriver.html @@ -0,0 +1,205 @@ + + + + + + + + +Load and unload database drivers — dbDriver • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    These methods are deprecated, please consult the documentation of the +individual backends for the construction of driver instances. + + dbDriver() is a helper method used to create an new driver object +given the name of a database or the corresponding R package. It works +through convention: all DBI-extending packages should provide an exported +object with the same name as the package. dbDriver() just looks for +this object in the right places: if you know what database you are connecting +to, you should call the function directly. + + dbUnloadDriver() is not implemented for modern backends.

    + + +
    dbDriver(drvName, ...)
    +
    +dbUnloadDriver(drv, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    drvName

    character name of the driver to instantiate.

    ...

    any other arguments are passed to the driver drvName.

    drv

    an object that inherits from DBIDriver as created by +dbDriver.

    + +

    Value

    + +

    In the case of dbDriver, an driver object whose class extends +DBIDriver. This object may be used to create connections to the +actual DBMS engine.

    +

    In the case of dbUnloadDriver, a logical indicating whether the +operation succeeded or not.

    + +

    Details

    + +

    The client part of the database communication is +initialized (typically dynamically loading C code, etc.) but note that +connecting to the database engine itself needs to be done through calls to +dbConnect.

    + +

    See also

    + +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDataType, + dbGetInfo, dbIsValid, + dbListConnections

    +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDataType, + dbGetInfo, dbIsValid, + dbListConnections

    + + +

    Examples

    +
    # Create a RSQLite driver with a string +d <- dbDriver("SQLite") +d
    #> <SQLiteDriver>
    +# But better, access the object directly +RSQLite::SQLite()
    #> <SQLiteDriver>
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbExecute.html b/docs/reference/dbExecute.html new file mode 100644 index 000000000..6172f28ef --- /dev/null +++ b/docs/reference/dbExecute.html @@ -0,0 +1,218 @@ + + + + + + + + +Execute an update statement, query number of rows affected, and then close result set — dbExecute • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Executes a statement and returns the number of rows affected. +dbExecute() comes with a default implementation +(which should work with most backends) that calls +dbSendStatement(), then dbGetRowsAffected(), ensuring that +the result is always free-d by dbClearResult(). + +

    Methods in other packages

    + +

    + + +
    dbExecute(conn, statement, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    statement

    a character string containing SQL.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbExecute() always returns a +scalar +numeric +that specifies the number of rows affected +by the statement. +An error is raised when issuing a statement over a closed +or invalid connection, +if the syntax of the statement is invalid, +or if the statement is not a non-NA string.

    + +

    Implementation notes

    + + +

    Subclasses should override this method only if they provide some sort of +performance optimization.

    + +

    See also

    + +

    For queries: dbSendQuery() and dbGetQuery().

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "cars", head(cars, 3)) +dbReadTable(con, "cars") # there are 3 rows
    #> speed dist +#> 1 4 2 +#> 2 4 10 +#> 3 7 4
    dbExecute(con, + "INSERT INTO cars (speed, dist) VALUES (1, 1), (2, 2), (3, 3);")
    #> [1] 3
    dbReadTable(con, "cars") # there are now 6 rows
    #> speed dist +#> 1 4 2 +#> 2 4 10 +#> 3 7 4 +#> 4 1 1 +#> 5 2 2 +#> 6 3 3
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbExistsTable.html b/docs/reference/dbExistsTable.html new file mode 100644 index 000000000..810419338 --- /dev/null +++ b/docs/reference/dbExistsTable.html @@ -0,0 +1,217 @@ + + + + + + + + +Does a table exist? — dbExistsTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns if a table given by name exists in the database. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbExistsTable("SQLiteConnection", "character")

    • +

    + + +
    dbExistsTable(conn, name, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    name

    A character string specifying a DBMS table name.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbExistsTable() returns a logical scalar, TRUE if the table or view +specified by the name argument exists, FALSE otherwise. +This includes temporary tables if supported by the database.

    +

    An error is raised when calling this method for a closed +or invalid connection. +An error is also raised +if name cannot be processed with dbQuoteIdentifier() +or if this results in a non-scalar.

    + +

    Additional arguments

    + + +

    TBD: temporary = NA

    +

    This must be provided as named argument. +See the "Specification" section for details on their usage.

    + +

    Specification

    + + +

    The name argument is processed as follows, +to support databases that allow non-syntactic names for their objects:

    +

    For all tables listed by dbListTables(), dbExistsTable() returns TRUE.

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbGetException, + dbGetInfo, dbGetQuery, + dbIsValid, dbListFields, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbExistsTable(con, "iris")
    #> [1] FALSE
    dbWriteTable(con, "iris", iris) +dbExistsTable(con, "iris")
    #> [1] TRUE
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbFetch.html b/docs/reference/dbFetch.html new file mode 100644 index 000000000..6befbf8b8 --- /dev/null +++ b/docs/reference/dbFetch.html @@ -0,0 +1,305 @@ + + + + + + + + +Fetch records from a previously executed query — dbFetch • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Fetch the next n elements (rows) from the result set and return them +as a data.frame. + +

    Methods in other packages

    + +

    + + +
    dbFetch(res, n = -1, ...)
    +
    +fetch(res, n = -1, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    res

    An object inheriting from DBIResult, created by +dbSendQuery().

    n

    maximum number of records to retrieve per fetch. Use n = -1 +or n = Inf +to retrieve all pending records. Some implementations may recognize other +special values.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbFetch() always returns a data.frame +with as many rows as records were fetched and as many +columns as fields in the result set, +even if the result is a single value +or has one +or zero rows. +An attempt to fetch from a closed result set raises an error. +If the n argument is not an atomic whole number +greater or equal to -1 or Inf, an error is raised, +but a subsequent call to dbFetch() with proper n argument succeeds. +Calling dbFetch() on a result set from a data manipulation query +created by dbSendStatement() +can be fetched and return an empty data frame, with a warning.

    + +

    Details

    + +

    fetch() is provided for compatibility with older DBI clients - for all +new code you are strongly encouraged to use dbFetch(). The default +implementation for dbFetch() calls fetch() so that it is compatible with +existing code. Modern backends should implement for dbFetch() only.

    + +

    Specification

    + + +

    Fetching multi-row queries with one +or more columns by default returns the entire result. +Multi-row queries can also be fetched progressively +by passing a whole number (integer +or numeric) +as the n argument. +A value of Inf for the n argument is supported +and also returns the full result. +If more rows than available are fetched, the result is returned in full +without warning. +If fewer rows than requested are returned, further fetches will +return a data frame with zero rows. +If zero rows are fetched, the columns of the data frame are still fully +typed. +Fetching fewer rows than available is permitted, +no warning is issued when clearing the result set.

    +

    A column named row_names is treated like any other column.

    +

    The column types of the returned data frame depend on the data returned:

      +
    • integer (or coercible to an integer) for integer values between -2^31 and 2^31 - 1, +with NA for SQL NULL values

    • +
    • numeric for numbers with a fractional component, +with NA for SQL NULL values

    • +
    • logical for Boolean values (some backends may return an integer); +with NA for SQL NULL values

    • +
    • character for text, +with NA for SQL NULL values

    • +
    • lists of raw for blobs +with NULL entries for SQL NULL values

    • +
    • coercible using as.Date() for dates, +with NA for SQL NULL values +(also applies to the return value of the SQL function current_date)

    • +
    • coercible using hms::as.hms() for times, +with NA for SQL NULL values +(also applies to the return value of the SQL function current_time)

    • +
    • coercible using as.POSIXct() for timestamps, +with NA for SQL NULL values +(also applies to the return value of the SQL function current_timestamp)

    • +
    +

    If dates and timestamps are supported by the backend, the following R types are +used:

      +
    • Date for dates +(also applies to the return value of the SQL function current_date)

    • +
    • POSIXct for timestamps +(also applies to the return value of the SQL function current_timestamp)

    • +
    +

    R has no built-in type with lossless support for the full range of 64-bit +or larger integers. If 64-bit integers are returned from a query, +the following rules apply:

      +
    • Values are returned in a container with support for the full range of +valid 64-bit values (such as the integer64 class of the bit64 +package)

    • +
    • Coercion to numeric always returns a number that is as close as possible +to the true value

    • +
    • Loss of precision when converting to numeric gives a warning

    • +
    • Conversion to character always returns a lossless decimal representation +of the data

    • +
    + +

    See also

    + +

    Close the result set with dbClearResult() as soon as you +finish retrieving the records you want.

    +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbGetInfo, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) + +# Fetch all results +rs <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4") +dbFetch(rs)
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 2 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 3 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 4 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 +#> 5 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 +#> 6 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 +#> 7 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 +#> 8 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 +#> 9 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 +#> 10 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 +#> 11 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
    dbClearResult(rs) + +# Fetch in chunks +rs <- dbSendQuery(con, "SELECT * FROM mtcars") +while (!dbHasCompleted(rs)) { + chunk <- dbFetch(rs, 10) + print(nrow(chunk)) +}
    #> [1] 10 +#> [1] 10 +#> [1] 10 +#> [1] 2
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetDBIVersion.html b/docs/reference/dbGetDBIVersion.html new file mode 100644 index 000000000..3403a1152 --- /dev/null +++ b/docs/reference/dbGetDBIVersion.html @@ -0,0 +1,134 @@ + + + + + + + + +Determine the current version of the package. — dbGetDBIVersion • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Determine the current version of the package.

    + + +
    dbGetDBIVersion()
    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetException.html b/docs/reference/dbGetException.html new file mode 100644 index 000000000..8b40eff79 --- /dev/null +++ b/docs/reference/dbGetException.html @@ -0,0 +1,172 @@ + + + + + + + + +Get DBMS exceptions — dbGetException • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    DEPRECATED. Backends should use R's condition system to signal errors and +warnings.

    + + +
    dbGetException(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    a list with elements errorNum (an integer error number) and +errorMsg (a character string) describing the last error in the +connection conn.

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetInfo, dbGetQuery, + dbIsValid, dbListFields, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetInfo.html b/docs/reference/dbGetInfo.html new file mode 100644 index 000000000..4513dbdfc --- /dev/null +++ b/docs/reference/dbGetInfo.html @@ -0,0 +1,207 @@ + + + + + + + + +Get DBMS metadata — dbGetInfo • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Get DBMS metadata

    + + +
    dbGetInfo(dbObj, ...)
    + +

    Arguments

    + + + + + + + + + + +
    dbObj

    An object inheriting from DBIObject, +i.e. DBIDriver, DBIConnection, +or a DBIResult

    ...

    Other arguments to methods.

    + +

    Value

    + +

    a named list

    + +

    Implementation notes

    + + +

    For DBIDriver subclasses, this should include the version of the +package (driver.version) and the version of the underlying client +library (client.version).

    +

    For DBIConnection objects this should report the version of +the DBMS engine (db.version), database name (dbname), +username, (username), host (host), port (port), etc. +It MAY also include any other arguments related to the connection +(e.g., thread id, socket or TCP connection type). It MUST NOT include the +password.

    +

    For DBIResult objects, this should include the statement +being executed (statement), how many rows have been fetched so far +(in the case of queries, row.count), how many rows were affected +(deleted, inserted, changed, +(rows.affected), and if the query is complete (has.completed).

    +

    The default implementation for DBIResult objects +constructs such a list from the return values of the corresponding methods, +dbGetStatement(), dbGetRowCount(), +dbGetRowsAffected(), and dbHasCompleted().

    + +

    See also

    + +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDataType, + dbDriver, dbIsValid, + dbListConnections

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetQuery, + dbIsValid, dbListFields, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetQuery.html b/docs/reference/dbGetQuery.html new file mode 100644 index 000000000..29a40f00e --- /dev/null +++ b/docs/reference/dbGetQuery.html @@ -0,0 +1,270 @@ + + + + + + + + +Send query, retrieve results and then clear result set — dbGetQuery • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns the result of a query as a data frame. +dbGetQuery() comes with a default implementation +(which should work with most backends) that calls +dbSendQuery(), then dbFetch(), ensuring that +the result is always free-d by dbClearResult(). + +

    Methods in other packages

    + +

    + + +
    dbGetQuery(conn, statement, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    statement

    a character string containing SQL.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbGetQuery() always returns a data.frame +with as many rows as records were fetched and as many +columns as fields in the result set, +even if the result is a single value +or has one +or zero rows. +An error is raised when issuing a query over a closed +or invalid connection, +if the syntax of the query is invalid, +or if the query is not a non-NA string. +If the n argument is not an atomic whole number +greater or equal to -1 or Inf, an error is raised, +but a subsequent call to dbGetQuery() with proper n argument succeeds.

    + +

    Details

    + +

    This method is for SELECT queries only. Some backends may +support data manipulation statements through this method for compatibility +reasons. However, callers are strongly advised to use +dbExecute() for data manipulation statements.

    + +

    Implementation notes

    + + +

    Subclasses should override this method only if they provide some sort of +performance optimization.

    + +

    Specification

    + + +

    Fetching multi-row queries with one +or more columns be default returns the entire result. +A value of Inf for the n argument is supported +and also returns the full result. +If more rows than available are fetched, the result is returned in full +without warning. +If zero rows are fetched, the columns of the data frame are still fully +typed. +Fetching fewer rows than available is permitted, +no warning is issued.

    +

    A column named row_names is treated like any other column.

    + +

    See also

    + +

    For updates: dbSendStatement() and dbExecute().

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbIsValid, dbListFields, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +dbGetQuery(con, "SELECT * FROM mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 +#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 +#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 +#> 11 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 +#> 12 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 +#> 13 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 +#> 14 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 +#> 15 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 +#> 16 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 +#> 17 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 +#> 18 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 +#> 19 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 +#> 20 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 +#> 21 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 +#> 22 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 +#> 23 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 +#> 24 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 +#> 25 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 +#> 26 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 +#> 27 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 +#> 28 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 +#> 29 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 +#> 30 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 +#> 31 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 +#> 32 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetRowCount.html b/docs/reference/dbGetRowCount.html new file mode 100644 index 000000000..0a814a708 --- /dev/null +++ b/docs/reference/dbGetRowCount.html @@ -0,0 +1,204 @@ + + + + + + + + +The number of rows fetched so far — dbGetRowCount • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns the total number of rows actually fetched with calls to dbFetch() +for this result set. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbGetRowCount("SQLiteResult")

    • +

    + + +
    dbGetRowCount(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbGetRowCount() returns a scalar number (integer or numeric), +the number of rows fetched so far. +After calling dbSendQuery(), +the row count is initially zero. +After a call to dbFetch() without limit, +the row count matches the total number of rows returned. +Fetching a limited number of rows +increases the number of rows by the number of rows returned, +even if fetching past the end of the result set. +For queries with an empty result set, +zero is returned +even after fetching. +For data manipulation statements issued with +dbSendStatement(), +zero is returned before +and after calling dbFetch(). +Attempting to get the row count for a result set cleared with +dbClearResult() gives an error.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +rs <- dbSendQuery(con, "SELECT * FROM mtcars") + +dbGetRowCount(rs)
    #> [1] 0
    ret1 <- dbFetch(rs, 10) +dbGetRowCount(rs)
    #> [1] 10
    ret2 <- dbFetch(rs) +dbGetRowCount(rs)
    #> [1] 32
    nrow(ret1) + nrow(ret2)
    #> [1] 32
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetRowsAffected.html b/docs/reference/dbGetRowsAffected.html new file mode 100644 index 000000000..2e20f99c8 --- /dev/null +++ b/docs/reference/dbGetRowsAffected.html @@ -0,0 +1,193 @@ + + + + + + + + +The number of rows affected — dbGetRowsAffected • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This method returns the number of rows that were added, deleted, or updated +by a data manipulation statement. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbGetRowsAffected("SQLiteResult")

    • +

    + + +
    dbGetRowsAffected(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbGetRowsAffected() returns a scalar number (integer or numeric), +the number of rows affected by a data manipulation statement +issued with dbSendStatement(). +The value is available directly after the call +and does not change after calling dbFetch(). +For queries issued with dbSendQuery(), +zero is returned before +and after the call to dbFetch(). +Attempting to get the rows affected for a result set cleared with +dbClearResult() gives an error.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +rs <- dbSendStatement(con, "DELETE FROM mtcars") +dbGetRowsAffected(rs)
    #> [1] 32
    nrow(mtcars)
    #> [1] 32
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbGetStatement.html b/docs/reference/dbGetStatement.html new file mode 100644 index 000000000..e2c507091 --- /dev/null +++ b/docs/reference/dbGetStatement.html @@ -0,0 +1,188 @@ + + + + + + + + +Get the statement associated with a result set — dbGetStatement • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns the statement that was passed to dbSendQuery() +or dbSendStatement(). + +

    Methods in other packages

    + +
      +
    • RSQLite::dbGetStatement("SQLiteResult")

    • +

    + + +
    dbGetStatement(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbGetStatement() returns a string, the query used in +either dbSendQuery() +or dbSendStatement(). +Attempting to query the statement for a result set cleared with +dbClearResult() gives an error.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +rs <- dbSendQuery(con, "SELECT * FROM mtcars") +dbGetStatement(rs)
    #> [1] "SELECT * FROM mtcars"
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbHasCompleted.html b/docs/reference/dbHasCompleted.html new file mode 100644 index 000000000..6029b48d4 --- /dev/null +++ b/docs/reference/dbHasCompleted.html @@ -0,0 +1,210 @@ + + + + + + + + +Completion status — dbHasCompleted • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This method returns if the operation has completed. +A SELECT query is completed if all rows have been fetched. +A data manipulation statement is always completed. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbHasCompleted("SQLiteResult")

    • +

    + + +
    dbHasCompleted(res, ...)
    + +

    Arguments

    + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbHasCompleted() returns a logical scalar. +For a query initiated by dbSendQuery() with non-empty result set, +dbHasCompleted() returns FALSE initially +and TRUE after calling dbFetch() without limit. +For a query initiated by dbSendStatement(), +dbHasCompleted() always returns TRUE. +Attempting to query completion status for a result set cleared with +dbClearResult() gives an error.

    + +

    Specification

    + + +

    The completion status for a query is only guaranteed to be set to +FALSE after attempting to fetch past the end of the entire result. +Therefore, for a query with an empty result set, +the initial return value is unspecified, +but the result value is TRUE after trying to fetch only one row. +Similarly, for a query with a result set of length n, +the return value is unspecified after fetching n rows, +but the result value is TRUE after trying to fetch only one more +row.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +rs <- dbSendQuery(con, "SELECT * FROM mtcars") + +dbHasCompleted(rs)
    #> [1] FALSE
    ret1 <- dbFetch(rs, 10) +dbHasCompleted(rs)
    #> [1] FALSE
    ret2 <- dbFetch(rs) +dbHasCompleted(rs)
    #> [1] TRUE
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbIsValid.html b/docs/reference/dbIsValid.html new file mode 100644 index 000000000..025dd5c1e --- /dev/null +++ b/docs/reference/dbIsValid.html @@ -0,0 +1,219 @@ + + + + + + + + +Is this DBMS object still valid? — dbIsValid • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This generic tests whether a database object is still valid (i.e. it hasn't +been disconnected or cleared). + +

    Methods in other packages

    + +
      +
    • RSQLite::dbIsValid("SQLiteConnection")

    • +
    • RSQLite::dbIsValid("SQLiteDriver")

    • +
    • RSQLite::dbIsValid("SQLiteResult")

    • +

    + + +
    dbIsValid(dbObj, ...)
    + +

    Arguments

    + + + + + + + + + + +
    dbObj

    An object inheriting from DBIObject, +i.e. DBIDriver, DBIConnection, +or a DBIResult

    ...

    Other arguments to methods.

    + +

    Value

    + +

    dbIsValid() returns a logical scalar, +TRUE if the object specified by dbObj is valid, +FALSE otherwise. +A DBIConnection object is initially valid, +and becomes invalid after disconnecting with dbDisconnect(). +For an invalid connection object (e.g., for some drivers if the object +is saved to a file and then restored), the method also returns FALSE. +A DBIResult object is valid after a call to dbSendQuery(), +and stays valid even after all rows have been fetched; +only clearing it with dbClearResult() invalidates it. +A DBIResult object is also valid after a call to dbSendStatement(), +and stays valid after querying the number of rows affected; +only clearing it with dbClearResult() invalidates it. +If the connection to the database system is dropped (e.g., due to +connectivity problems, server failure, etc.), dbIsValid() should return +FALSE. This is not tested automatically.

    + +

    See also

    + +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDataType, + dbDriver, dbGetInfo, + dbListConnections

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbListFields, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    dbIsValid(RSQLite::SQLite())
    #> [1] TRUE
    +con <- dbConnect(RSQLite::SQLite(), ":memory:") +dbIsValid(con)
    #> [1] TRUE
    +rs <- dbSendQuery(con, "SELECT 1") +dbIsValid(rs)
    #> [1] TRUE
    +dbClearResult(rs) +dbIsValid(rs)
    #> [1] FALSE
    +dbDisconnect(con) +dbIsValid(con)
    #> [1] FALSE
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbListConnections.html b/docs/reference/dbListConnections.html new file mode 100644 index 000000000..8b8bc7164 --- /dev/null +++ b/docs/reference/dbListConnections.html @@ -0,0 +1,165 @@ + + + + + + + + +List currently open connections — dbListConnections • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Drivers that implement only a single connections MUST return a list +containing a single element. If no connection are open, methods MUST +return an empty list.

    + + +
    dbListConnections(drv, ...)
    + +

    Arguments

    + + + + + + + + + + +
    drv

    A object inheriting from DBIDriver

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    a list

    + +

    See also

    + +

    Other DBIDriver generics: DBIDriver-class, + dbConnect, dbDataType, + dbDriver, dbGetInfo, + dbIsValid

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbListFields.html b/docs/reference/dbListFields.html new file mode 100644 index 000000000..b97c4ff0a --- /dev/null +++ b/docs/reference/dbListFields.html @@ -0,0 +1,183 @@ + + + + + + + + +List field names of a remote table — dbListFields • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    List field names of a remote table

    + + +
    dbListFields(conn, name, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    name

    a character string with the name of the remote table.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    a character vector

    + +

    See also

    + +

    dbColumnInfo() to get the type of the fields.

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +dbListFields(con, "mtcars")
    #> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" +#> [11] "carb"
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbListResults.html b/docs/reference/dbListResults.html new file mode 100644 index 000000000..05c9c0610 --- /dev/null +++ b/docs/reference/dbListResults.html @@ -0,0 +1,172 @@ + + + + + + + + +A list of all pending results — dbListResults • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    DEPRECATED. DBI currenty supports only one open result set per connection, +you need to keep track of the result sets you open if you need this +functionality.

    + + +
    dbListResults(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    a list. If no results are active, an empty list. If only +a single result is active, a list with one element.

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbListTables.html b/docs/reference/dbListTables.html new file mode 100644 index 000000000..1b2cdd563 --- /dev/null +++ b/docs/reference/dbListTables.html @@ -0,0 +1,206 @@ + + + + + + + + +List remote tables — dbListTables • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Returns the unquoted names of remote tables accessible through this +connection. +This should, where possible, include temporary tables, and views. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbListTables("SQLiteConnection")

    • +

    + + +
    dbListTables(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbListTables() +returns a character vector +that enumerates all tables +and views +in the database. +Tables added with dbWriteTable() +are part of the list, +including temporary tables if supported by the database. +As soon a table is removed from the database, +it is also removed from the list of database tables.

    +

    The returned names are suitable for quoting with dbQuoteIdentifier(). +An error is raised when calling this method for a closed +or invalid connection.

    + +

    Additional arguments

    + + +

    TBD: temporary = NA

    +

    This must be provided as named argument. +See the "Specification" section for details on their usage.

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbListTables(con)
    #> character(0)
    dbWriteTable(con, "mtcars", mtcars) +dbListTables(con)
    #> [1] "mtcars"
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbQuoteIdentifier.html b/docs/reference/dbQuoteIdentifier.html new file mode 100644 index 000000000..910190ffa --- /dev/null +++ b/docs/reference/dbQuoteIdentifier.html @@ -0,0 +1,232 @@ + + + + + + + + +Quote identifiers — dbQuoteIdentifier • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Call this method to generate a string that is suitable for +use in a query as a column name, to make sure that you +generate valid SQL and avoid SQL injection. + +

    Methods in other packages

    + +

    + + +
    dbQuoteIdentifier(conn, x, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A subclass of DBIConnection, representing +an active connection to an DBMS.

    x

    A character vector to quote as identifier.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbQuoteIdentifier() returns an object that can be coerced to character, +of the same length as the input. +For an empty character vector this function returns a length-0 object. +An error is raised if the input contains NA, +but not for an empty string.

    +

    When passing the returned object again to dbQuoteIdentifier() +as x +argument, it is returned unchanged. +Passing objects of class SQL should also return them unchanged. +(For backends it may be most convenient to return SQL objects +to achieve this behavior, but this is not required.)

    + +

    Specification

    + + +

    Calling dbGetQuery() for a query of the format SELECT 1 AS ... +returns a data frame with the identifier, unquoted, as column name. +Quoted identifiers can be used as table and column names in SQL queries, +in particular in queries like SELECT 1 AS ... +and SELECT * FROM (SELECT 1) .... +The method must use a quoting mechanism that is unambiguously different +from the quoting mechanism used for strings, so that a query like +SELECT ... FROM (SELECT 1 AS ...) +throws an error if the column names do not match.

    +

    The method can quote column names that +contain special characters such as a space, +a dot, +a comma, +or quotes used to mark strings +or identifiers, +if the database supports this. +In any case, checking the validity of the identifier +should be performed only when executing a query, +and not by dbQuoteIdentifier().

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteLiteral, dbQuoteString

    + + +

    Examples

    +
    # Quoting ensures that arbitrary input is safe for use in a query +name <- "Robert'); DROP TABLE Students;--" +dbQuoteIdentifier(ANSI(), name)
    #> <SQL> "Robert'); DROP TABLE Students;--"
    +# SQL vectors are always passed through as is +var_name <- SQL("select") +var_name
    #> <SQL> select
    +dbQuoteIdentifier(ANSI(), var_name)
    #> <SQL> select
    +# This mechanism is used to prevent double escaping +dbQuoteIdentifier(ANSI(), dbQuoteIdentifier(ANSI(), name))
    #> <SQL> "Robert'); DROP TABLE Students;--"
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbQuoteLiteral.html b/docs/reference/dbQuoteLiteral.html new file mode 100644 index 000000000..4ee56666d --- /dev/null +++ b/docs/reference/dbQuoteLiteral.html @@ -0,0 +1,198 @@ + + + + + + + + +Quote literal values — dbQuoteLiteral • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Call these methods to generate a string that is suitable for +use in a query as a literal value of the correct type, to make sure that you +generate valid SQL and avoid SQL injection. + +

    Methods in other packages

    + +

    + + +
    dbQuoteLiteral(conn, x, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A subclass of DBIConnection, representing +an active connection to an DBMS.

    x

    A vector to quote as string.

    ...

    Other arguments passed on to methods.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteString

    + + +

    Examples

    +
    # Quoting ensures that arbitrary input is safe for use in a query +name <- "Robert'); DROP TABLE Students;--" +dbQuoteLiteral(ANSI(), name)
    #> <SQL> 'Robert''); DROP TABLE Students;--'
    +# NAs become NULL +dbQuoteLiteral(ANSI(), c(1:3, NA))
    #> <SQL> 1 +#> <SQL> 2 +#> <SQL> 3 +#> <SQL> NULL
    +# Logicals become integers by default +dbQuoteLiteral(ANSI(), c(TRUE, FALSE, NA))
    #> <SQL> 1 +#> <SQL> 0 +#> <SQL> NULL
    +# Raw vectors become hex strings by default +dbQuoteLiteral(ANSI(), list(as.raw(1:3), NULL))
    #> <SQL> X'010203' +#> <SQL> NULL
    +# SQL vectors are always passed through as is +var_name <- SQL("select") +var_name
    #> <SQL> select
    dbQuoteLiteral(ANSI(), var_name)
    #> <SQL> select
    +# This mechanism is used to prevent double escaping +dbQuoteLiteral(ANSI(), dbQuoteLiteral(ANSI(), name))
    #> <SQL> 'Robert''); DROP TABLE Students;--'
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbQuoteString.html b/docs/reference/dbQuoteString.html new file mode 100644 index 000000000..75f7a8d70 --- /dev/null +++ b/docs/reference/dbQuoteString.html @@ -0,0 +1,230 @@ + + + + + + + + +Quote literal strings — dbQuoteString • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Call this method to generate a string that is suitable for +use in a query as a string literal, to make sure that you +generate valid SQL and avoid SQL injection. + +

    Methods in other packages

    + +

    + + +
    dbQuoteString(conn, x, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A subclass of DBIConnection, representing +an active connection to an DBMS.

    x

    A character vector to quote as string.

    ...

    Other arguments passed on to methods.

    + +

    Value

    + +

    dbQuoteString() returns an object that can be coerced to character, +of the same length as the input. +For an empty character vector this function returns a length-0 object.

    +

    When passing the returned object again to dbQuoteString() +as x +argument, it is returned unchanged. +Passing objects of class SQL should also return them unchanged. +(For backends it may be most convenient to return SQL objects +to achieve this behavior, but this is not required.)

    + +

    Specification

    + + +

    The returned expression can be used in a SELECT ... query, +and for any scalar character x the value of +dbGetQuery(paste0("SELECT ", dbQuoteString(x)))[[1]] +must be identical to x, +even if x contains +spaces, +tabs, +quotes (single +or double), +backticks, +or newlines +(in any combination) +or is itself the result of a dbQuoteString() call coerced back to +character (even repeatedly). +If x is NA, the result must merely satisfy is.na(). +The strings "NA" or "NULL" are not treated specially. + NA should be translated to an unquoted SQL NULL, +so that the query SELECT * FROM (SELECT 1) a WHERE ... IS NULL +returns one row.

    + +

    See also

    + +

    Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral

    + + +

    Examples

    +
    # Quoting ensures that arbitrary input is safe for use in a query +name <- "Robert'); DROP TABLE Students;--" +dbQuoteString(ANSI(), name)
    #> <SQL> 'Robert''); DROP TABLE Students;--'
    +# NAs become NULL +dbQuoteString(ANSI(), c("x", NA))
    #> <SQL> 'x' +#> <SQL> NULL
    +# SQL vectors are always passed through as is +var_name <- SQL("select") +var_name
    #> <SQL> select
    dbQuoteString(ANSI(), var_name)
    #> <SQL> select
    +# This mechanism is used to prevent double escaping +dbQuoteString(ANSI(), dbQuoteString(ANSI(), name))
    #> <SQL> 'Robert''); DROP TABLE Students;--'
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbReadTable.html b/docs/reference/dbReadTable.html new file mode 100644 index 000000000..2922208ad --- /dev/null +++ b/docs/reference/dbReadTable.html @@ -0,0 +1,260 @@ + + + + + + + + +Copy data frames from database tables — dbReadTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Reads a database table to a data frame, optionally converting +a column to row names and converting the column names to valid +R identifiers. + +

    Methods in other packages

    + +

    + + +
    dbReadTable(conn, name, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    name

    A character string specifying the unquoted DBMS table name, +or the result of a call to dbQuoteIdentifier().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbReadTable() returns a data frame that contains the complete data +from the remote table, effectively the result of calling dbGetQuery() +with SELECT * FROM <name>. +An error is raised if the table does not exist. +An empty table is returned as a data frame with zero rows.

    +

    The presence of rownames depends on the row.names argument, +see sqlColumnToRownames() for details:

      +
    • If FALSE or NULL, the returned data frame doesn't have row names.

    • +
    • If TRUE, a column named "row_names" is converted to row names, +an error is raised if no such column exists.

    • +
    • If NA, a column named "row_names" is converted to row names if it exists, +otherwise no translation occurs.

    • +
    • If a string, this specifies the name of the column in the remote table +that contains the row names, +an error is raised if no such column exists.

    • +
    + +

    The default is row.names = FALSE.

    +

    If the database supports identifiers with special characters, +the columns in the returned data frame are converted to valid R +identifiers +if the check.names argument is TRUE, +otherwise non-syntactic column names can be returned unquoted.

    +

    An error is raised when calling this method for a closed +or invalid connection. +An error is raised +if name cannot be processed with dbQuoteIdentifier() +or if this results in a non-scalar. +Unsupported values for row.names and check.names +(non-scalars, +unsupported data types, +NA for check.names) +also raise an error.

    + +

    Additional arguments

    + + +

    The following arguments are not part of the dbReadTable() generic +(to improve compatibility across backends) +but are part of the DBI specification:

      +
    • row.names

    • +
    • check.names

    • +
    +

    They must be provided as named arguments. +See the "Value" section for details on their usage.

    + +

    Specification

    + + +

    The name argument is processed as follows, +to support databases that allow non-syntactic names for their objects:

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars[1:10, ]) +dbReadTable(con, "mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 +#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 +#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbRemoveTable.html b/docs/reference/dbRemoveTable.html new file mode 100644 index 000000000..872834409 --- /dev/null +++ b/docs/reference/dbRemoveTable.html @@ -0,0 +1,214 @@ + + + + + + + + +Remove a table from the database — dbRemoveTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Remove a remote table (e.g., created by dbWriteTable()) +from the database. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbRemoveTable("SQLiteConnection", "character")

    • +

    + + +
    dbRemoveTable(conn, name, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    name

    A character string specifying a DBMS table name.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbRemoveTable() returns TRUE, invisibly. +If the table does not exist, an error is raised. +An attempt to remove a view with this function may result in an error.

    +

    An error is raised when calling this method for a closed +or invalid connection. +An error is also raised +if name cannot be processed with dbQuoteIdentifier() +or if this results in a non-scalar.

    + +

    Specification

    + + +

    A table removed by dbRemoveTable() doesn't appear in the list of tables +returned by dbListTables(), +and dbExistsTable() returns FALSE. +The removal propagates immediately to other connections to the same database. +This function can also be used to remove a temporary table.

    +

    The name argument is processed as follows, +to support databases that allow non-syntactic names for their objects:

    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbSendQuery, dbSendStatement, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbExistsTable(con, "iris")
    #> [1] FALSE
    dbWriteTable(con, "iris", iris) +dbExistsTable(con, "iris")
    #> [1] TRUE
    dbRemoveTable(con, "iris") +dbExistsTable(con, "iris")
    #> [1] FALSE
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbSendQuery.html b/docs/reference/dbSendQuery.html new file mode 100644 index 000000000..57a0529f5 --- /dev/null +++ b/docs/reference/dbSendQuery.html @@ -0,0 +1,245 @@ + + + + + + + + +Execute a query on a given database connection — dbSendQuery • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    The dbSendQuery() method only submits and synchronously executes the +SQL query to the database engine. It does not extract any +records --- for that you need to use the dbFetch() method, and +then you must call dbClearResult() when you finish fetching the +records you need. For interactive use, you should almost always prefer +dbGetQuery(). + +

    Methods in other packages

    + +
      +
    • RSQLite::dbSendQuery("SQLiteConnection", "character")

    • +

    + + +
    dbSendQuery(conn, statement, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    statement

    a character string containing SQL.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbSendQuery() returns +an S4 object that inherits from DBIResult. +The result set can be used with dbFetch() to extract records. +Once you have finished using a result, make sure to clear it +with dbClearResult(). +An error is raised when issuing a query over a closed +or invalid connection, +if the syntax of the query is invalid, +or if the query is not a non-NA string.

    + +

    Details

    + +

    This method is for SELECT queries only. Some backends may +support data manipulation queries through this method for compatibility +reasons. However, callers are strongly encouraged to use +dbSendStatement() for data manipulation statements.

    +

    The query is submitted to the database server and the DBMS executes it, +possibly generating vast amounts of data. Where these data live +is driver-specific: some drivers may choose to leave the output on the server +and transfer them piecemeal to R, others may transfer all the data to the +client -- but not necessarily to the memory that R manages. See individual +drivers' dbSendQuery() documentation for details.

    + +

    Specification

    + + +

    No warnings occur under normal conditions. +When done, the DBIResult object must be cleared with a call to +dbClearResult(). +Failure to clear the result set leads to a warning +when the connection is closed.

    +

    If the backend supports only one open result set per connection, +issuing a second query invalidates an already open result set +and raises a warning. +The newly opened result set is valid +and must be cleared with dbClearResult().

    + +

    See also

    + +

    For updates: dbSendStatement() and dbExecute().

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, + dbSendStatement, dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars) +rs <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4;") +dbFetch(rs)
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 2 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 3 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 4 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 +#> 5 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 +#> 6 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 +#> 7 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 +#> 8 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 +#> 9 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 +#> 10 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 +#> 11 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbSendStatement.html b/docs/reference/dbSendStatement.html new file mode 100644 index 000000000..da67185ce --- /dev/null +++ b/docs/reference/dbSendStatement.html @@ -0,0 +1,236 @@ + + + + + + + + +Execute a data manipulation statement on a given database connection — dbSendStatement • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    The dbSendStatement() method only submits and synchronously executes the +SQL data manipulation statement (e.g., UPDATE, DELETE, +INSERT INTO, DROP TABLE, ...) to the database engine. To query +the number of affected rows, call dbGetRowsAffected() on the +returned result object. You must also call dbClearResult() after +that. For interactive use, you should almost always prefer +dbExecute(). + +

    Methods in other packages

    + +

    + + +
    dbSendStatement(conn, statement, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    statement

    a character string containing SQL.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbSendStatement() returns +an S4 object that inherits from DBIResult. +The result set can be used with dbGetRowsAffected() to +determine the number of rows affected by the query. +Once you have finished using a result, make sure to clear it +with dbClearResult(). +An error is raised when issuing a statement over a closed +or invalid connection, +if the syntax of the statement is invalid, +or if the statement is not a non-NA string.

    + +

    Details

    + +

    dbSendStatement() comes with a default implementation that simply +forwards to dbSendQuery(), to support backends that only +implement the latter.

    + +

    Specification

    + + +

    No warnings occur under normal conditions. +When done, the DBIResult object must be cleared with a call to +dbClearResult(). +Failure to clear the result set leads to a warning +when the connection is closed. +If the backend supports only one open result set per connection, +issuing a second query invalidates an already open result set +and raises a warning. +The newly opened result set is valid +and must be cleared with dbClearResult().

    + +

    See also

    + +

    For queries: dbSendQuery() and dbGetQuery().

    +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbWriteTable

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "cars", head(cars, 3)) +rs <- dbSendStatement(con, + "INSERT INTO cars (speed, dist) VALUES (1, 1), (2, 2), (3, 3);") +dbHasCompleted(rs)
    #> [1] TRUE
    #> [1] 3
    dbClearResult(rs) +dbReadTable(con, "cars") # there are now 6 rows
    #> speed dist +#> 1 4 2 +#> 2 4 10 +#> 3 7 4 +#> 4 1 1 +#> 5 2 2 +#> 6 3 3
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbSetDataMappings.html b/docs/reference/dbSetDataMappings.html new file mode 100644 index 000000000..7ff548fdd --- /dev/null +++ b/docs/reference/dbSetDataMappings.html @@ -0,0 +1,162 @@ + + + + + + + + +Set data mappings between an DBMS and R. — dbSetDataMappings • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This generic is deprecated since no working implementation was ever produced.

    + + +
    dbSetDataMappings(res, flds, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    res

    An object inheriting from DBIResult.

    flds

    a field description object as returned by dbColumnInfo.

    ...

    Other arguments passed on to methods.

    + +

    Details

    + +

    Sets one or more conversion functions to handle the translation of DBMS data +types to R objects. This is only needed for non-primitive data, since all +DBI drivers handle the common base types (integers, numeric, strings, etc.)

    +

    The details on conversion functions (e.g., arguments, whether they can invoke +initializers and/or destructors) have not been specified.

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbWithTransaction.html b/docs/reference/dbWithTransaction.html new file mode 100644 index 000000000..22b1e2953 --- /dev/null +++ b/docs/reference/dbWithTransaction.html @@ -0,0 +1,246 @@ + + + + + + + + +Self-contained SQL transactions — dbWithTransaction • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Given that transactions are implemented, this function +allows you to pass in code that is run in a transaction. +The default method of dbWithTransaction() calls dbBegin() +before executing the code, +and dbCommit() after successful completion, +or dbRollback() in case of an error. +The advantage is +that you don't have to remember to do dbBegin() and dbCommit() or +dbRollback() -- that is all taken care of. +The special function dbBreak() allows an early exit with rollback, +it can be called only inside dbWithTransaction(). + +

    Methods in other packages

    + +

    + + +
    dbWithTransaction(conn, code, ...)
    +
    +dbBreak()
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    code

    An arbitrary block of R code.

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbWithTransaction() returns the value of the executed code. +Failure to initiate the transaction +(e.g., if the connection is closed +or invalid +of if dbBegin() has been called already) +gives an error.

    + +

    Details

    + +

    DBI implements dbWithTransaction(), backends should need to override this +generic only if they implement specialized handling.

    + +

    Specification

    + + +

    dbWithTransaction() initiates a transaction with dbBegin(), executes +the code given in the code argument, and commits the transaction with +dbCommit(). +If the code raises an error, the transaction is instead aborted with +dbRollback(), and the error is propagated. +If the code calls dbBreak(), execution of the code stops and the +transaction is silently aborted. +All side effects caused by the code +(such as the creation of new variables) +propagate to the calling environment.

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "cash", data.frame(amount = 100)) +dbWriteTable(con, "account", data.frame(amount = 2000)) + +# All operations are carried out as logical unit: +dbWithTransaction( + con, + { + withdrawal <- 300 + dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal)) + dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal)) + } +)
    #> [1] 1
    +# The code is executed as if in the curent environment: +withdrawal
    #> [1] 300
    +# The changes are committed to the database after successful execution: +dbReadTable(con, "cash")
    #> amount +#> 1 400
    dbReadTable(con, "account")
    #> amount +#> 1 1700
    +# Rolling back with dbBreak(): +dbWithTransaction( + con, + { + withdrawal <- 5000 + dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal)) + dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal)) + if (dbReadTable(con, "account")$amount < 0) { + dbBreak() + } + } +) + +# These changes were not committed to the database: +dbReadTable(con, "cash")
    #> amount +#> 1 400
    dbReadTable(con, "account")
    #> amount +#> 1 1700
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/dbWriteTable.html b/docs/reference/dbWriteTable.html new file mode 100644 index 000000000..d6b5aed0c --- /dev/null +++ b/docs/reference/dbWriteTable.html @@ -0,0 +1,343 @@ + + + + + + + + +Copy data frames to database tables — dbWriteTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Writes, overwrites or appends a data frame to a database table, optionally +converting row names to a column and specifying SQL data types for fields. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbWriteTable("SQLiteConnection", "character", "character")

    • +
    • RSQLite::dbWriteTable("SQLiteConnection", "character", "data.frame")

    • +

    + + +
    dbWriteTable(conn, name, value, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    name

    A character string specifying the unquoted DBMS table name, +or the result of a call to dbQuoteIdentifier().

    value

    a data.frame (or coercible to data.frame).

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbWriteTable() returns TRUE, invisibly. +If the table exists, and both append and overwrite arguments are unset, +or append = TRUE and the data frame with the new data has different +column names, +an error is raised; the remote table remains unchanged.

    +

    An error is raised when calling this method for a closed +or invalid connection. +An error is also raised +if name cannot be processed with dbQuoteIdentifier() +or if this results in a non-scalar. +Invalid values for the additional arguments row.names, +overwrite, append, field.types, and temporary +(non-scalars, +unsupported data types, +NA, +incompatible values, +duplicate +or missing names, +incompatible columns) +also raise an error.

    + +

    Additional arguments

    + + +

    The following arguments are not part of the dbWriteTable() generic +(to improve compatibility across backends) +but are part of the DBI specification:

      +
    • row.names (default: NA)

    • +
    • overwrite (default: FALSE)

    • +
    • append (default: FALSE)

    • +
    • field.types (default: NULL)

    • +
    • temporary (default: FALSE)

    • +
    +

    They must be provided as named arguments. +See the "Specification" and "Value" sections for details on their usage.

    + +

    Specification

    + + +

    The name argument is processed as follows, +to support databases that allow non-syntactic names for their objects:

    +

    If the overwrite argument is TRUE, an existing table of the same name +will be overwritten. +This argument doesn't change behavior if the table does not exist yet.

    +

    If the append argument is TRUE, the rows in an existing table are +preserved, and the new data are appended. +If the table doesn't exist yet, it is created.

    +

    If the temporary argument is TRUE, the table is not available in a +second connection and is gone after reconnecting. +Not all backends support this argument. +A regular, non-temporary table is visible in a second connection +and after reconnecting to the database.

    +

    SQL keywords can be used freely in table names, column names, and data. +Quotes, commas, and spaces can also be used in the data, +and, if the database supports non-syntactic identifiers, +also for table names and column names.

    +

    The following data types must be supported at least, +and be read identically with dbReadTable():

      +
    • integer

    • +
    • numeric +(the behavior for Inf and NaN is not specified)

    • +
    • logical

    • +
    • NA as NULL

    • +
    • 64-bit values (using "bigint" as field type); +the result can be converted to a numeric, which may lose precision,

    • +
    • character (in both UTF-8 +and native encodings), +supporting empty strings

    • +
    • factor (returned as character)

    • +
    • list of raw +(if supported by the database)

    • +
    • objects of type blob::blob +(if supported by the database)

    • +
    • date +(if supported by the database; +returned as Date)

    • +
    • time +(if supported by the database; +returned as objects that inherit from difftime)

    • +
    • timestamp +(if supported by the database; +returned as POSIXct +respecting the time zone but not necessarily preserving the +input time zone)

    • +
    +

    Mixing column types in the same table is supported.

    +

    The field.types argument must be a named character vector with at most +one entry for each column. +It indicates the SQL data type to be used for a new column.

    +

    The interpretation of rownames depends on the row.names argument, +see sqlRownamesToColumn() for details:

      +
    • If FALSE or NULL, row names are ignored.

    • +
    • If TRUE, row names are converted to a column named "row_names", +even if the input data frame only has natural row names from 1 to nrow(...).

    • +
    • If NA, a column named "row_names" is created if the data has custom row names, +no extra column is created in the case of natural row names.

    • +
    • If a string, this specifies the name of the column in the remote table +that contains the row names, +even if the input data frame only has natural row names.

    • +
    + +

    See also

    + +

    Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "mtcars", mtcars[1:5, ]) +dbReadTable(con, "mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
    +dbWriteTable(con, "mtcars", mtcars[6:10, ], append = TRUE) +dbReadTable(con, "mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 +#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 +#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
    +dbWriteTable(con, "mtcars", mtcars[1:10, ], overwrite = TRUE) +dbReadTable(con, "mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 +#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 +#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
    +# No row names +dbWriteTable(con, "mtcars", mtcars[1:10, ], overwrite = TRUE, row.names = FALSE) +dbReadTable(con, "mtcars")
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 +#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 +#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 +#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 +#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
    +
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/hidden_aliases.html b/docs/reference/hidden_aliases.html new file mode 100644 index 000000000..40c1d79ff --- /dev/null +++ b/docs/reference/hidden_aliases.html @@ -0,0 +1,262 @@ + + + + + + + + +Internal page for hidden aliases — dbDriver,character-method • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    For S4 methods that require a documentation entry but only clutter the index.

    + + +
    # S4 method for character
    +dbDriver(drvName, ...)
    +
    +# S4 method for DBIDriver
    +show(object)
    +
    +# S4 method for DBIObject
    +dbDataType(dbObj, obj, ...)
    +
    +# S4 method for DBIConnection
    +show(object)
    +
    +# S4 method for DBIConnection,character
    +dbSendStatement(conn, statement, ...)
    +
    +# S4 method for DBIConnection,character
    +dbGetQuery(conn, statement, ..., n = -1L)
    +
    +# S4 method for DBIConnection,character
    +dbExecute(conn, statement, ...)
    +
    +# S4 method for DBIConnection,character
    +dbListFields(conn, name, ...)
    +
    +# S4 method for DBIConnection,character
    +dbReadTable(conn, name, ...,
    +  row.names = FALSE, check.names = TRUE)
    +
    +# S4 method for AnsiConnection
    +show(object)
    +
    +# S4 method for DBIResult
    +show(object)
    +
    +# S4 method for DBIResult
    +dbFetch(res, n = -1, ...)
    +
    +# S4 method for DBIResult
    +dbGetInfo(dbObj, ...)
    +
    +# S4 method for DBIConnection
    +sqlData(con, value, row.names = NA, ...)
    +
    +# S4 method for DBIObject,character
    +make.db.names(dbObj, snames,
    +  keywords = .SQL92Keywords, unique = TRUE, allow.keywords = TRUE, ...)
    +
    +# S4 method for DBIObject,character
    +isSQLKeyword(dbObj, name,
    +  keywords = .SQL92Keywords, case = c("lower", "upper", "any")[3], ...)
    +
    +# S4 method for DBIObject
    +SQLKeywords(dbObj, ...)
    +
    +# S4 method for missing
    +SQLKeywords(dbObj, ...)
    +
    +# S4 method for DBIConnection
    +sqlInterpolate(conn, sql, ..., .dots = list())
    +
    +# S4 method for DBIConnection
    +sqlParseVariables(conn, sql, ...)
    +
    +# S4 method for SQL
    +show(object)
    +
    +# S4 method for DBIConnection,ANY
    +dbQuoteIdentifier(conn, x, ...)
    +
    +# S4 method for DBIConnection,character
    +dbQuoteIdentifier(conn, x, ...)
    +
    +# S4 method for DBIConnection,SQL
    +dbQuoteIdentifier(conn, x, ...)
    +
    +# S4 method for DBIConnection,ANY
    +dbQuoteString(conn, x, ...)
    +
    +# S4 method for DBIConnection,character
    +dbQuoteString(conn, x, ...)
    +
    +# S4 method for DBIConnection,SQL
    +dbQuoteString(conn, x, ...)
    +
    +# S4 method for DBIConnection
    +dbQuoteLiteral(conn, x, ...)
    +
    +# S4 method for DBIConnection
    +sqlCreateTable(con, table, fields, row.names = NA,
    +  temporary = FALSE, ...)
    +
    +# S4 method for DBIConnection
    +sqlAppendTable(con, table, values, row.names = NA,
    +  ...)
    +
    +# S4 method for Table
    +show(object)
    +
    +# S4 method for DBIConnection,Table
    +dbQuoteIdentifier(conn, x, ...)
    +
    +# S4 method for DBIConnection
    +dbWithTransaction(conn, code)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + +
    object

    Object to display

    n

    Number of rows to fetch, default -1

    object

    Object to display

    object

    Object to display

    object

    Table object to print

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/index.html b/docs/reference/index.html new file mode 100644 index 000000000..40a230bbc --- /dev/null +++ b/docs/reference/index.html @@ -0,0 +1,420 @@ + + + + + + + + +Function reference • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    All functions

    +

    +
    +

    dbBind

    +

    Bind values to a parameterized/prepared statement

    +

    dbClearResult

    +

    Clear a result set

    +

    dbColumnInfo

    +

    Information about result types

    +

    dbConnect

    +

    Create a connection to a DBMS

    +

    dbDataType

    +

    Determine the SQL data type of an object

    +

    dbDisconnect

    +

    Disconnect (close) a connection

    +

    dbDriver dbUnloadDriver

    +

    Load and unload database drivers

    +

    dbExecute

    +

    Execute an update statement, query number of rows affected, and then close result set

    +

    dbExistsTable

    +

    Does a table exist?

    +

    dbFetch fetch

    +

    Fetch records from a previously executed query

    +

    dbGetException

    +

    Get DBMS exceptions

    +

    dbGetInfo

    +

    Get DBMS metadata

    +

    dbGetQuery

    +

    Send query, retrieve results and then clear result set

    +

    dbGetRowCount

    +

    The number of rows fetched so far

    +

    dbGetRowsAffected

    +

    The number of rows affected

    +

    dbGetStatement

    +

    Get the statement associated with a result set

    +

    dbHasCompleted

    +

    Completion status

    +

    DBI-package

    +

    DBI: R Database Interface

    +

    DBIConnection-class

    +

    DBIConnection class

    +

    DBIDriver-class

    +

    DBIDriver class

    +

    DBIObject-class

    +

    DBIObject class

    +

    DBIResult-class

    +

    DBIResult class

    +

    dbIsValid

    +

    Is this DBMS object still valid?

    +

    dbListConnections

    +

    List currently open connections

    +

    dbListFields

    +

    List field names of a remote table

    +

    dbListResults

    +

    A list of all pending results

    +

    dbListTables

    +

    List remote tables

    +

    dbQuoteIdentifier

    +

    Quote identifiers

    +

    dbQuoteLiteral

    +

    Quote literal values

    +

    dbQuoteString

    +

    Quote literal strings

    +

    dbReadTable

    +

    Copy data frames from database tables

    +

    dbRemoveTable

    +

    Remove a table from the database

    +

    dbSendQuery

    +

    Execute a query on a given database connection

    +

    dbSendStatement

    +

    Execute a data manipulation statement on a given database connection

    +

    dbWithTransaction dbBreak

    +

    Self-contained SQL transactions

    +

    dbWriteTable

    +

    Copy data frames to database tables

    +

    make.db.names make.db.names.default isSQLKeyword isSQLKeyword.default

    +

    Make R identifiers into legal SQL identifiers

    +

    sqlRownamesToColumn sqlColumnToRownames

    +

    Convert row names back and forth between columns

    +

    SQL

    +

    SQL quoting

    +

    sqlAppendTable sqlAppendTableTemplate

    +

    Insert rows into a table

    +

    sqlCreateTable

    +

    Create a simple table

    +

    sqlData

    +

    Convert a data frame into form suitable for upload to an SQL database

    +

    sqlInterpolate

    +

    Safely interpolate values into an SQL string

    +

    Table

    +

    Refer to a table nested in a hierarchy (e.g. within a schema)

    +

    dbBegin dbCommit dbRollback

    +

    Begin/commit/rollback SQL transactions

    +
    +
    + + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/make.db.names.html b/docs/reference/make.db.names.html new file mode 100644 index 000000000..e8a2d1ab4 --- /dev/null +++ b/docs/reference/make.db.names.html @@ -0,0 +1,237 @@ + + + + + + + + +Make R identifiers into legal SQL identifiers — make.db.names • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    These methods are DEPRECATED. Please use dbQuoteIdentifier() +(or possibly dbQuoteString()) instead.

    + + +
    make.db.names(dbObj, snames, keywords = .SQL92Keywords, unique = TRUE,
    +  allow.keywords = TRUE, ...)
    +
    +make.db.names.default(snames, keywords = .SQL92Keywords, unique = TRUE,
    +  allow.keywords = TRUE)
    +
    +isSQLKeyword(dbObj, name, keywords = .SQL92Keywords, case = c("lower",
    +  "upper", "any")[3], ...)
    +
    +isSQLKeyword.default(name, keywords = .SQL92Keywords, case = c("lower",
    +  "upper", "any")[3])
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    dbObj

    any DBI object (e.g., DBIDriver).

    snames

    a character vector of R identifiers (symbols) from which we +need to make SQL identifiers.

    keywords

    a character vector with SQL keywords, by default it's +.SQL92Keywords defined by the DBI.

    unique

    logical describing whether the resulting set of SQL names +should be unique. Its default is TRUE. Following the SQL 92 +standard, uniqueness of SQL identifiers is determined regardless of whether +letters are upper or lower case.

    allow.keywords

    logical describing whether SQL keywords should be +allowed in the resulting set of SQL names. Its default is TRUE

    any other argument are passed to the driver implementation.

    name

    a character vector with database identifier candidates we need +to determine whether they are legal SQL identifiers or not.

    case

    a character string specifying whether to make the comparison as +lower case, upper case, or any of the two. it defaults to any.

    + +

    Value

    + +

    make.db.names returns a character vector of legal SQL +identifiers corresponding to its snames argument. + +SQLKeywords returns a character vector of all known keywords for the +database-engine associated with dbObj. + +isSQLKeyword returns a logical vector parallel to name.

    + +

    Details

    + +

    The algorithm in make.db.names first invokes make.names and +then replaces each occurrence of a dot . by an underscore _. If +allow.keywords is FALSE and identifiers collide with SQL +keywords, a small integer is appended to the identifier in the form of +"_n".

    +

    The set of SQL keywords is stored in the character vector +.SQL92Keywords and reflects the SQL ANSI/ISO standard as documented +in "X/Open SQL and RDA", 1994, ISBN 1-872630-68-8. Users can easily +override or update this vector.

    + +

    Bugs

    + + +

    The current mapping is not guaranteed to be fully reversible: some SQL +identifiers that get mapped into R identifiers with make.names and +then back to SQL with make.db.names() will not be equal to the +original SQL identifiers (e.g., compound SQL identifiers of the form +username.tablename will loose the dot ``.'').

    + +

    References

    + +

    The set of SQL keywords is stored in the character vector +.SQL92Keywords and reflects the SQL ANSI/ISO standard as documented +in "X/Open SQL and RDA", 1994, ISBN 1-872630-68-8. Users can easily +override or update this vector.

    + + +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/rownames.html b/docs/reference/rownames.html new file mode 100644 index 000000000..ab06d04e5 --- /dev/null +++ b/docs/reference/rownames.html @@ -0,0 +1,205 @@ + + + + + + + + +Convert row names back and forth between columns — rownames • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    These functions provide a reasonably automatic way of preserving the row +names of data frame during back-and-forth translation to an SQL table. +By default, row names will be converted to an explicit column +called "row_names", and any query returning a column called "row_names" +will have those automatically set as row names. +These methods are mostly useful for backend implementers.

    + + +
    sqlRownamesToColumn(df, row.names = NA)
    +
    +sqlColumnToRownames(df, row.names = NA)
    + +

    Arguments

    + + + + + + + + + + +
    df

    A data frame

    row.names

    Either TRUE, FALSE, NA or a string.

    +

    If TRUE, always translate row names to a column called "row_names". +If FALSE, never translate row names. If NA, translate +rownames only if they're a character vector.

    +

    A string is equivalent to TRUE, but allows you to override the +default name.

    +

    For backward compatibility, NULL is equivalent to FALSE.

    + + +

    Examples

    +
    # If have row names +sqlRownamesToColumn(head(mtcars))
    #> row_names mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 +#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 +#> 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 +#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 +#> 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 +#> 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
    sqlRownamesToColumn(head(mtcars), FALSE)
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
    sqlRownamesToColumn(head(mtcars), "ROWNAMES")
    #> ROWNAMES mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 +#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 +#> 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 +#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 +#> 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 +#> 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
    +# If don't have +sqlRownamesToColumn(head(iris))
    #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 5.1 3.5 1.4 0.2 setosa +#> 2 4.9 3.0 1.4 0.2 setosa +#> 3 4.7 3.2 1.3 0.2 setosa +#> 4 4.6 3.1 1.5 0.2 setosa +#> 5 5.0 3.6 1.4 0.2 setosa +#> 6 5.4 3.9 1.7 0.4 setosa
    sqlRownamesToColumn(head(iris), TRUE)
    #> row_names Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 1 5.1 3.5 1.4 0.2 setosa +#> 2 2 4.9 3.0 1.4 0.2 setosa +#> 3 3 4.7 3.2 1.3 0.2 setosa +#> 4 4 4.6 3.1 1.5 0.2 setosa +#> 5 5 5.0 3.6 1.4 0.2 setosa +#> 6 6 5.4 3.9 1.7 0.4 setosa
    sqlRownamesToColumn(head(iris), "ROWNAMES")
    #> ROWNAMES Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 1 5.1 3.5 1.4 0.2 setosa +#> 2 2 4.9 3.0 1.4 0.2 setosa +#> 3 3 4.7 3.2 1.3 0.2 setosa +#> 4 4 4.6 3.1 1.5 0.2 setosa +#> 5 5 5.0 3.6 1.4 0.2 setosa +#> 6 6 5.4 3.9 1.7 0.4 setosa
    +
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/sqlAppendTable.html b/docs/reference/sqlAppendTable.html new file mode 100644 index 000000000..effb7d54d --- /dev/null +++ b/docs/reference/sqlAppendTable.html @@ -0,0 +1,217 @@ + + + + + + + + +Insert rows into a table — sqlAppendTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    sqlAppendTable generates a single SQL string that inserts a +data frame into an existing table. sqlAppendTableTemplate generates +a template suitable for use with dbBind(). +These methods are mostly useful for backend implementers.

    + + +
    sqlAppendTable(con, table, values, row.names = NA, ...)
    +
    +sqlAppendTableTemplate(con, table, values, row.names = NA, prefix = "?",
    +  ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    con

    A database connection.

    table

    Name of the table. Escaped with +dbQuoteIdentifier().

    values

    A data frame. Factors will be converted to character vectors. +Character vectors will be escaped with dbQuoteString().

    row.names

    Either TRUE, FALSE, NA or a string.

    +

    If TRUE, always translate row names to a column called "row_names". +If FALSE, never translate row names. If NA, translate +rownames only if they're a character vector.

    +

    A string is equivalent to TRUE, but allows you to override the +default name.

    +

    For backward compatibility, NULL is equivalent to FALSE.

    ...

    Other arguments used by individual methods.

    prefix

    Parameter prefix to put in front of column id.

    + + +

    Examples

    +
    sqlAppendTable(ANSI(), "iris", head(iris))
    #> <SQL> INSERT INTO "iris" +#> ("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species") +#> VALUES +#> (5.1, 3.5, 1.4, 0.2, 'setosa'), +#> (4.9, 3, 1.4, 0.2, 'setosa'), +#> (4.7, 3.2, 1.3, 0.2, 'setosa'), +#> (4.6, 3.1, 1.5, 0.2, 'setosa'), +#> (5, 3.6, 1.4, 0.2, 'setosa'), +#> (5.4, 3.9, 1.7, 0.4, 'setosa')
    +sqlAppendTable(ANSI(), "mtcars", head(mtcars))
    #> <SQL> INSERT INTO "mtcars" +#> ("row_names", "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb") +#> VALUES +#> ('Mazda RX4', 21, 6, 160, 110, 3.9, 2.62, 16.46, 0, 1, 4, 4), +#> ('Mazda RX4 Wag', 21, 6, 160, 110, 3.9, 2.875, 17.02, 0, 1, 4, 4), +#> ('Datsun 710', 22.8, 4, 108, 93, 3.85, 2.32, 18.61, 1, 1, 4, 1), +#> ('Hornet 4 Drive', 21.4, 6, 258, 110, 3.08, 3.215, 19.44, 1, 0, 3, 1), +#> ('Hornet Sportabout', 18.7, 8, 360, 175, 3.15, 3.44, 17.02, 0, 0, 3, 2), +#> ('Valiant', 18.1, 6, 225, 105, 2.76, 3.46, 20.22, 1, 0, 3, 1)
    sqlAppendTable(ANSI(), "mtcars", head(mtcars), row.names = FALSE)
    #> <SQL> INSERT INTO "mtcars" +#> ("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb") +#> VALUES +#> (21, 6, 160, 110, 3.9, 2.62, 16.46, 0, 1, 4, 4), +#> (21, 6, 160, 110, 3.9, 2.875, 17.02, 0, 1, 4, 4), +#> (22.8, 4, 108, 93, 3.85, 2.32, 18.61, 1, 1, 4, 1), +#> (21.4, 6, 258, 110, 3.08, 3.215, 19.44, 1, 0, 3, 1), +#> (18.7, 8, 360, 175, 3.15, 3.44, 17.02, 0, 0, 3, 2), +#> (18.1, 6, 225, 105, 2.76, 3.46, 20.22, 1, 0, 3, 1)
    sqlAppendTableTemplate(ANSI(), "iris", iris)
    #> <SQL> INSERT INTO "iris" +#> ("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species") +#> VALUES +#> (?1, ?2, ?3, ?4, ?5)
    +sqlAppendTableTemplate(ANSI(), "mtcars", mtcars)
    #> <SQL> INSERT INTO "mtcars" +#> ("row_names", "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb") +#> VALUES +#> (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)
    sqlAppendTableTemplate(ANSI(), "mtcars", mtcars, row.names = FALSE)
    #> <SQL> INSERT INTO "mtcars" +#> ("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb") +#> VALUES +#> (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/sqlCreateTable.html b/docs/reference/sqlCreateTable.html new file mode 100644 index 000000000..88d00f933 --- /dev/null +++ b/docs/reference/sqlCreateTable.html @@ -0,0 +1,219 @@ + + + + + + + + +Create a simple table — sqlCreateTable • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Exposes interface to simple CREATE TABLE commands. The default +method is ANSI SQL 99 compliant. +This method is mostly useful for backend implementers.

    + + +
    sqlCreateTable(con, table, fields, row.names = NA, temporary = FALSE, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    con

    A database connection.

    table

    Name of the table. Escaped with +dbQuoteIdentifier().

    fields

    Either a character vector or a data frame.

    +

    A named character vector: Names are column names, values are types. +Names are escaped with dbQuoteIdentifier(). +Field types are unescaped.

    +

    A data frame: field types are generated using +dbDataType().

    row.names

    Either TRUE, FALSE, NA or a string.

    +

    If TRUE, always translate row names to a column called "row_names". +If FALSE, never translate row names. If NA, translate +rownames only if they're a character vector.

    +

    A string is equivalent to TRUE, but allows you to override the +default name.

    +

    For backward compatibility, NULL is equivalent to FALSE.

    temporary

    If TRUE, will generate a temporary table statement.

    ...

    Other arguments used by individual methods.

    + +

    DBI-backends

    + + +

    If you implement one method (i.e. for strings or data frames), you need +to implement both, otherwise the S4 dispatch rules will be ambiguous +and will generate an error on every call.

    + + +

    Examples

    +
    sqlCreateTable(ANSI(), "my-table", c(a = "integer", b = "text"))
    #> <SQL> CREATE TABLE "my-table" ( +#> "a" integer, +#> "b" text +#> ) +#>
    sqlCreateTable(ANSI(), "my-table", iris)
    #> <SQL> CREATE TABLE "my-table" ( +#> "Sepal.Length" DOUBLE, +#> "Sepal.Width" DOUBLE, +#> "Petal.Length" DOUBLE, +#> "Petal.Width" DOUBLE, +#> "Species" TEXT +#> ) +#>
    +# By default, character row names are converted to a row_names colum +sqlCreateTable(ANSI(), "mtcars", mtcars[, 1:5])
    #> <SQL> CREATE TABLE "mtcars" ( +#> "row_names" TEXT, +#> "mpg" DOUBLE, +#> "cyl" DOUBLE, +#> "disp" DOUBLE, +#> "hp" DOUBLE, +#> "drat" DOUBLE +#> ) +#>
    sqlCreateTable(ANSI(), "mtcars", mtcars[, 1:5], row.names = FALSE)
    #> <SQL> CREATE TABLE "mtcars" ( +#> "mpg" DOUBLE, +#> "cyl" DOUBLE, +#> "disp" DOUBLE, +#> "hp" DOUBLE, +#> "drat" DOUBLE +#> ) +#>
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/sqlData.html b/docs/reference/sqlData.html new file mode 100644 index 000000000..22dd0601d --- /dev/null +++ b/docs/reference/sqlData.html @@ -0,0 +1,196 @@ + + + + + + + + +Convert a data frame into form suitable for upload to an SQL database — sqlData • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    This is a generic method that coerces R objects into vectors suitable for +upload to the database. The output will vary a little from method to +method depending on whether the main upload device is through a single +SQL string or multiple parameterized queries. +This method is mostly useful for backend implementers.

    + + +
    sqlData(con, value, row.names = NA, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + +
    con

    A database connection.

    value

    A data frame

    row.names

    Either TRUE, FALSE, NA or a string.

    +

    If TRUE, always translate row names to a column called "row_names". +If FALSE, never translate row names. If NA, translate +rownames only if they're a character vector.

    +

    A string is equivalent to TRUE, but allows you to override the +default name.

    +

    For backward compatibility, NULL is equivalent to FALSE.

    ...

    Other arguments used by individual methods.

    + +

    Details

    + +

    The default method:

      +
    • Converts factors to characters

    • +
    • Quotes all strings

    • +
    • Converts all columns to strings

    • +
    • Replaces NA with NULL

    • +
    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +sqlData(con, head(iris))
    #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 5.1 3.5 1.4 0.2 'setosa' +#> 2 4.9 3.0 1.4 0.2 'setosa' +#> 3 4.7 3.2 1.3 0.2 'setosa' +#> 4 4.6 3.1 1.5 0.2 'setosa' +#> 5 5.0 3.6 1.4 0.2 'setosa' +#> 6 5.4 3.9 1.7 0.4 'setosa'
    sqlData(con, head(mtcars))
    #> mpg cyl disp hp drat wt qsec vs am gear carb +#> 1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 +#> 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 +#> 3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 +#> 4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 +#> 5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 +#> 6 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/sqlInterpolate.html b/docs/reference/sqlInterpolate.html new file mode 100644 index 000000000..759688740 --- /dev/null +++ b/docs/reference/sqlInterpolate.html @@ -0,0 +1,175 @@ + + + + + + + + +Safely interpolate values into an SQL string — sqlInterpolate • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    Safely interpolate values into an SQL string

    + + +
    sqlInterpolate(conn, sql, ..., .dots = list())
    + +

    Arguments

    + + + + + + + + + + + + + + +
    conn

    A database connection.

    sql

    A SQL string containing variables to interpolate. +Variables must start with a question mark and can be any valid R +identifier, i.e. it must start with a letter or ., and be followed +by a letter, digit, . or _.

    ..., .dots

    Named values (for ...) or a named list (for .dots) +to interpolate into a string. All strings +will be first escaped with dbQuoteString() prior +to interpolation to protect against SQL injection attacks.

    + +

    Backend authors

    + + +

    If you are implementing an SQL backend with non-ANSI quoting rules, you'll +need to implement a method for sqlParseVariables(). Failure to +do so does not expose you to SQL injection attacks, but will (rarely) result +in errors matching supplied and interpolated variables.

    + + +

    Examples

    +
    sql <- "SELECT * FROM X WHERE name = ?name" +sqlInterpolate(ANSI(), sql, name = "Hadley")
    #> <SQL> SELECT * FROM X WHERE name = 'Hadley'
    +# This is safe because the single quote has been double escaped +sqlInterpolate(ANSI(), sql, name = "H'); DROP TABLE--;")
    #> <SQL> SELECT * FROM X WHERE name = 'H''); DROP TABLE--;'
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/sqlParseVariables.html b/docs/reference/sqlParseVariables.html new file mode 100644 index 000000000..80e832b73 --- /dev/null +++ b/docs/reference/sqlParseVariables.html @@ -0,0 +1,204 @@ + + + + + + + + +Parse interpolated variables from SQL. — sqlParseVariables • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    If you're implementing a backend that uses non-ANSI quoting or commenting +rules, you'll need to implement a method for sqlParseVariables that +calls sqlParseVariablesImpl with the appropriate quote and +comment specifications.

    + + +
    sqlParseVariables(conn, sql, ...)
    +
    +sqlCommentSpec(start, end, endRequired)
    +
    +sqlQuoteSpec(start, end, escape = "", doubleEscape = TRUE)
    +
    +sqlParseVariablesImpl(sql, quotes, comments)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    sql

    SQL to parse (a character string)

    start, end

    Start and end characters for quotes and comments

    endRequired

    Is the ending character of a comment required?

    escape

    What character can be used to escape quoting characters? +Defaults to "", i.e. nothing.

    doubleEscape

    Can quoting characters be escaped by doubling them? +Defaults to TRUE.

    quotes

    A list of QuoteSpec calls defining the quoting +specification.

    comments

    A list of CommentSpec calls defining the commenting +specification.

    + + +

    Examples

    +
    # Use [] for quoting and no comments +sqlParseVariablesImpl("[?a]", + list(sqlQuoteSpec("[", "]", "\\", FALSE)), + list() +)
    #> $start +#> integer(0) +#> +#> $end +#> integer(0) +#>
    +# Standard quotes, use # for commenting +sqlParseVariablesImpl("# ?a\n?b", + list(sqlQuoteSpec("'", "'"), sqlQuoteSpec('"', '"')), + list(sqlCommentSpec("#", "\n", FALSE)) +)
    #> $start +#> integer(0) +#> +#> $end +#> integer(0) +#>
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + diff --git a/docs/reference/transactions.html b/docs/reference/transactions.html new file mode 100644 index 000000000..42bef1555 --- /dev/null +++ b/docs/reference/transactions.html @@ -0,0 +1,257 @@ + + + + + + + + +Begin/commit/rollback SQL transactions — transactions • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    + +
    +
    + + + +

    A transaction encapsulates several SQL statements in an atomic unit. +It is initiated with dbBegin() and either made persistent with dbCommit() +or undone with dbRollback(). +In any case, the DBMS guarantees that either all or none of the statements +have a permanent effect. +This helps ensuring consistency of write operations to multiple tables. + +

    Methods in other packages

    + +
      +
    • RSQLite::dbBegin("SQLiteConnection")

    • +
    • RSQLite::dbCommit("SQLiteConnection")

    • +
    • RSQLite::dbRollback("SQLiteConnection")

    • +

    + + +
    dbBegin(conn, ...)
    +
    +dbCommit(conn, ...)
    +
    +dbRollback(conn, ...)
    + +

    Arguments

    + + + + + + + + + + +
    conn

    A DBIConnection object, as returned by +dbConnect().

    ...

    Other parameters passed on to methods.

    + +

    Value

    + +

    dbBegin(), dbCommit() and dbRollback() return TRUE, invisibly. +The implementations are expected to raise an error in case of failure, +but this is not tested. +In any way, all generics throw an error with a closed +or invalid connection. +In addition, a call to dbCommit() +or dbRollback() +without a prior call to dbBegin() raises an error. +Nested transactions are not supported by DBI, +an attempt to call dbBegin() twice +yields an error.

    + +

    Details

    + +

    Not all database engines implement transaction management, in which case +these methods should not be implemented for the specific +DBIConnection subclass.

    + +

    Specification

    + + +

    Actual support for transactions may vary between backends. +A transaction is initiated by a call to dbBegin() +and committed by a call to dbCommit(). +Data written in a transaction must persist after the transaction is committed. +For example, a record that is missing when the transaction is started +but is created during the transaction +must exist +both during +and after the transaction, +and also in a new connection.

    +

    A transaction +can also be aborted with dbRollback(). +All data written in such a transaction must be removed after the +transaction is rolled back. +For example, a record that is missing when the transaction is started +but is created during the transaction +must not exist anymore after the rollback.

    +

    Disconnection from a connection with an open transaction +effectively rolls back the transaction. +All data written in such a transaction must be removed after the +transaction is rolled back.

    +

    The behavior is not specified if other arguments are passed to these +functions. In particular, RSQLite issues named transactions +with support for nesting +if the name argument is set.

    +

    The transaction isolation level is not specified by DBI.

    + +

    See also

    + +

    Self-contained transactions: dbWithTransaction()

    + + +

    Examples

    +
    con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbWriteTable(con, "cash", data.frame(amount = 100)) +dbWriteTable(con, "account", data.frame(amount = 2000)) + +# All operations are carried out as logical unit: +dbBegin(con) +withdrawal <- 300 +dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
    #> [1] 1
    dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
    #> [1] 1
    dbCommit(con) + +dbReadTable(con, "cash")
    #> amount +#> 1 400
    dbReadTable(con, "account")
    #> amount +#> 1 1700
    +# Rolling back after detecting negative value on account: +dbBegin(con) +withdrawal <- 5000 +dbExecute(con, "UPDATE cash SET amount = amount + ?", list(withdrawal))
    #> [1] 1
    dbExecute(con, "UPDATE account SET amount = amount - ?", list(withdrawal))
    #> [1] 1
    if (dbReadTable(con, "account")$amount >= 0) { + dbCommit(con) +} else { + dbRollback(con) +} + +dbReadTable(con, "cash")
    #> amount +#> 1 400
    dbReadTable(con, "account")
    #> amount +#> 1 1700
    +
    + +
    + +
    + + +
    +

    Site built with pkgdown.

    +
    + +
    +
    + + + From 75778a9d34c8b705309ab5032033af62e08346ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 27 Jan 2018 21:15:31 +0100 Subject: [PATCH 03/44] test removal of names - Breaking change: If the `names` argument is unset, `SQL()` strips the names from the output. --- tests/testthat/test-quote.R | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/testthat/test-quote.R b/tests/testthat/test-quote.R index ca8b75b8b..84ec40bc2 100644 --- a/tests/testthat/test-quote.R +++ b/tests/testthat/test-quote.R @@ -12,4 +12,5 @@ test_that("identifier", { test_that("SQL names", { expect_null(names(SQL(letters))) expect_equal(names(SQL(letters, names = LETTERS)), LETTERS) + expect_null(names(SQL(setNames(letters, LETTERS)))) }) From a46249ec68f585e17fad932ceb9ed3864e9d1f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 27 Jan 2018 21:34:33 +0100 Subject: [PATCH 04/44] default implementations of dbQuoteIdentifier() and dbQuoteLiteral() preserve names, closes #173 - Default implementations of `dbQuoteIdentifier()` and `dbQuoteLiteral()` preserve names, default implementation of `dbQuoteString()` strips names (#173). --- R/quote.R | 8 ++++---- tests/testthat/test-quote.R | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/R/quote.R b/R/quote.R index 5145a9638..6c2f15a8f 100644 --- a/R/quote.R +++ b/R/quote.R @@ -112,10 +112,10 @@ quote_identifier <- # Avoid fixed = TRUE due to https://github.com/r-dbi/DBItest/issues/156 x <- gsub('"', '""', enc2utf8(x)) if (length(x) == 0L) { - SQL(character()) + SQL(character(), names = names(x)) } else { # Not calling encodeString() here to keep things simple - SQL(paste('"', x, '"', sep = "")) + SQL(paste('"', x, '"', sep = ""), names = names(x)) } } @@ -285,12 +285,12 @@ setMethod("dbQuoteLiteral", signature("DBIConnection"), }, character(1) ) - return(SQL(blob_data)) + return(SQL(blob_data, names = names(x))) } if (is.logical(x)) x <- as.numeric(x) x <- as.character(x) x[is.na(x)] <- "NULL" - SQL(x) + SQL(x, names = names(x)) } ) diff --git a/tests/testthat/test-quote.R b/tests/testthat/test-quote.R index 84ec40bc2..cfca97d5c 100644 --- a/tests/testthat/test-quote.R +++ b/tests/testthat/test-quote.R @@ -9,6 +9,15 @@ test_that("identifier", { expect_equal(dbQuoteIdentifier(ANSI(), SQL('"a b"')), SQL('"a b"')) }) +test_that("identifier names", { + expect_equal(dbQuoteIdentifier(ANSI(), setNames(character(), character())), SQL(character(), names = character())) + expect_equal(dbQuoteIdentifier(ANSI(), c(a = "a")), SQL('"a"', names = "a")) + expect_equal(dbQuoteIdentifier(ANSI(), c(ab = "a b")), SQL('"a b"', names = "ab")) + + expect_equal(dbQuoteIdentifier(ANSI(), SQL('"a"', names = "a")), SQL('"a"', names = "a")) + expect_equal(dbQuoteIdentifier(ANSI(), SQL('"a b"', names = "ab")), SQL('"a b"', names = "ab")) +}) + test_that("SQL names", { expect_null(names(SQL(letters))) expect_equal(names(SQL(letters, names = LETTERS)), LETTERS) From fc8ced889c02fb0d5a5f004e5727411599ac4dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 03:16:26 +0100 Subject: [PATCH 05/44] use dev roxygen2 --- DESCRIPTION | 2 +- man/DBIConnection-class.Rd | 2 ++ man/DBIDriver-class.Rd | 2 ++ man/DBIObject-class.Rd | 1 + man/DBIResult-class.Rd | 2 ++ man/dbBind.Rd | 1 + man/dbClearResult.Rd | 1 + man/dbColumnInfo.Rd | 1 + man/dbConnect.Rd | 1 + man/dbDataType.Rd | 2 ++ man/dbDisconnect.Rd | 1 + man/dbDriver.Rd | 1 + man/dbExecute.Rd | 1 + man/dbExistsTable.Rd | 1 + man/dbFetch.Rd | 1 + man/dbGetException.Rd | 1 + man/dbGetInfo.Rd | 4 +++- man/dbGetQuery.Rd | 1 + man/dbGetRowCount.Rd | 1 + man/dbGetRowsAffected.Rd | 1 + man/dbGetStatement.Rd | 1 + man/dbHasCompleted.Rd | 1 + man/dbIsValid.Rd | 3 +++ man/dbListConnections.Rd | 1 + man/dbListFields.Rd | 1 + man/dbListResults.Rd | 1 + man/dbListTables.Rd | 1 + man/dbQuoteIdentifier.Rd | 1 + man/dbQuoteLiteral.Rd | 1 + man/dbQuoteString.Rd | 1 + man/dbReadTable.Rd | 1 + man/dbRemoveTable.Rd | 1 + man/dbSendQuery.Rd | 1 + man/dbSendStatement.Rd | 1 + man/dbWriteTable.Rd | 1 + man/make.db.names.Rd | 1 - man/sqlAppendTable.Rd | 1 + 37 files changed, 44 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index b7fe13712..dc5a51bb5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -51,4 +51,4 @@ Collate: 'transactions.R' VignetteBuilder: knitr Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "pkgapi::api_roclet")) -RoxygenNote: 6.0.1 +RoxygenNote: 6.0.1.9000 diff --git a/man/DBIConnection-class.Rd b/man/DBIConnection-class.Rd index 5e217dc24..2c38aacad 100644 --- a/man/DBIConnection-class.Rd +++ b/man/DBIConnection-class.Rd @@ -41,3 +41,5 @@ Other DBIConnection generics: \code{\link{dbDataType}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBI classes} +\concept{DBIConnection generics} diff --git a/man/DBIDriver-class.Rd b/man/DBIDriver-class.Rd index f4792a925..1eaa972ba 100644 --- a/man/DBIDriver-class.Rd +++ b/man/DBIDriver-class.Rd @@ -21,3 +21,5 @@ Other DBIDriver generics: \code{\link{dbConnect}}, \code{\link{dbGetInfo}}, \code{\link{dbIsValid}}, \code{\link{dbListConnections}} } +\concept{DBI classes} +\concept{DBIDriver generics} diff --git a/man/DBIObject-class.Rd b/man/DBIObject-class.Rd index dd1c945b9..9d5aa7eed 100644 --- a/man/DBIObject-class.Rd +++ b/man/DBIObject-class.Rd @@ -52,3 +52,4 @@ Other DBI classes: \code{\link{DBIConnection-class}}, \code{\link{DBIDriver-class}}, \code{\link{DBIResult-class}} } +\concept{DBI classes} diff --git a/man/DBIResult-class.Rd b/man/DBIResult-class.Rd index b27b9169c..a5668743d 100644 --- a/man/DBIResult-class.Rd +++ b/man/DBIResult-class.Rd @@ -35,3 +35,5 @@ Other DBIResult generics: \code{\link{dbBind}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBI classes} +\concept{DBIResult generics} diff --git a/man/dbBind.Rd b/man/dbBind.Rd index 687f0eec5..0334f81f0 100644 --- a/man/dbBind.Rd +++ b/man/dbBind.Rd @@ -188,3 +188,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbClearResult.Rd b/man/dbClearResult.Rd index 0d34e7758..3672b9acb 100644 --- a/man/dbClearResult.Rd +++ b/man/dbClearResult.Rd @@ -55,3 +55,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbColumnInfo.Rd b/man/dbColumnInfo.Rd index fdf05173a..0f832834a 100644 --- a/man/dbColumnInfo.Rd +++ b/man/dbColumnInfo.Rd @@ -45,3 +45,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbConnect.Rd b/man/dbConnect.Rd index 4866530ae..ba24b53f6 100644 --- a/man/dbConnect.Rd +++ b/man/dbConnect.Rd @@ -68,3 +68,4 @@ Other DBIDriver generics: \code{\link{DBIDriver-class}}, \code{\link{dbGetInfo}}, \code{\link{dbIsValid}}, \code{\link{dbListConnections}} } +\concept{DBIDriver generics} diff --git a/man/dbDataType.Rd b/man/dbDataType.Rd index 797eae97d..66d6f838b 100644 --- a/man/dbDataType.Rd +++ b/man/dbDataType.Rd @@ -128,3 +128,5 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} +\concept{DBIDriver generics} diff --git a/man/dbDisconnect.Rd b/man/dbDisconnect.Rd index 1166b9ae4..754ad1817 100644 --- a/man/dbDisconnect.Rd +++ b/man/dbDisconnect.Rd @@ -48,3 +48,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbDriver.Rd b/man/dbDriver.Rd index 8cba8992c..1eb655c67 100644 --- a/man/dbDriver.Rd +++ b/man/dbDriver.Rd @@ -63,3 +63,4 @@ Other DBIDriver generics: \code{\link{DBIDriver-class}}, \code{\link{dbGetInfo}}, \code{\link{dbIsValid}}, \code{\link{dbListConnections}} } +\concept{DBIDriver generics} diff --git a/man/dbExecute.Rd b/man/dbExecute.Rd index 9484baf8b..dae2b025c 100644 --- a/man/dbExecute.Rd +++ b/man/dbExecute.Rd @@ -64,3 +64,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbExistsTable.Rd b/man/dbExistsTable.Rd index bc719b660..db6d5a62a 100644 --- a/man/dbExistsTable.Rd +++ b/man/dbExistsTable.Rd @@ -76,3 +76,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbFetch.Rd b/man/dbFetch.Rd index f9ef167be..a22511de2 100644 --- a/man/dbFetch.Rd +++ b/man/dbFetch.Rd @@ -154,3 +154,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbGetException.Rd b/man/dbGetException.Rd index c8534039d..cae662b73 100644 --- a/man/dbGetException.Rd +++ b/man/dbGetException.Rd @@ -32,3 +32,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbGetInfo.Rd b/man/dbGetInfo.Rd index a161ded0b..fa5711919 100644 --- a/man/dbGetInfo.Rd +++ b/man/dbGetInfo.Rd @@ -2,7 +2,6 @@ % Please edit documentation in R/DBObject.R, R/DBResult.R \name{dbGetInfo} \alias{dbGetInfo} -\alias{dbGetInfo} \title{Get DBMS metadata} \usage{ dbGetInfo(dbObj, ...) @@ -72,3 +71,6 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIConnection generics} +\concept{DBIDriver generics} +\concept{DBIResult generics} diff --git a/man/dbGetQuery.Rd b/man/dbGetQuery.Rd index 6c0d0bcea..626d97e3d 100644 --- a/man/dbGetQuery.Rd +++ b/man/dbGetQuery.Rd @@ -89,3 +89,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbGetRowCount.Rd b/man/dbGetRowCount.Rd index dc538d270..f5551fb24 100644 --- a/man/dbGetRowCount.Rd +++ b/man/dbGetRowCount.Rd @@ -63,3 +63,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbGetRowsAffected.Rd b/man/dbGetRowsAffected.Rd index 4acfcbf5b..d089fcb58 100644 --- a/man/dbGetRowsAffected.Rd +++ b/man/dbGetRowsAffected.Rd @@ -50,3 +50,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbGetStatement.Rd b/man/dbGetStatement.Rd index 45a7f97fe..38d1feef2 100644 --- a/man/dbGetStatement.Rd +++ b/man/dbGetStatement.Rd @@ -44,3 +44,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbHasCompleted.Rd b/man/dbHasCompleted.Rd index 4af9f5d37..bc34e8fa2 100644 --- a/man/dbHasCompleted.Rd +++ b/man/dbHasCompleted.Rd @@ -68,3 +68,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbIsValid.Rd b/man/dbIsValid.Rd index 3fa4f4a21..3ca6a893c 100644 --- a/man/dbIsValid.Rd +++ b/man/dbIsValid.Rd @@ -78,3 +78,6 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIConnection generics} +\concept{DBIDriver generics} +\concept{DBIResult generics} diff --git a/man/dbListConnections.Rd b/man/dbListConnections.Rd index cc76ad6d9..27ac8516c 100644 --- a/man/dbListConnections.Rd +++ b/man/dbListConnections.Rd @@ -25,3 +25,4 @@ Other DBIDriver generics: \code{\link{DBIDriver-class}}, \code{\link{dbDriver}}, \code{\link{dbGetInfo}}, \code{\link{dbIsValid}} } +\concept{DBIDriver generics} diff --git a/man/dbListFields.Rd b/man/dbListFields.Rd index 908a11f56..aeb92912d 100644 --- a/man/dbListFields.Rd +++ b/man/dbListFields.Rd @@ -41,3 +41,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbListResults.Rd b/man/dbListResults.Rd index 187f87ce3..9d66578e4 100644 --- a/man/dbListResults.Rd +++ b/man/dbListResults.Rd @@ -32,3 +32,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbListTables.Rd b/man/dbListTables.Rd index 637c47252..e421ca13c 100644 --- a/man/dbListTables.Rd +++ b/man/dbListTables.Rd @@ -65,3 +65,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbQuoteIdentifier.Rd b/man/dbQuoteIdentifier.Rd index ebc076546..3458f070d 100644 --- a/man/dbQuoteIdentifier.Rd +++ b/man/dbQuoteIdentifier.Rd @@ -85,3 +85,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbQuoteLiteral.Rd b/man/dbQuoteLiteral.Rd index b38eb0e43..e9d62fd71 100644 --- a/man/dbQuoteLiteral.Rd +++ b/man/dbQuoteLiteral.Rd @@ -54,3 +54,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteString}} } +\concept{DBIResult generics} diff --git a/man/dbQuoteString.Rd b/man/dbQuoteString.Rd index d580a48d0..5a63eb56c 100644 --- a/man/dbQuoteString.Rd +++ b/man/dbQuoteString.Rd @@ -86,3 +86,4 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbQuoteIdentifier}}, \code{\link{dbQuoteLiteral}} } +\concept{DBIResult generics} diff --git a/man/dbReadTable.Rd b/man/dbReadTable.Rd index b2a73ed5d..0d461bb6e 100644 --- a/man/dbReadTable.Rd +++ b/man/dbReadTable.Rd @@ -110,3 +110,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbRemoveTable.Rd b/man/dbRemoveTable.Rd index 400064fc3..b629de015 100644 --- a/man/dbRemoveTable.Rd +++ b/man/dbRemoveTable.Rd @@ -73,3 +73,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbSendQuery.Rd b/man/dbSendQuery.Rd index 137fb3575..64b7004b9 100644 --- a/man/dbSendQuery.Rd +++ b/man/dbSendQuery.Rd @@ -88,3 +88,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbSendStatement.Rd b/man/dbSendStatement.Rd index 6110ef88e..bc7f1e4b4 100644 --- a/man/dbSendStatement.Rd +++ b/man/dbSendStatement.Rd @@ -84,3 +84,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbWriteTable}} } +\concept{DBIConnection generics} diff --git a/man/dbWriteTable.Rd b/man/dbWriteTable.Rd index 43ea97429..052abce86 100644 --- a/man/dbWriteTable.Rd +++ b/man/dbWriteTable.Rd @@ -175,3 +175,4 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}} } +\concept{DBIConnection generics} diff --git a/man/make.db.names.Rd b/man/make.db.names.Rd index 2e20acdae..8d7db8a9d 100644 --- a/man/make.db.names.Rd +++ b/man/make.db.names.Rd @@ -5,7 +5,6 @@ \alias{SQLKeywords} \alias{isSQLKeyword} \alias{make.db.names.default} -\alias{isSQLKeyword} \alias{isSQLKeyword.default} \title{Make R identifiers into legal SQL identifiers} \usage{ diff --git a/man/sqlAppendTable.Rd b/man/sqlAppendTable.Rd index 5a9492c41..d9bd2737e 100644 --- a/man/sqlAppendTable.Rd +++ b/man/sqlAppendTable.Rd @@ -50,3 +50,4 @@ sqlAppendTableTemplate(ANSI(), "iris", iris) sqlAppendTableTemplate(ANSI(), "mtcars", mtcars) sqlAppendTableTemplate(ANSI(), "mtcars", mtcars, row.names = FALSE) } +\concept{SQL generation} From 2651fffbe702670fffcf4fc467da7504b853493b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 03:16:44 +0100 Subject: [PATCH 06/44] deprecate dbListConnections() - `dbListConnections()` is soft-deprecated by documentation. --- R/DBDriver.R | 5 ++--- man/dbListConnections.Rd | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/R/DBDriver.R b/R/DBDriver.R index 526e54919..24c6f94e6 100644 --- a/R/DBDriver.R +++ b/R/DBDriver.R @@ -170,9 +170,8 @@ setGeneric("dbConnect", #' List currently open connections #' -#' Drivers that implement only a single connections MUST return a list -#' containing a single element. If no connection are open, methods MUST -#' return an empty list. +#' DEPRECATED, drivers are no longer required to implement this method. +#' Keep track of the connections you opened if you require a list. #' #' @param drv A object inheriting from [DBIDriver-class] #' @param ... Other arguments passed on to methods. diff --git a/man/dbListConnections.Rd b/man/dbListConnections.Rd index 27ac8516c..09ae7c176 100644 --- a/man/dbListConnections.Rd +++ b/man/dbListConnections.Rd @@ -15,9 +15,8 @@ dbListConnections(drv, ...) a list } \description{ -Drivers that implement only a single connections MUST return a list -containing a single element. If no connection are open, methods MUST -return an empty list. +DEPRECATED, drivers are no longer required to implement this method. +Keep track of the connections you opened if you require a list. } \seealso{ Other DBIDriver generics: \code{\link{DBIDriver-class}}, From 13d4c5595c1f9fca587c08ee9857ef240087b476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 02:24:06 +0000 Subject: [PATCH 07/44] Deploy from Travis build 958 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/334261807 Commit: 2651fffbe702670fffcf4fc467da7504b853493b --- docs/articles/DBI-1.html | 14 +++++++------- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- docs/news/index.html | 6 +++--- docs/reference/DBIConnection-class.html | 2 +- docs/reference/DBIDriver-class.html | 2 +- docs/reference/DBIObject-class.html | 4 ++-- docs/reference/DBIResult-class.html | 2 +- docs/reference/dbBind.html | 2 +- docs/reference/dbClearResult.html | 2 +- docs/reference/dbColumnInfo.html | 2 +- docs/reference/dbConnect.html | 2 +- docs/reference/dbDataType.html | 4 ++-- docs/reference/dbDisconnect.html | 2 +- docs/reference/dbDriver.html | 4 ++-- docs/reference/dbExecute.html | 2 +- docs/reference/dbExistsTable.html | 2 +- docs/reference/dbFetch.html | 2 +- docs/reference/dbGetException.html | 2 +- docs/reference/dbGetQuery.html | 2 +- docs/reference/dbGetRowCount.html | 2 +- docs/reference/dbGetRowsAffected.html | 2 +- docs/reference/dbGetStatement.html | 2 +- docs/reference/dbHasCompleted.html | 2 +- docs/reference/dbIsValid.html | 6 +++--- docs/reference/dbListConnections.html | 7 +++---- docs/reference/dbListFields.html | 2 +- docs/reference/dbListResults.html | 2 +- docs/reference/dbListTables.html | 2 +- docs/reference/dbQuoteIdentifier.html | 2 +- docs/reference/dbQuoteLiteral.html | 2 +- docs/reference/dbQuoteString.html | 2 +- docs/reference/dbReadTable.html | 2 +- docs/reference/dbRemoveTable.html | 2 +- docs/reference/dbSendQuery.html | 2 +- docs/reference/dbSendStatement.html | 2 +- docs/reference/dbWriteTable.html | 2 +- docs/reference/hidden_aliases.html | 4 ++-- 38 files changed, 54 insertions(+), 55 deletions(-) diff --git a/docs/articles/DBI-1.html b/docs/articles/DBI-1.html index 972cabe69..9ba08f7ee 100644 --- a/docs/articles/DBI-1.html +++ b/docs/articles/DBI-1.html @@ -200,13 +200,13 @@

    summary(object, ...):
    -

    produces a concise description of the object. The default method for DBIObject simply invokes dbGetInfo(dbObj) and prints the name-value pairs one per line. Individual implementations may tailor this appropriately.

    +

    produces a concise description of the object. The default method for DBIObject simply invokes dbGetInfo(dbObj) and prints the name-value pairs one per line. Individual implementations may tailor this appropriately.

    -dbGetInfo(dbObj, ...):
    +dbGetInfo(dbObj, ...):

    extracts information (meta-data) relevant for the DBIObject dbObj. It may return a list of key/value pairs, individual meta-data if supplied in the call, or NULL if the requested meta-data is not available.

    -

    Hint: Driver implementations may choose to allow an argument what to specify individual meta-data, e.g., dbGetInfo(drv, what = max.connections).

    +

    Hint: Driver implementations may choose to allow an argument what to specify individual meta-data, e.g., dbGetInfo(drv, what = max.connections).

    In the next few sub-sections we describe in detail each of these classes and their methods.

    @@ -235,7 +235,7 @@

    list of current connections being handled by the drv driver. May be NULL if there are no open connections. Drivers that do not support multiple connections may return the one open connection.

    -dbGetInfo(dbObj, ...):
    +dbGetInfo(dbObj, ...):

    returns a list of name-value pairs of information about the driver.

    Hint: Useful entries could include

    @@ -310,7 +310,7 @@

    Hint: The ANSI SQL-92 defines both a status code and an status message that could be return as members of the list.

    -dbGetInfo(dbObj, ...):
    +dbGetInfo(dbObj, ...):

    returns a list of name-value pairs describing the state of the connection; it may return one or more meta-data, the actual driver method allows to specify individual pieces of meta-data (e.g., maximum number of open results/cursors).

    Hint: Useful entries could include

    @@ -424,7 +424,7 @@

    flushes any pending data and frees all resources (local and remote) used by the object res on both sides of the connection. Returns a logical indicating success or not.

    -dbGetInfo(dbObj, ...):
    +dbGetInfo(dbObj, ...):

    returns a name-value list with the state of the result set.

    Hint: Useful entries could include

    @@ -555,7 +555,7 @@

    returns a character vector of SQL keywords (reserved words). The default method returns the list of .SQL92Keywords, but drivers should update this vector with the DBMS-specific additional reserved words.

    -isSQLKeyword(dbObj, name, ...):
    +isSQLKeyword(dbObj, name, ...):

    for each element in the character vector name determine whether or not it is an SQL keyword, as reported by the generic function SQLKeywords. Returns a logical vector parallel to the input object name.

    diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 7962a3106..dd12b611e 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

    Implementing a new backend

    Hadley Wickham

    -

    2018-01-27

    +

    2018-01-28

  • diff --git a/docs/articles/spec.html b/docs/articles/spec.html index a5e4ea100..29459959d 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

    DBI specification

    Kirill Müller

    -

    2018-01-27

    +

    2018-01-28

    diff --git a/docs/news/index.html b/docs/news/index.html index 42f5f7924..70f19689f 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -261,7 +261,7 @@

    DBI 0.4 (2016-04-30)

    • New package maintainer: Kirill Müller.

    • -
    • dbGetInfo() gains a default method that extracts the information from dbGetStatement(), dbGetRowsAffected(), dbHasCompleted(), and dbGetRowCount(). This means that most drivers should no longer need to implement dbGetInfo() (which may be deprecated anyway at some point) (#55).

    • +
    • dbGetInfo() gains a default method that extracts the information from dbGetStatement(), dbGetRowsAffected(), dbHasCompleted(), and dbGetRowCount(). This means that most drivers should no longer need to implement dbGetInfo() (which may be deprecated anyway at some point) (#55).

    • dbDataType() and dbQuoteString() are now properly exported.

    • The default implementation for dbDataType() (powered by dbiDataType()) now also supports difftime and AsIs objects and lists of raw (#70).

    • Default dbGetQuery() method now always calls dbFetch(), in a tryCatch() block.

    • @@ -311,7 +311,7 @@

      New default methods

      @@ -323,7 +323,7 @@

      The following functions are soft-deprecated. They are going away, and developers who use the DBI should begin preparing. The formal deprecation process will begin in July 2015, where these function will emit warnings on use.

    • dbGetDBIVersion() is deprecated since it’s now just a thin wrapper around packageVersion("DBI").

    • diff --git a/docs/reference/DBIConnection-class.html b/docs/reference/DBIConnection-class.html index c0c2513ec..6268ab3c0 100644 --- a/docs/reference/DBIConnection-class.html +++ b/docs/reference/DBIConnection-class.html @@ -123,7 +123,7 @@

      See a

      Other DBIConnection generics: dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/DBIDriver-class.html b/docs/reference/DBIDriver-class.html index d4032354c..77b730953 100644 --- a/docs/reference/DBIDriver-class.html +++ b/docs/reference/DBIDriver-class.html @@ -118,7 +118,7 @@

      See a DBIResult-class

      Other DBIDriver generics: dbConnect, dbDataType, dbDriver, - dbGetInfo, dbIsValid, + dbGetInfo, dbIsValid, dbListConnections

      diff --git a/docs/reference/DBIObject-class.html b/docs/reference/DBIObject-class.html index b624f57d7..822e5cfb8 100644 --- a/docs/reference/DBIObject-class.html +++ b/docs/reference/DBIObject-class.html @@ -122,11 +122,11 @@

      See a DBIObject-class

      Other DBIResult generics: dbBind, dbClearResult, dbColumnInfo, - dbFetch, dbGetInfo, + dbFetch, dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, diff --git a/docs/reference/dbBind.html b/docs/reference/dbBind.html index 5989447c3..d5925de35 100644 --- a/docs/reference/dbBind.html +++ b/docs/reference/dbBind.html @@ -254,7 +254,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbClearResult, dbColumnInfo, - dbFetch, dbGetInfo, + dbFetch, dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, diff --git a/docs/reference/dbClearResult.html b/docs/reference/dbClearResult.html index 5dca9a184..968ed5687 100644 --- a/docs/reference/dbClearResult.html +++ b/docs/reference/dbClearResult.html @@ -149,7 +149,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbColumnInfo, - dbFetch, dbGetInfo, + dbFetch, dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, diff --git a/docs/reference/dbColumnInfo.html b/docs/reference/dbColumnInfo.html index ac6445bf4..6a4d4f309 100644 --- a/docs/reference/dbColumnInfo.html +++ b/docs/reference/dbColumnInfo.html @@ -136,7 +136,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, - dbFetch, dbGetInfo, + dbFetch, dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, diff --git a/docs/reference/dbConnect.html b/docs/reference/dbConnect.html index aa855209f..8ba83cfe2 100644 --- a/docs/reference/dbConnect.html +++ b/docs/reference/dbConnect.html @@ -163,7 +163,7 @@

      See a

      dbDisconnect() to disconnect from a database.

      Other DBIDriver generics: DBIDriver-class, dbDataType, dbDriver, - dbGetInfo, dbIsValid, + dbGetInfo, dbIsValid, dbListConnections

      diff --git a/docs/reference/dbDataType.html b/docs/reference/dbDataType.html index 81e169f71..27e4a76c2 100644 --- a/docs/reference/dbDataType.html +++ b/docs/reference/dbDataType.html @@ -195,12 +195,12 @@

      See a

      Other DBIDriver generics: DBIDriver-class, dbConnect, dbDriver, - dbGetInfo, dbIsValid, + dbGetInfo, dbIsValid, dbListConnections

      Other DBIConnection generics: DBIConnection-class, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbDisconnect.html b/docs/reference/dbDisconnect.html index 44323f747..601477a0d 100644 --- a/docs/reference/dbDisconnect.html +++ b/docs/reference/dbDisconnect.html @@ -148,7 +148,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbDriver.html b/docs/reference/dbDriver.html index bee942a65..992d68112 100644 --- a/docs/reference/dbDriver.html +++ b/docs/reference/dbDriver.html @@ -157,11 +157,11 @@

      See a

      Other DBIDriver generics: DBIDriver-class, dbConnect, dbDataType, - dbGetInfo, dbIsValid, + dbGetInfo, dbIsValid, dbListConnections

      Other DBIDriver generics: DBIDriver-class, dbConnect, dbDataType, - dbGetInfo, dbIsValid, + dbGetInfo, dbIsValid, dbListConnections

      diff --git a/docs/reference/dbExecute.html b/docs/reference/dbExecute.html index 6172f28ef..ba6b578c1 100644 --- a/docs/reference/dbExecute.html +++ b/docs/reference/dbExecute.html @@ -160,7 +160,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbExistsTable.html b/docs/reference/dbExistsTable.html index 810419338..631463d48 100644 --- a/docs/reference/dbExistsTable.html +++ b/docs/reference/dbExistsTable.html @@ -167,7 +167,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbGetException, - dbGetInfo, dbGetQuery, + dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbFetch.html b/docs/reference/dbFetch.html index 6befbf8b8..46bae2ed7 100644 --- a/docs/reference/dbFetch.html +++ b/docs/reference/dbFetch.html @@ -229,7 +229,7 @@

      See a finish retrieving the records you want.

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, - dbColumnInfo, dbGetInfo, + dbColumnInfo, dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, diff --git a/docs/reference/dbGetException.html b/docs/reference/dbGetException.html index 8b40eff79..6c58500c4 100644 --- a/docs/reference/dbGetException.html +++ b/docs/reference/dbGetException.html @@ -134,7 +134,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetInfo, dbGetQuery, + dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbGetQuery.html b/docs/reference/dbGetQuery.html index 29a40f00e..1ae6be030 100644 --- a/docs/reference/dbGetQuery.html +++ b/docs/reference/dbGetQuery.html @@ -186,7 +186,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbGetRowCount.html b/docs/reference/dbGetRowCount.html index 0a814a708..856dbabb0 100644 --- a/docs/reference/dbGetRowCount.html +++ b/docs/reference/dbGetRowCount.html @@ -154,7 +154,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowsAffected, + dbGetInfo, dbGetRowsAffected, dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, diff --git a/docs/reference/dbGetRowsAffected.html b/docs/reference/dbGetRowsAffected.html index 2e20f99c8..b107b7ea3 100644 --- a/docs/reference/dbGetRowsAffected.html +++ b/docs/reference/dbGetRowsAffected.html @@ -146,7 +146,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, diff --git a/docs/reference/dbGetStatement.html b/docs/reference/dbGetStatement.html index e2c507091..1064aad92 100644 --- a/docs/reference/dbGetStatement.html +++ b/docs/reference/dbGetStatement.html @@ -141,7 +141,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbHasCompleted, dbIsValid, dbQuoteIdentifier, diff --git a/docs/reference/dbHasCompleted.html b/docs/reference/dbHasCompleted.html index 6029b48d4..29e16ac05 100644 --- a/docs/reference/dbHasCompleted.html +++ b/docs/reference/dbHasCompleted.html @@ -158,7 +158,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, dbIsValid, dbQuoteIdentifier, diff --git a/docs/reference/dbIsValid.html b/docs/reference/dbIsValid.html index 025dd5c1e..e7d55313c 100644 --- a/docs/reference/dbIsValid.html +++ b/docs/reference/dbIsValid.html @@ -155,12 +155,12 @@

      See a

      Other DBIDriver generics: DBIDriver-class, dbConnect, dbDataType, - dbDriver, dbGetInfo, + dbDriver, dbGetInfo, dbListConnections

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbListFields, dbListResults, dbListTables, dbReadTable, dbRemoveTable, @@ -169,7 +169,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, dbHasCompleted, diff --git a/docs/reference/dbListConnections.html b/docs/reference/dbListConnections.html index 8b8bc7164..d3a78a9e5 100644 --- a/docs/reference/dbListConnections.html +++ b/docs/reference/dbListConnections.html @@ -103,9 +103,8 @@

      List currently open connections

      -

      Drivers that implement only a single connections MUST return a list -containing a single element. If no connection are open, methods MUST -return an empty list.

      +

      DEPRECATED, drivers are no longer required to implement this method. +Keep track of the connections you opened if you require a list.

      dbListConnections(drv, ...)
      @@ -131,7 +130,7 @@

      See a

      Other DBIDriver generics: DBIDriver-class, dbConnect, dbDataType, - dbDriver, dbGetInfo, + dbDriver, dbGetInfo, dbIsValid

      diff --git a/docs/reference/dbListFields.html b/docs/reference/dbListFields.html index b97c4ff0a..8073dfa7e 100644 --- a/docs/reference/dbListFields.html +++ b/docs/reference/dbListFields.html @@ -136,7 +136,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListResults, dbListTables, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbListResults.html b/docs/reference/dbListResults.html index 05c9c0610..e695a1a6c 100644 --- a/docs/reference/dbListResults.html +++ b/docs/reference/dbListResults.html @@ -134,7 +134,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListTables, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbListTables.html b/docs/reference/dbListTables.html index 1b2cdd563..7c0eb0952 100644 --- a/docs/reference/dbListTables.html +++ b/docs/reference/dbListTables.html @@ -158,7 +158,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbReadTable, dbRemoveTable, diff --git a/docs/reference/dbQuoteIdentifier.html b/docs/reference/dbQuoteIdentifier.html index 910190ffa..3ebba16ba 100644 --- a/docs/reference/dbQuoteIdentifier.html +++ b/docs/reference/dbQuoteIdentifier.html @@ -181,7 +181,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, dbHasCompleted, dbIsValid, diff --git a/docs/reference/dbQuoteLiteral.html b/docs/reference/dbQuoteLiteral.html index 4ee56666d..42b76a51e 100644 --- a/docs/reference/dbQuoteLiteral.html +++ b/docs/reference/dbQuoteLiteral.html @@ -139,7 +139,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, dbHasCompleted, dbIsValid, diff --git a/docs/reference/dbQuoteString.html b/docs/reference/dbQuoteString.html index 75f7a8d70..3e5c73855 100644 --- a/docs/reference/dbQuoteString.html +++ b/docs/reference/dbQuoteString.html @@ -176,7 +176,7 @@

      See a

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, - dbGetInfo, dbGetRowCount, + dbGetInfo, dbGetRowCount, dbGetRowsAffected, dbGetStatement, dbHasCompleted, dbIsValid, diff --git a/docs/reference/dbReadTable.html b/docs/reference/dbReadTable.html index 2922208ad..d3242db7f 100644 --- a/docs/reference/dbReadTable.html +++ b/docs/reference/dbReadTable.html @@ -200,7 +200,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbRemoveTable, diff --git a/docs/reference/dbRemoveTable.html b/docs/reference/dbRemoveTable.html index 872834409..c58d4a575 100644 --- a/docs/reference/dbRemoveTable.html +++ b/docs/reference/dbRemoveTable.html @@ -165,7 +165,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbSendQuery.html b/docs/reference/dbSendQuery.html index 57a0529f5..f193166ca 100644 --- a/docs/reference/dbSendQuery.html +++ b/docs/reference/dbSendQuery.html @@ -182,7 +182,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbSendStatement.html b/docs/reference/dbSendStatement.html index da67185ce..bbd4b3ebf 100644 --- a/docs/reference/dbSendStatement.html +++ b/docs/reference/dbSendStatement.html @@ -177,7 +177,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/dbWriteTable.html b/docs/reference/dbWriteTable.html index d6b5aed0c..85ec14dad 100644 --- a/docs/reference/dbWriteTable.html +++ b/docs/reference/dbWriteTable.html @@ -251,7 +251,7 @@

      See a

      Other DBIConnection generics: DBIConnection-class, dbDataType, dbDisconnect, dbExecute, dbExistsTable, - dbGetException, dbGetInfo, + dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, dbListResults, dbListTables, dbReadTable, diff --git a/docs/reference/hidden_aliases.html b/docs/reference/hidden_aliases.html index 40c1d79ff..e4f626964 100644 --- a/docs/reference/hidden_aliases.html +++ b/docs/reference/hidden_aliases.html @@ -144,7 +144,7 @@

      Internal page for hidden aliases

      dbFetch(res, n = -1, ...) # S4 method for DBIResult -dbGetInfo(dbObj, ...) +dbGetInfo(dbObj, ...) # S4 method for DBIConnection sqlData(con, value, row.names = NA, ...) @@ -154,7 +154,7 @@

      Internal page for hidden aliases

      keywords = .SQL92Keywords, unique = TRUE, allow.keywords = TRUE, ...) # S4 method for DBIObject,character -isSQLKeyword(dbObj, name, +isSQLKeyword(dbObj, name, keywords = .SQL92Keywords, case = c("lower", "upper", "any")[3], ...) # S4 method for DBIObject From c0590c2eecd6d055b3d6dd55b833dcd8f6751f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 18:55:19 +0100 Subject: [PATCH 08/44] use signature() for all methods --- R/DBConnection.R | 2 +- R/DBDriver.R | 4 ++-- R/DBResult.R | 6 +++--- R/data-types.R | 22 +++++++++++----------- R/data.R | 2 +- R/deprecated.R | 4 ++-- R/interpolate.R | 4 ++-- R/quote.R | 12 ++++++------ R/table.R | 4 ++-- R/transactions.R | 2 +- 10 files changed, 31 insertions(+), 31 deletions(-) diff --git a/R/DBConnection.R b/R/DBConnection.R index 892b3aa3c..1ca08fb18 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -394,7 +394,7 @@ setGeneric("dbReadTable", #' @rdname hidden_aliases #' @export -setMethod("dbReadTable", c("DBIConnection", "character"), +setMethod("dbReadTable", signature("DBIConnection", "character"), function(conn, name, ..., row.names = FALSE, check.names = TRUE) { sql_name <- dbQuoteIdentifier(conn, x = name, ...) if (length(sql_name) != 1L) { diff --git a/R/DBDriver.R b/R/DBDriver.R index 24c6f94e6..ff8c79186 100644 --- a/R/DBDriver.R +++ b/R/DBDriver.R @@ -68,7 +68,7 @@ setMethod("dbDriver", signature("character"), #' @rdname hidden_aliases #' @param object Object to display #' @export -setMethod("show", "DBIDriver", function(object) { +setMethod("show", signature("DBIDriver"), function(object) { tryCatch( # to protect drivers that fail to implement the required methods (e.g., # RPostgreSQL) @@ -251,6 +251,6 @@ setGeneric("dbDataType", #' @rdname hidden_aliases #' @export -setMethod("dbDataType", "DBIObject", function(dbObj, obj, ...) { +setMethod("dbDataType", signature("DBIObject"), function(dbObj, obj, ...) { dbiDataType(obj) }) diff --git a/R/DBResult.R b/R/DBResult.R index 1155b6bd5..27707970b 100644 --- a/R/DBResult.R +++ b/R/DBResult.R @@ -24,7 +24,7 @@ setClass("DBIResult", contains = c("DBIObject", "VIRTUAL")) #' @rdname hidden_aliases #' @param object Object to display #' @export -setMethod("show", "DBIResult", function(object) { +setMethod("show", signature("DBIResult"), function(object) { # to protect drivers that fail to implement the required methods (e.g., # RPostgreSQL) tryCatch( @@ -101,7 +101,7 @@ setGeneric("dbFetch", #' @rdname hidden_aliases #' @export -setMethod("dbFetch", "DBIResult", function(res, n = -1, ...) { +setMethod("dbFetch", signature("DBIResult"), function(res, n = -1, ...) { fetch(res, n = n, ...) }) @@ -303,7 +303,7 @@ setGeneric("dbGetRowCount", #' [dbGetRowsAffected()], and [dbHasCompleted()]. NULL #' @rdname hidden_aliases -setMethod("dbGetInfo", "DBIResult", function(dbObj, ...) { +setMethod("dbGetInfo", signature("DBIResult"), function(dbObj, ...) { list( statement = dbGetStatement(dbObj), row.count = dbGetRowCount(dbObj), diff --git a/R/data-types.R b/R/data-types.R index 3b5654ac6..c29317e2e 100644 --- a/R/data-types.R +++ b/R/data-types.R @@ -30,14 +30,14 @@ as_is_data_type <- function(x) { setOldClass("difftime") setOldClass("AsIs") -setMethod("dbiDataType", "data.frame", data_frame_data_type) -setMethod("dbiDataType", "integer", function(x) "INT") -setMethod("dbiDataType", "numeric", function(x) "DOUBLE") -setMethod("dbiDataType", "logical", function(x) "SMALLINT") -setMethod("dbiDataType", "Date", function(x) "DATE") -setMethod("dbiDataType", "difftime", function(x) "TIME") -setMethod("dbiDataType", "POSIXct", function(x) "TIMESTAMP") -setMethod("dbiDataType", "character", varchar_data_type) -setMethod("dbiDataType", "factor", varchar_data_type) -setMethod("dbiDataType", "list", list_data_type) -setMethod("dbiDataType", "AsIs", as_is_data_type) +setMethod("dbiDataType", signature("data.frame"), data_frame_data_type) +setMethod("dbiDataType", signature("integer"), function(x) "INT") +setMethod("dbiDataType", signature("numeric"), function(x) "DOUBLE") +setMethod("dbiDataType", signature("logical"), function(x) "SMALLINT") +setMethod("dbiDataType", signature("Date"), function(x) "DATE") +setMethod("dbiDataType", signature("difftime"), function(x) "TIME") +setMethod("dbiDataType", signature("POSIXct"), function(x) "TIMESTAMP") +setMethod("dbiDataType", signature("character"), varchar_data_type) +setMethod("dbiDataType", signature("factor"), varchar_data_type) +setMethod("dbiDataType", signature("list"), list_data_type) +setMethod("dbiDataType", signature("AsIs"), as_is_data_type) diff --git a/R/data.R b/R/data.R index 295e388f6..dd85d25c1 100644 --- a/R/data.R +++ b/R/data.R @@ -31,7 +31,7 @@ setGeneric("sqlData", #' @rdname hidden_aliases #' @export -setMethod("sqlData", "DBIConnection", function(con, value, row.names = NA, ...) { +setMethod("sqlData", signature("DBIConnection"), function(con, value, row.names = NA, ...) { value <- sqlRownamesToColumn(value, row.names) # Convert factors to strings diff --git a/R/deprecated.R b/R/deprecated.R index 216d6f349..60901da2b 100644 --- a/R/deprecated.R +++ b/R/deprecated.R @@ -144,13 +144,13 @@ setGeneric("SQLKeywords", ) #' @rdname hidden_aliases -setMethod("SQLKeywords", "DBIObject", +setMethod("SQLKeywords", signature("DBIObject"), definition = function(dbObj, ...) .SQL92Keywords, valueClass = "character" ) #' @rdname hidden_aliases -setMethod("SQLKeywords", "missing", +setMethod("SQLKeywords", signature("missing"), definition = function(dbObj, ...) .SQL92Keywords, valueClass = "character" ) diff --git a/R/interpolate.R b/R/interpolate.R index 44c0a976e..ed81aaed9 100644 --- a/R/interpolate.R +++ b/R/interpolate.R @@ -28,7 +28,7 @@ setGeneric("sqlInterpolate", #' @rdname hidden_aliases #' @export -setMethod("sqlInterpolate", "DBIConnection", function(conn, sql, ..., .dots = list()) { +setMethod("sqlInterpolate", signature("DBIConnection"), function(conn, sql, ..., .dots = list()) { pos <- sqlParseVariables(conn, sql) if (length(pos$start) == 0) { @@ -110,7 +110,7 @@ setGeneric("sqlParseVariables", #' @rdname hidden_aliases #' @export -setMethod("sqlParseVariables", "DBIConnection", function(conn, sql, ...) { +setMethod("sqlParseVariables", signature("DBIConnection"), function(conn, sql, ...) { sqlParseVariablesImpl( sql, list( diff --git a/R/quote.R b/R/quote.R index 6c2f15a8f..db8f88aaf 100644 --- a/R/quote.R +++ b/R/quote.R @@ -121,17 +121,17 @@ quote_identifier <- #' @rdname hidden_aliases #' @export -setMethod("dbQuoteIdentifier", c("DBIConnection"), quote_identifier) +setMethod("dbQuoteIdentifier", signature("DBIConnection"), quote_identifier) # Need to keep other method declarations around for now, because clients might # use getMethod(), see e.g. https://github.com/r-dbi/odbc/pull/149 #' @rdname hidden_aliases #' @export -setMethod("dbQuoteIdentifier", c("DBIConnection", "character"), quote_identifier) +setMethod("dbQuoteIdentifier", signature("DBIConnection", "character"), quote_identifier) #' @rdname hidden_aliases #' @export -setMethod("dbQuoteIdentifier", c("DBIConnection", "SQL"), quote_identifier) +setMethod("dbQuoteIdentifier", signature("DBIConnection", "SQL"), quote_identifier) #' Quote literal strings #' @@ -194,15 +194,15 @@ quote_string <- # use getMethod(), see e.g. https://github.com/r-dbi/odbc/pull/149 #' @rdname hidden_aliases #' @export -setMethod("dbQuoteString", c("DBIConnection"), quote_string) +setMethod("dbQuoteString", signature("DBIConnection"), quote_string) #' @rdname hidden_aliases #' @export -setMethod("dbQuoteString", c("DBIConnection", "character"), quote_string) +setMethod("dbQuoteString", signature("DBIConnection", "character"), quote_string) #' @rdname hidden_aliases #' @export -setMethod("dbQuoteString", c("DBIConnection", "SQL"), quote_string) +setMethod("dbQuoteString", signature("DBIConnection", "SQL"), quote_string) #' Quote literal values #' diff --git a/R/table.R b/R/table.R index a7a58cae7..2ea795599 100644 --- a/R/table.R +++ b/R/table.R @@ -14,10 +14,10 @@ Table <- function(...) { #' @rdname hidden_aliases #' @param object Table object to print #' @export -setMethod("show", "Table", function(object) { +setMethod("show", signature("Table"), function(object) { cat(" ", paste0(object@name, collapse = "."), "\n", sep = "") }) #' @rdname hidden_aliases #' @export -setMethod("dbQuoteIdentifier", c("DBIConnection", "Table"), quote_identifier) +setMethod("dbQuoteIdentifier", signature("DBIConnection", "Table"), quote_identifier) diff --git a/R/transactions.R b/R/transactions.R index ab338a1ff..e73b4dae3 100644 --- a/R/transactions.R +++ b/R/transactions.R @@ -145,7 +145,7 @@ setGeneric("dbWithTransaction", #' @rdname hidden_aliases #' @export -setMethod("dbWithTransaction", "DBIConnection", function(conn, code) { +setMethod("dbWithTransaction", signature("DBIConnection"), function(conn, code) { ## needs to be a closure, because it accesses conn rollback_because <- function(e) { call <- dbRollback(conn) From 9a9eb8d573ec97e618bd4578db7c925bab1eb730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 18:44:14 +0100 Subject: [PATCH 09/44] new dbUnquoteIdentifier() --- NAMESPACE | 2 + R/quote.R | 77 ++++++++++++++++++++++++++++++++++++-- man/DBIResult-class.Rd | 4 +- man/dbBind.Rd | 4 +- man/dbClearResult.Rd | 4 +- man/dbColumnInfo.Rd | 4 +- man/dbFetch.Rd | 4 +- man/dbGetInfo.Rd | 4 +- man/dbGetRowCount.Rd | 4 +- man/dbGetRowsAffected.Rd | 4 +- man/dbGetStatement.Rd | 4 +- man/dbHasCompleted.Rd | 4 +- man/dbIsValid.Rd | 4 +- man/dbQuoteIdentifier.Rd | 12 ++++-- man/dbQuoteLiteral.Rd | 3 +- man/dbQuoteString.Rd | 3 +- man/dbUnquoteIdentifier.Rd | 56 +++++++++++++++++++++++++++ man/hidden_aliases.Rd | 3 ++ 18 files changed, 180 insertions(+), 20 deletions(-) create mode 100644 man/dbUnquoteIdentifier.Rd diff --git a/NAMESPACE b/NAMESPACE index d048efa6c..380b4599a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -41,6 +41,7 @@ export(dbSendQuery) export(dbSendStatement) export(dbSetDataMappings) export(dbUnloadDriver) +export(dbUnquoteIdentifier) export(dbWithTransaction) export(dbWriteTable) export(fetch) @@ -74,6 +75,7 @@ exportMethods(dbQuoteLiteral) exportMethods(dbQuoteString) exportMethods(dbReadTable) exportMethods(dbSendStatement) +exportMethods(dbUnquoteIdentifier) exportMethods(dbWithTransaction) exportMethods(show) exportMethods(sqlAppendTable) diff --git a/R/quote.R b/R/quote.R index db8f88aaf..0e71b4e48 100644 --- a/R/quote.R +++ b/R/quote.R @@ -65,12 +65,13 @@ setMethod("show", "SQL", function(object) { #' Quote identifiers #' #' Call this method to generate a string that is suitable for -#' use in a query as a column name, to make sure that you -#' generate valid SQL and avoid SQL injection. +#' use in a query as a column or table name, to make sure that you +#' generate valid SQL and avoid SQL injection. The inverse operation is +#' [dbUnquoteIdentifier()]. #' #' @param conn A subclass of [DBIConnection-class], representing #' an active connection to an DBMS. -#' @param x A character vector to quote as identifier. +#' @param x A character vector, [SQL] or [Table] object to quote as identifier. #' @param ... Other arguments passed on to methods. #' #' @template methods @@ -133,6 +134,76 @@ setMethod("dbQuoteIdentifier", signature("DBIConnection", "character"), quote_id #' @export setMethod("dbQuoteIdentifier", signature("DBIConnection", "SQL"), quote_identifier) +#' Unquote identifiers +#' +#' Call this method to convert a [SQL] object created by [dbQuoteIdentifier()] +#' back to a list of [Table] objects. +#' +#' @param conn A subclass of [DBIConnection-class], representing +#' an active connection to an DBMS. +#' @param x An [SQL] or [Table] object or character vector, or a list of such +#' objects, to unquote. +#' @param ... Other arguments passed on to methods. +#' +#' @template methods +#' @templateVar method_name dbUnquoteIdentifier +#' +#' @inherit DBItest::spec_sql_unquote_identifier return +#' @inheritSection DBItest::spec_sql_unquote_identifier Specification +#' +#' @family DBIResult generics +#' @export +#' @examples +#' # Unquoting allows to understand the structure of a possibly complex quoted +#' # identifier +#' +#' dbUnquoteIdentifier( +#' ANSI(), +#' SQL(c("Schema"."Table", "UnqualifiedTable")) +#' ) +#' +#' # Character vectors are wrapped in a list +#' dbQuoteIdentifier( +#' ANSI(), +#' c(schema = "Schema", table = "Table") +#' ) +#' +#' # Lists of character vectors are returned unchanged +#' dbQuoteIdentifier( +#' ANSI(), +#' list(c(schema = "Schema", table = "Table"), "UnqualifiedTable") +#' ) +setGeneric("dbUnquoteIdentifier", + def = function(conn, x, ...) standardGeneric("dbUnquoteIdentifier") +) + +#' @rdname hidden_aliases +#' @export +setMethod("dbUnquoteIdentifier", signature("DBIConnection"), function(conn, x, ...) { + if (is.list(x)) { + return(vapply(x, dbUnquoteIdentifier, conn = conn, list(1))) + } + if (is(x, "SQL")) { + . <- strsplit(as.character(x), '^"|"$|"[.]"') + . <- lapply(., `[`, -1L) + split <- . + tables <- lapply(split, Table) + quoted <- lapply(tables, dbQuoteIdentifier, conn = conn) + bad <- quoted != x + if (any(bad)) { + stop("Can't unquote ", x[bad][[1L]], call. = FALSE) + } + return(tables) + } + if (is(x, "Table")) { + return(list(x)) + } + if (is.character(x)) { + return(list(do.call(Table, as.list(x)))) + } + stop("x must be character, SQL or Table, or a list of such objects", call. = FALSE) +}) + #' Quote literal strings #' #' Call this method to generate a string that is suitable for diff --git a/man/DBIResult-class.Rd b/man/DBIResult-class.Rd index a5668743d..9b2cd59e0 100644 --- a/man/DBIResult-class.Rd +++ b/man/DBIResult-class.Rd @@ -33,7 +33,9 @@ Other DBIResult generics: \code{\link{dbBind}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBI classes} \concept{DBIResult generics} diff --git a/man/dbBind.Rd b/man/dbBind.Rd index 0334f81f0..ac29c5fb2 100644 --- a/man/dbBind.Rd +++ b/man/dbBind.Rd @@ -186,6 +186,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbClearResult.Rd b/man/dbClearResult.Rd index 3672b9acb..0f89bd606 100644 --- a/man/dbClearResult.Rd +++ b/man/dbClearResult.Rd @@ -53,6 +53,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbColumnInfo.Rd b/man/dbColumnInfo.Rd index 0f832834a..becabb4e8 100644 --- a/man/dbColumnInfo.Rd +++ b/man/dbColumnInfo.Rd @@ -43,6 +43,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbFetch.Rd b/man/dbFetch.Rd index a22511de2..d84064194 100644 --- a/man/dbFetch.Rd +++ b/man/dbFetch.Rd @@ -152,6 +152,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbGetInfo.Rd b/man/dbGetInfo.Rd index fa5711919..c01a9e5e5 100644 --- a/man/dbGetInfo.Rd +++ b/man/dbGetInfo.Rd @@ -69,7 +69,9 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIConnection generics} \concept{DBIDriver generics} diff --git a/man/dbGetRowCount.Rd b/man/dbGetRowCount.Rd index f5551fb24..daeafc480 100644 --- a/man/dbGetRowCount.Rd +++ b/man/dbGetRowCount.Rd @@ -61,6 +61,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbGetRowsAffected.Rd b/man/dbGetRowsAffected.Rd index d089fcb58..7466cf38f 100644 --- a/man/dbGetRowsAffected.Rd +++ b/man/dbGetRowsAffected.Rd @@ -48,6 +48,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbGetStatement.Rd b/man/dbGetStatement.Rd index 38d1feef2..3a3d9bba7 100644 --- a/man/dbGetStatement.Rd +++ b/man/dbGetStatement.Rd @@ -42,6 +42,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetRowsAffected}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbHasCompleted.Rd b/man/dbHasCompleted.Rd index bc34e8fa2..bb63c2ec2 100644 --- a/man/dbHasCompleted.Rd +++ b/man/dbHasCompleted.Rd @@ -66,6 +66,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetRowsAffected}}, \code{\link{dbGetStatement}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbIsValid.Rd b/man/dbIsValid.Rd index 3ca6a893c..5b56b529b 100644 --- a/man/dbIsValid.Rd +++ b/man/dbIsValid.Rd @@ -76,7 +76,9 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIConnection generics} \concept{DBIDriver generics} diff --git a/man/dbQuoteIdentifier.Rd b/man/dbQuoteIdentifier.Rd index 3458f070d..5507dac3a 100644 --- a/man/dbQuoteIdentifier.Rd +++ b/man/dbQuoteIdentifier.Rd @@ -10,7 +10,7 @@ dbQuoteIdentifier(conn, x, ...) \item{conn}{A subclass of \linkS4class{DBIConnection}, representing an active connection to an DBMS.} -\item{x}{A character vector to quote as identifier.} +\item{x}{A character vector, \link{SQL} or \link{Table} object to quote as identifier.} \item{...}{Other arguments passed on to methods.} } @@ -18,6 +18,7 @@ an active connection to an DBMS.} \code{dbQuoteIdentifier()} returns an object that can be coerced to \link{character}, of the same length as the input. For an empty character vector this function returns a length-0 object. +The names of the input argument are preserved in the output. An error is raised if the input contains \code{NA}, but not for an empty string. @@ -30,8 +31,9 @@ to achieve this behavior, but this is not required.) } \description{ Call this method to generate a string that is suitable for -use in a query as a column name, to make sure that you -generate valid SQL and avoid SQL injection. +use in a query as a column or table name, to make sure that you +generate valid SQL and avoid SQL injection. The inverse operation is +\code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbQuoteIdentifier")} } @@ -83,6 +85,8 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetRowsAffected}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, - \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbQuoteLiteral.Rd b/man/dbQuoteLiteral.Rd index e9d62fd71..e1ae829c1 100644 --- a/man/dbQuoteLiteral.Rd +++ b/man/dbQuoteLiteral.Rd @@ -52,6 +52,7 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteString}} + \code{\link{dbQuoteString}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbQuoteString.Rd b/man/dbQuoteString.Rd index 5a63eb56c..f6dfd5267 100644 --- a/man/dbQuoteString.Rd +++ b/man/dbQuoteString.Rd @@ -84,6 +84,7 @@ Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbGetStatement}}, \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, \code{\link{dbQuoteIdentifier}}, - \code{\link{dbQuoteLiteral}} + \code{\link{dbQuoteLiteral}}, + \code{\link{dbUnquoteIdentifier}} } \concept{DBIResult generics} diff --git a/man/dbUnquoteIdentifier.Rd b/man/dbUnquoteIdentifier.Rd new file mode 100644 index 000000000..8f4d83d8a --- /dev/null +++ b/man/dbUnquoteIdentifier.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/quote.R +\name{dbUnquoteIdentifier} +\alias{dbUnquoteIdentifier} +\title{Unquote identifiers} +\usage{ +dbUnquoteIdentifier(conn, x, ...) +} +\arguments{ +\item{conn}{A subclass of \linkS4class{DBIConnection}, representing +an active connection to an DBMS.} + +\item{x}{An \link{SQL} or \link{Table} object or character vector, or a list of such +objects, to unquote.} + +\item{...}{Other arguments passed on to methods.} +} +\description{ +Call this method to convert a \link{SQL} object created by \code{\link[=dbQuoteIdentifier]{dbQuoteIdentifier()}} +back to a list of \link{Table} objects. + +\Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbUnquoteIdentifier")} +} +\examples{ +# Unquoting allows to understand the structure of a possibly complex quoted +# identifier + +dbUnquoteIdentifier( + ANSI(), + SQL(c("Schema"."Table", "UnqualifiedTable")) +) + +# Character vectors are wrapped in a list +dbQuoteIdentifier( + ANSI(), + c(schema = "Schema", table = "Table") +) + +# Lists of character vectors are returned unchanged +dbQuoteIdentifier( + ANSI(), + list(c(schema = "Schema", table = "Table"), "UnqualifiedTable") +) +} +\seealso{ +Other DBIResult generics: \code{\link{DBIResult-class}}, + \code{\link{dbBind}}, \code{\link{dbClearResult}}, + \code{\link{dbColumnInfo}}, \code{\link{dbFetch}}, + \code{\link{dbGetInfo}}, \code{\link{dbGetRowCount}}, + \code{\link{dbGetRowsAffected}}, + \code{\link{dbGetStatement}}, + \code{\link{dbHasCompleted}}, \code{\link{dbIsValid}}, + \code{\link{dbQuoteIdentifier}}, + \code{\link{dbQuoteLiteral}}, \code{\link{dbQuoteString}} +} +\concept{DBIResult generics} diff --git a/man/hidden_aliases.Rd b/man/hidden_aliases.Rd index 269fac33a..0a5215ef6 100644 --- a/man/hidden_aliases.Rd +++ b/man/hidden_aliases.Rd @@ -29,6 +29,7 @@ \alias{dbQuoteIdentifier,DBIConnection,ANY-method} \alias{dbQuoteIdentifier,DBIConnection,character-method} \alias{dbQuoteIdentifier,DBIConnection,SQL-method} +\alias{dbUnquoteIdentifier,DBIConnection-method} \alias{dbQuoteString,DBIConnection,ANY-method} \alias{dbQuoteString,DBIConnection,character-method} \alias{dbQuoteString,DBIConnection,SQL-method} @@ -91,6 +92,8 @@ \S4method{dbQuoteIdentifier}{DBIConnection,SQL}(conn, x, ...) +\S4method{dbUnquoteIdentifier}{DBIConnection}(conn, x, ...) + \S4method{dbQuoteString}{DBIConnection,ANY}(conn, x, ...) \S4method{dbQuoteString}{DBIConnection,character}(conn, x, ...) From 984d5495f2bee05d1508dca3636bb69bd8cfe01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 19:08:13 +0100 Subject: [PATCH 10/44] declare dbListObjects() --- NAMESPACE | 1 + R/DBConnection.R | 30 +++++++++++++++++++++++++ man/DBIConnection-class.Rd | 9 ++++---- man/dbDataType.Rd | 9 ++++---- man/dbDisconnect.Rd | 9 ++++---- man/dbExecute.Rd | 9 ++++---- man/dbExistsTable.Rd | 8 +++---- man/dbGetException.Rd | 8 +++---- man/dbGetInfo.Rd | 8 +++---- man/dbGetQuery.Rd | 8 +++---- man/dbIsValid.Rd | 8 +++---- man/dbListFields.Rd | 8 +++---- man/dbListObjects.Rd | 45 ++++++++++++++++++++++++++++++++++++++ man/dbListResults.Rd | 8 +++---- man/dbListTables.Rd | 8 +++---- man/dbReadTable.Rd | 8 +++---- man/dbRemoveTable.Rd | 8 +++---- man/dbSendQuery.Rd | 6 ++--- man/dbSendStatement.Rd | 8 +++---- man/dbWriteTable.Rd | 8 +++---- 20 files changed, 147 insertions(+), 67 deletions(-) create mode 100644 man/dbListObjects.Rd diff --git a/NAMESPACE b/NAMESPACE index 380b4599a..778429b5e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,6 +29,7 @@ export(dbHasCompleted) export(dbIsValid) export(dbListConnections) export(dbListFields) +export(dbListObjects) export(dbListResults) export(dbListTables) export(dbQuoteIdentifier) diff --git a/R/DBConnection.R b/R/DBConnection.R index 1ca08fb18..3493cdc7c 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -362,6 +362,36 @@ setGeneric("dbListTables", valueClass = "character" ) +#' List remote objects +#' +#' Returns the names of remote tables accessible through this connection +#' (possibly via a prefix) as a data frame. +#' This should, where possible, include temporary objects. +#' +#' @template methods +#' @templateVar method_name dbListObjects +#' +#' @inherit DBItest::spec_sql_list_objects return +#' @inheritSection DBItest::spec_sql_list_objects Additional arguments +#' +#' @inheritParams dbGetQuery +#' @param prefix An optional prefix, passed to [dbUnquoteIdentifier()]. +#' If given the method will return all objects accessible through this prefix. +#' @family DBIConnection generics +#' @export +#' @examples +#' con <- dbConnect(RSQLite::SQLite(), ":memory:") +#' +#' dbListObjects(con) +#' dbWriteTable(con, "mtcars", mtcars) +#' dbListObjects(con) +#' +#' dbDisconnect(con) +setGeneric("dbListObjects", + def = function(conn, prefix = NULL, ...) standardGeneric("dbListObjects"), + valueClass = "data.frame" +) + #' Copy data frames from database tables #' #' Reads a database table to a data frame, optionally converting diff --git a/man/DBIConnection-class.Rd b/man/DBIConnection-class.Rd index 2c38aacad..f38b451a9 100644 --- a/man/DBIConnection-class.Rd +++ b/man/DBIConnection-class.Rd @@ -36,10 +36,11 @@ Other DBIConnection generics: \code{\link{dbDataType}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, + \code{\link{dbWriteTable}} } \concept{DBI classes} \concept{DBIConnection generics} diff --git a/man/dbDataType.Rd b/man/dbDataType.Rd index 66d6f838b..dc38c1b77 100644 --- a/man/dbDataType.Rd +++ b/man/dbDataType.Rd @@ -123,10 +123,11 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, + \code{\link{dbWriteTable}} } \concept{DBIConnection generics} \concept{DBIDriver generics} diff --git a/man/dbDisconnect.Rd b/man/dbDisconnect.Rd index 754ad1817..c5419e340 100644 --- a/man/dbDisconnect.Rd +++ b/man/dbDisconnect.Rd @@ -43,9 +43,10 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, + \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbExecute.Rd b/man/dbExecute.Rd index dae2b025c..aecb17ca5 100644 --- a/man/dbExecute.Rd +++ b/man/dbExecute.Rd @@ -59,9 +59,10 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, + \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbExistsTable.Rd b/man/dbExistsTable.Rd index db6d5a62a..ece93903f 100644 --- a/man/dbExistsTable.Rd +++ b/man/dbExistsTable.Rd @@ -71,9 +71,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, \code{\link{dbListFields}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbGetException.Rd b/man/dbGetException.Rd index cae662b73..bbc322b7b 100644 --- a/man/dbGetException.Rd +++ b/man/dbGetException.Rd @@ -27,9 +27,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, \code{\link{dbListFields}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbGetInfo.Rd b/man/dbGetInfo.Rd index c01a9e5e5..aa7eafb83 100644 --- a/man/dbGetInfo.Rd +++ b/man/dbGetInfo.Rd @@ -56,10 +56,10 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, \code{\link{dbListFields}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbBind}}, \code{\link{dbClearResult}}, diff --git a/man/dbGetQuery.Rd b/man/dbGetQuery.Rd index 626d97e3d..e5589491e 100644 --- a/man/dbGetQuery.Rd +++ b/man/dbGetQuery.Rd @@ -84,9 +84,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbIsValid}}, \code{\link{dbListFields}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbIsValid.Rd b/man/dbIsValid.Rd index 5b56b529b..58378f7ba 100644 --- a/man/dbIsValid.Rd +++ b/man/dbIsValid.Rd @@ -63,10 +63,10 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbListFields}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} Other DBIResult generics: \code{\link{DBIResult-class}}, \code{\link{dbBind}}, \code{\link{dbClearResult}}, diff --git a/man/dbListFields.Rd b/man/dbListFields.Rd index aeb92912d..1b8dcd5c5 100644 --- a/man/dbListFields.Rd +++ b/man/dbListFields.Rd @@ -36,9 +36,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListResults}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListObjects}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbListObjects.Rd b/man/dbListObjects.Rd new file mode 100644 index 000000000..ddaa79f52 --- /dev/null +++ b/man/dbListObjects.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/DBConnection.R +\name{dbListObjects} +\alias{dbListObjects} +\title{List remote objects} +\usage{ +dbListObjects(conn, prefix = NULL, ...) +} +\arguments{ +\item{conn}{A \linkS4class{DBIConnection} object, as returned by +\code{\link[=dbConnect]{dbConnect()}}.} + +\item{prefix}{An optional prefix, passed to \code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. +If given the method will return all objects accessible through this prefix.} + +\item{...}{Other parameters passed on to methods.} +} +\description{ +Returns the names of remote tables accessible through this connection +(possibly via a prefix) as a data frame. +This should, where possible, include temporary objects. + +\Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbListObjects")} +} +\examples{ +con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbListObjects(con) +dbWriteTable(con, "mtcars", mtcars) +dbListObjects(con) + +dbDisconnect(con) +} +\seealso{ +Other DBIConnection generics: \code{\link{DBIConnection-class}}, + \code{\link{dbDataType}}, \code{\link{dbDisconnect}}, + \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, + \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, + \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, + \code{\link{dbListFields}}, \code{\link{dbListResults}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} +} +\concept{DBIConnection generics} diff --git a/man/dbListResults.Rd b/man/dbListResults.Rd index 9d66578e4..786120076 100644 --- a/man/dbListResults.Rd +++ b/man/dbListResults.Rd @@ -27,9 +27,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListTables}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListTables}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbListTables.Rd b/man/dbListTables.Rd index e421ca13c..7f6f2b468 100644 --- a/man/dbListTables.Rd +++ b/man/dbListTables.Rd @@ -60,9 +60,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbReadTable}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbReadTable.Rd b/man/dbReadTable.Rd index 0d461bb6e..856c631bf 100644 --- a/man/dbReadTable.Rd +++ b/man/dbReadTable.Rd @@ -105,9 +105,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbRemoveTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbRemoveTable.Rd b/man/dbRemoveTable.Rd index b629de015..6ce52cd6b 100644 --- a/man/dbRemoveTable.Rd +++ b/man/dbRemoveTable.Rd @@ -68,9 +68,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}}, - \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbSendQuery}}, + \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbSendQuery.Rd b/man/dbSendQuery.Rd index 64b7004b9..026c30f2a 100644 --- a/man/dbSendQuery.Rd +++ b/man/dbSendQuery.Rd @@ -83,9 +83,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, \code{\link{dbSendStatement}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbSendStatement.Rd b/man/dbSendStatement.Rd index bc7f1e4b4..c2a61647e 100644 --- a/man/dbSendStatement.Rd +++ b/man/dbSendStatement.Rd @@ -79,9 +79,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbWriteTable}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbWriteTable}} } \concept{DBIConnection generics} diff --git a/man/dbWriteTable.Rd b/man/dbWriteTable.Rd index 052abce86..47b35ba4b 100644 --- a/man/dbWriteTable.Rd +++ b/man/dbWriteTable.Rd @@ -170,9 +170,9 @@ Other DBIConnection generics: \code{\link{DBIConnection-class}}, \code{\link{dbExecute}}, \code{\link{dbExistsTable}}, \code{\link{dbGetException}}, \code{\link{dbGetInfo}}, \code{\link{dbGetQuery}}, \code{\link{dbIsValid}}, - \code{\link{dbListFields}}, \code{\link{dbListResults}}, - \code{\link{dbListTables}}, \code{\link{dbReadTable}}, - \code{\link{dbRemoveTable}}, \code{\link{dbSendQuery}}, - \code{\link{dbSendStatement}} + \code{\link{dbListFields}}, \code{\link{dbListObjects}}, + \code{\link{dbListResults}}, \code{\link{dbListTables}}, + \code{\link{dbReadTable}}, \code{\link{dbRemoveTable}}, + \code{\link{dbSendQuery}}, \code{\link{dbSendStatement}} } \concept{DBIConnection generics} From 1f7101ae910938fdf4089e0e4637a6c387c90d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 19:18:43 +0100 Subject: [PATCH 11/44] dbQuoteIdentifier() works for lists --- R/quote.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/quote.R b/R/quote.R index 0e71b4e48..4811229b0 100644 --- a/R/quote.R +++ b/R/quote.R @@ -101,6 +101,9 @@ setGeneric("dbQuoteIdentifier", quote_identifier <- function(conn, x, ...) { + if (is.list(x)) { + return(vapply(x, function(xx) list(dbQuoteIdentifier(conn, xx)), list(1))) + } if (is(x, "SQL")) return(x) if (is(x, "Table")) { return(SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = "."))) From 18c8e85501d3bf4b853d91f3bedb6eb737a4c46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 20:40:53 +0100 Subject: [PATCH 12/44] implement toString.Table --- NAMESPACE | 1 + R/table.R | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index 778429b5e..a83cfb5ca 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method(toString,Table) export(.SQL92Keywords) export(ANSI) export(SQL) diff --git a/R/table.R b/R/table.R index 2ea795599..3bcb8fd2a 100644 --- a/R/table.R +++ b/R/table.R @@ -15,9 +15,14 @@ Table <- function(...) { #' @param object Table object to print #' @export setMethod("show", signature("Table"), function(object) { - cat("
      ", paste0(object@name, collapse = "."), "\n", sep = "") + cat(toString(object), "\n", sep = "") }) +#' @export +toString.Table <- function(x, ...) { + paste0("
      ", paste(x@name, collapse = ".")) +} + #' @rdname hidden_aliases #' @export setMethod("dbQuoteIdentifier", signature("DBIConnection", "Table"), quote_identifier) From 679bc6a2eee49d79836cbb40153be685235a138a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 20:45:53 +0100 Subject: [PATCH 13/44] provide subsetting operators for class SQL --- NAMESPACE | 2 ++ R/quote.R | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index a83cfb5ca..a72dbc017 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,7 @@ # Generated by roxygen2: do not edit by hand +S3method("[",SQL) +S3method("[[",SQL) S3method(toString,Table) export(.SQL92Keywords) export(ANSI) diff --git a/R/quote.R b/R/quote.R index 4811229b0..44a086f3b 100644 --- a/R/quote.R +++ b/R/quote.R @@ -61,6 +61,11 @@ setMethod("show", "SQL", function(object) { cat(paste0(" ", object@.Data, collapse = "\n"), "\n", sep = "") }) +#' @export +`[.SQL` <- function(x, ...) SQL(NextMethod()) + +#' @export +`[[.SQL` <- function(x, ...) SQL(NextMethod()) #' Quote identifiers #' From ad9fd0fa6ae2a52f3bad408a34801209f10aea5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 28 Jan 2018 20:46:31 +0100 Subject: [PATCH 14/44] document slots of Table --- R/table.R | 3 +++ man/Table.Rd | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/R/table.R b/R/table.R index 3bcb8fd2a..bdf515d28 100644 --- a/R/table.R +++ b/R/table.R @@ -3,6 +3,9 @@ setClass("Table", slots = list(name = "character")) #' Refer to a table nested in a hierarchy (e.g. within a schema) #' +#' Objects of class `Table` have a single slot `name`, which is a named +#' character vector. +#' #' @param ... Components of the hierarchy, e.g. `schema`, `table`, #' or `cluster`, `catalog`, `schema`, `table`. #' For more on these concepts, see diff --git a/man/Table.Rd b/man/Table.Rd index 5c35f185a..ddf8425ed 100644 --- a/man/Table.Rd +++ b/man/Table.Rd @@ -15,5 +15,6 @@ For more on these concepts, see \url{http://stackoverflow.com/questions/7022755/}} } \description{ -Refer to a table nested in a hierarchy (e.g. within a schema) +Objects of class \code{Table} have a single slot \code{name}, which is a named +character vector. } From 2fa68115fb4f8d26dab40ce11a86cc82cab86525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 29 Jan 2018 08:45:18 +0100 Subject: [PATCH 15/44] export Table() --- NAMESPACE | 1 + R/table.R | 1 + 2 files changed, 2 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index a72dbc017..039937c5f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,6 +7,7 @@ export(.SQL92Keywords) export(ANSI) export(SQL) export(SQLKeywords) +export(Table) export(dbBegin) export(dbBind) export(dbBreak) diff --git a/R/table.R b/R/table.R index bdf515d28..90fbe2ed4 100644 --- a/R/table.R +++ b/R/table.R @@ -10,6 +10,7 @@ setClass("Table", slots = list(name = "character")) #' or `cluster`, `catalog`, `schema`, `table`. #' For more on these concepts, see #' \url{http://stackoverflow.com/questions/7022755/} +#' @export Table <- function(...) { new("Table", name = c(...)) } From 4e8e85591e779ca062d45eaba2a8ff09943dac9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 29 Jan 2018 08:26:42 +0000 Subject: [PATCH 16/44] Deploy from Travis build 961 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/334602418 Commit: 13d4c5595c1f9fca587c08ee9857ef240087b476 --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index dd12b611e..2dda0d73e 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-01-28

      +

      2018-01-29

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 29459959d..ec3af85b1 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-01-28

      +

      2018-01-29

      From dd7ce92fd464b7e441df97898c6938919e78541f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 29 Jan 2018 14:35:24 +0100 Subject: [PATCH 17/44] require all arguments to be named --- R/table.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/table.R b/R/table.R index 90fbe2ed4..80c82ba76 100644 --- a/R/table.R +++ b/R/table.R @@ -12,7 +12,11 @@ setClass("Table", slots = list(name = "character")) #' \url{http://stackoverflow.com/questions/7022755/} #' @export Table <- function(...) { - new("Table", name = c(...)) + components <- c(...) + if (is.null(names(components)) || any(names(components) == "")) { + stop("All arguments to Table() must be named.", call. = FALSE) + } + new("Table", name = components) } #' @rdname hidden_aliases From 9105b5ca5d44a15a2c6151009c2fb37f67646b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 30 Jan 2018 08:15:53 +0100 Subject: [PATCH 18/44] fix docs --- R/DBConnection.R | 18 +++++++++++++----- R/quote.R | 10 +++++----- man/dbListObjects.Rd | 15 +++++++++++---- man/dbListTables.Rd | 3 ++- man/dbQuoteIdentifier.Rd | 4 ++-- man/dbQuoteLiteral.Rd | 2 +- man/dbQuoteString.Rd | 2 +- man/dbUnquoteIdentifier.Rd | 2 +- 8 files changed, 36 insertions(+), 20 deletions(-) diff --git a/R/DBConnection.R b/R/DBConnection.R index 3493cdc7c..c447c87f7 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -338,7 +338,8 @@ setMethod("dbListFields", signature("DBIConnection", "character"), #' #' Returns the unquoted names of remote tables accessible through this #' connection. -#' This should, where possible, include temporary tables, and views. +#' This should include views and temporary objects, but not all database backends +#' (in particular \pkg{RMariaDB} and \pkg{RMySQL}) support this. #' #' @template methods #' @templateVar method_name dbListTables @@ -364,9 +365,15 @@ setGeneric("dbListTables", #' List remote objects #' -#' Returns the names of remote tables accessible through this connection -#' (possibly via a prefix) as a data frame. -#' This should, where possible, include temporary objects. +#' Returns the names of remote objects accessible through this connection +#' as a data frame. +#' This should include temporary objects, but not all database backends +#' (in particular \pkg{RMariaDB} and \pkg{RMySQL}) support this. +#' Compared to [dbListTables()], this method also enumerates tables and views +#' in schemas, and returns fully qualified identifiers to access these objects. +#' This allows exploration of all database objects available to the current +#' user, including those that can only be accessed by giving the full +#' namespace. #' #' @template methods #' @templateVar method_name dbListObjects @@ -375,7 +382,8 @@ setGeneric("dbListTables", #' @inheritSection DBItest::spec_sql_list_objects Additional arguments #' #' @inheritParams dbGetQuery -#' @param prefix An optional prefix, passed to [dbUnquoteIdentifier()]. +#' @param prefix A fully qualified path in the database's namespace, or `NULL`. +#' will be passed to [dbUnquoteIdentifier()]. #' If given the method will return all objects accessible through this prefix. #' @family DBIConnection generics #' @export diff --git a/R/quote.R b/R/quote.R index 44a086f3b..68b0ff299 100644 --- a/R/quote.R +++ b/R/quote.R @@ -71,8 +71,8 @@ setMethod("show", "SQL", function(object) { #' #' Call this method to generate a string that is suitable for #' use in a query as a column or table name, to make sure that you -#' generate valid SQL and avoid SQL injection. The inverse operation is -#' [dbUnquoteIdentifier()]. +#' generate valid SQL and protect against SQL injection attacks. The inverse +#' operation is [dbUnquoteIdentifier()]. #' #' @param conn A subclass of [DBIConnection-class], representing #' an active connection to an DBMS. @@ -167,7 +167,7 @@ setMethod("dbQuoteIdentifier", signature("DBIConnection", "SQL"), quote_identifi #' #' dbUnquoteIdentifier( #' ANSI(), -#' SQL(c("Schema"."Table", "UnqualifiedTable")) +#' SQL(c('"Schema"."Table"', "UnqualifiedTable")) #' ) #' #' # Character vectors are wrapped in a list @@ -216,7 +216,7 @@ setMethod("dbUnquoteIdentifier", signature("DBIConnection"), function(conn, x, . #' #' Call this method to generate a string that is suitable for #' use in a query as a string literal, to make sure that you -#' generate valid SQL and avoid SQL injection. +#' generate valid SQL and protect against SQL injection attacks. #' #' @param conn A subclass of [DBIConnection-class], representing #' an active connection to an DBMS. @@ -288,7 +288,7 @@ setMethod("dbQuoteString", signature("DBIConnection", "SQL"), quote_string) #' @description #' Call these methods to generate a string that is suitable for #' use in a query as a literal value of the correct type, to make sure that you -#' generate valid SQL and avoid SQL injection. +#' generate valid SQL and protect against SQL injection attacks. #' #' @inheritParams dbQuoteString #' @param x A vector to quote as string. diff --git a/man/dbListObjects.Rd b/man/dbListObjects.Rd index ddaa79f52..7551db0af 100644 --- a/man/dbListObjects.Rd +++ b/man/dbListObjects.Rd @@ -10,15 +10,22 @@ dbListObjects(conn, prefix = NULL, ...) \item{conn}{A \linkS4class{DBIConnection} object, as returned by \code{\link[=dbConnect]{dbConnect()}}.} -\item{prefix}{An optional prefix, passed to \code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. +\item{prefix}{A fully qualified path in the database's namespace, or \code{NULL}. +will be passed to \code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. If given the method will return all objects accessible through this prefix.} \item{...}{Other parameters passed on to methods.} } \description{ -Returns the names of remote tables accessible through this connection -(possibly via a prefix) as a data frame. -This should, where possible, include temporary objects. +Returns the names of remote objects accessible through this connection +as a data frame. +This should include temporary objects, but not all database backends +(in particular \pkg{RMariaDB} and \pkg{RMySQL}) support this. +Compared to \code{\link[=dbListTables]{dbListTables()}}, this method also enumerates tables and views +in schemas, and returns fully qualified identifiers to access these objects. +This allows exploration of all database objects available to the current +user, including those that can only be accessed by giving the full +namespace. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbListObjects")} } diff --git a/man/dbListTables.Rd b/man/dbListTables.Rd index 7f6f2b468..22869b63c 100644 --- a/man/dbListTables.Rd +++ b/man/dbListTables.Rd @@ -31,7 +31,8 @@ or invalid connection. \description{ Returns the unquoted names of remote tables accessible through this connection. -This should, where possible, include temporary tables, and views. +This should include views and temporary objects, but not all database backends +(in particular \pkg{RMariaDB} and \pkg{RMySQL}) support this. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbListTables")} } diff --git a/man/dbQuoteIdentifier.Rd b/man/dbQuoteIdentifier.Rd index 5507dac3a..9766976aa 100644 --- a/man/dbQuoteIdentifier.Rd +++ b/man/dbQuoteIdentifier.Rd @@ -32,8 +32,8 @@ to achieve this behavior, but this is not required.) \description{ Call this method to generate a string that is suitable for use in a query as a column or table name, to make sure that you -generate valid SQL and avoid SQL injection. The inverse operation is -\code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. +generate valid SQL and protect against SQL injection attacks. The inverse +operation is \code{\link[=dbUnquoteIdentifier]{dbUnquoteIdentifier()}}. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbQuoteIdentifier")} } diff --git a/man/dbQuoteLiteral.Rd b/man/dbQuoteLiteral.Rd index e1ae829c1..a172bf23c 100644 --- a/man/dbQuoteLiteral.Rd +++ b/man/dbQuoteLiteral.Rd @@ -17,7 +17,7 @@ an active connection to an DBMS.} \description{ Call these methods to generate a string that is suitable for use in a query as a literal value of the correct type, to make sure that you -generate valid SQL and avoid SQL injection. +generate valid SQL and protect against SQL injection attacks. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbQuoteLiteral")} } diff --git a/man/dbQuoteString.Rd b/man/dbQuoteString.Rd index f6dfd5267..514de1eab 100644 --- a/man/dbQuoteString.Rd +++ b/man/dbQuoteString.Rd @@ -29,7 +29,7 @@ to achieve this behavior, but this is not required.) \description{ Call this method to generate a string that is suitable for use in a query as a string literal, to make sure that you -generate valid SQL and avoid SQL injection. +generate valid SQL and protect against SQL injection attacks. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbQuoteString")} } diff --git a/man/dbUnquoteIdentifier.Rd b/man/dbUnquoteIdentifier.Rd index 8f4d83d8a..7b69a0526 100644 --- a/man/dbUnquoteIdentifier.Rd +++ b/man/dbUnquoteIdentifier.Rd @@ -27,7 +27,7 @@ back to a list of \link{Table} objects. dbUnquoteIdentifier( ANSI(), - SQL(c("Schema"."Table", "UnqualifiedTable")) + SQL(c('"Schema"."Table"', "UnqualifiedTable")) ) # Character vectors are wrapped in a list From 69d7aa8edede3e9489d16d7c6a1e87c1157cf34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 30 Jan 2018 08:17:20 +0100 Subject: [PATCH 19/44] type stability --- R/quote.R | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/R/quote.R b/R/quote.R index 68b0ff299..5d072afcb 100644 --- a/R/quote.R +++ b/R/quote.R @@ -106,9 +106,7 @@ setGeneric("dbQuoteIdentifier", quote_identifier <- function(conn, x, ...) { - if (is.list(x)) { - return(vapply(x, function(xx) list(dbQuoteIdentifier(conn, xx)), list(1))) - } + # Don't support lists, auto-vectorization violates type stability if (is(x, "SQL")) return(x) if (is(x, "Table")) { return(SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = "."))) From e0d1b52f7d0081ebc590e35cc9eb9f8a2d4cb42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 30 Jan 2018 08:25:41 +0000 Subject: [PATCH 20/44] Deploy from Travis build 966 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/335048749 Commit: 4e8e85591e779ca062d45eaba2a8ff09943dac9a --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 2dda0d73e..78e0baf30 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-01-29

      +

      2018-01-30

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index ec3af85b1..ff0fa23d9 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-01-29

      +

      2018-01-30

      From 70e8deb6518614cde583e75e41d1380dece39801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 31 Jan 2018 08:30:36 +0000 Subject: [PATCH 21/44] Deploy from Travis build 967 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/335515989 Commit: e0d1b52f7d0081ebc590e35cc9eb9f8a2d4cb42d --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 78e0baf30..42a7e64a1 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-01-30

      +

      2018-01-31

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index ff0fa23d9..010c6514d 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-01-30

      +

      2018-01-31

      From adee1b049cb6dc615dbf5e896e516d2eeac62f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 31 Jan 2018 18:38:10 +0100 Subject: [PATCH 22/44] get rid of . --- R/quote.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/R/quote.R b/R/quote.R index 5d072afcb..869a35967 100644 --- a/R/quote.R +++ b/R/quote.R @@ -190,10 +190,9 @@ setMethod("dbUnquoteIdentifier", signature("DBIConnection"), function(conn, x, . return(vapply(x, dbUnquoteIdentifier, conn = conn, list(1))) } if (is(x, "SQL")) { - . <- strsplit(as.character(x), '^"|"$|"[.]"') - . <- lapply(., `[`, -1L) - split <- . - tables <- lapply(split, Table) + split <- strsplit(as.character(x), '^"|"$|"[.]"') + components <- lapply(split, `[`, -1L) + tables <- lapply(components, Table) quoted <- lapply(tables, dbQuoteIdentifier, conn = conn) bad <- quoted != x if (any(bad)) { From 14008e45bcfd83d19ac7778cac702c4ce91115dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 31 Jan 2018 20:07:19 +0100 Subject: [PATCH 23/44] Table -> Id --- NAMESPACE | 2 +- R/quote.R | 6 +++--- R/table.R | 10 +++++----- man/{Table.Rd => Id.Rd} | 8 +++----- man/hidden_aliases.Rd | 8 ++++---- 5 files changed, 16 insertions(+), 18 deletions(-) rename man/{Table.Rd => Id.Rd} (86%) diff --git a/NAMESPACE b/NAMESPACE index 039937c5f..18b757fbc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,9 +5,9 @@ S3method("[[",SQL) S3method(toString,Table) export(.SQL92Keywords) export(ANSI) +export(Id) export(SQL) export(SQLKeywords) -export(Table) export(dbBegin) export(dbBind) export(dbBreak) diff --git a/R/quote.R b/R/quote.R index 869a35967..f1fc3eb6f 100644 --- a/R/quote.R +++ b/R/quote.R @@ -108,7 +108,7 @@ quote_identifier <- function(conn, x, ...) { # Don't support lists, auto-vectorization violates type stability if (is(x, "SQL")) return(x) - if (is(x, "Table")) { + if (is(x, "Id")) { return(SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = "."))) } if (!is.character(x)) stop("x must be character or SQL", call. = FALSE) @@ -200,11 +200,11 @@ setMethod("dbUnquoteIdentifier", signature("DBIConnection"), function(conn, x, . } return(tables) } - if (is(x, "Table")) { + if (is(x, "Id")) { return(list(x)) } if (is.character(x)) { - return(list(do.call(Table, as.list(x)))) + return(list(do.call(Id, as.list(x)))) } stop("x must be character, SQL or Table, or a list of such objects", call. = FALSE) }) diff --git a/R/table.R b/R/table.R index 80c82ba76..f7d33482f 100644 --- a/R/table.R +++ b/R/table.R @@ -1,5 +1,5 @@ #' @rdname Table -setClass("Table", slots = list(name = "character")) +setClass("Id", slots = list(name = "character")) #' Refer to a table nested in a hierarchy (e.g. within a schema) #' @@ -11,18 +11,18 @@ setClass("Table", slots = list(name = "character")) #' For more on these concepts, see #' \url{http://stackoverflow.com/questions/7022755/} #' @export -Table <- function(...) { +Id <- function(...) { components <- c(...) if (is.null(names(components)) || any(names(components) == "")) { stop("All arguments to Table() must be named.", call. = FALSE) } - new("Table", name = components) + new("Id", name = components) } #' @rdname hidden_aliases #' @param object Table object to print #' @export -setMethod("show", signature("Table"), function(object) { +setMethod("show", signature("Id"), function(object) { cat(toString(object), "\n", sep = "") }) @@ -33,4 +33,4 @@ toString.Table <- function(x, ...) { #' @rdname hidden_aliases #' @export -setMethod("dbQuoteIdentifier", signature("DBIConnection", "Table"), quote_identifier) +setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), quote_identifier) diff --git a/man/Table.Rd b/man/Id.Rd similarity index 86% rename from man/Table.Rd rename to man/Id.Rd index ddf8425ed..8f9a2ead8 100644 --- a/man/Table.Rd +++ b/man/Id.Rd @@ -1,12 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/table.R -\docType{class} -\name{Table-class} -\alias{Table-class} -\alias{Table} +\name{Id} +\alias{Id} \title{Refer to a table nested in a hierarchy (e.g. within a schema)} \usage{ -Table(...) +Id(...) } \arguments{ \item{...}{Components of the hierarchy, e.g. \code{schema}, \code{table}, diff --git a/man/hidden_aliases.Rd b/man/hidden_aliases.Rd index 0a5215ef6..a200551d1 100644 --- a/man/hidden_aliases.Rd +++ b/man/hidden_aliases.Rd @@ -36,8 +36,8 @@ \alias{dbQuoteLiteral,DBIConnection-method} \alias{sqlCreateTable,DBIConnection-method} \alias{sqlAppendTable,DBIConnection-method} -\alias{show,Table-method} -\alias{dbQuoteIdentifier,DBIConnection,Table-method} +\alias{show,Id-method} +\alias{dbQuoteIdentifier,DBIConnection,Id-method} \alias{dbWithTransaction,DBIConnection-method} \title{Internal page for hidden aliases} \usage{ @@ -108,9 +108,9 @@ \S4method{sqlAppendTable}{DBIConnection}(con, table, values, row.names = NA, ...) -\S4method{show}{Table}(object) +\S4method{show}{Id}(object) -\S4method{dbQuoteIdentifier}{DBIConnection,Table}(conn, x, ...) +\S4method{dbQuoteIdentifier}{DBIConnection,Id}(conn, x, ...) \S4method{dbWithTransaction}{DBIConnection}(conn, code) } From b13a85761e8b8b6ccda75720df791231e6b5a12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 31 Jan 2018 22:15:44 +0100 Subject: [PATCH 24/44] oops --- R/table.R | 2 +- man/Id.Rd | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/R/table.R b/R/table.R index f7d33482f..b97b5ed47 100644 --- a/R/table.R +++ b/R/table.R @@ -1,4 +1,4 @@ -#' @rdname Table +#' @rdname Id setClass("Id", slots = list(name = "character")) #' Refer to a table nested in a hierarchy (e.g. within a schema) diff --git a/man/Id.Rd b/man/Id.Rd index 8f9a2ead8..328971074 100644 --- a/man/Id.Rd +++ b/man/Id.Rd @@ -1,6 +1,8 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/table.R -\name{Id} +\docType{class} +\name{Id-class} +\alias{Id-class} \alias{Id} \title{Refer to a table nested in a hierarchy (e.g. within a schema)} \usage{ From dca98810c951fbc8abdabe1f98ed78d83679c92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 1 Feb 2018 08:28:10 +0000 Subject: [PATCH 25/44] Deploy from Travis build 972 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/335996333 Commit: 70e8deb6518614cde583e75e41d1380dece39801 --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 42a7e64a1..d7396f120 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-01-31

      +

      2018-02-01

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 010c6514d..54b645c35 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-01-31

      +

      2018-02-01

      From 7d90fe1cf3e86b6c9a6a23da22200cc053ca0bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 2 Feb 2018 08:27:20 +0000 Subject: [PATCH 26/44] Deploy from Travis build 973 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/336454850 Commit: dca98810c951fbc8abdabe1f98ed78d83679c92d --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index d7396f120..246ce5c01 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-01

      +

      2018-02-02

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 54b645c35..610911a18 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-01

      +

      2018-02-02

      From 1dd0ebc8a3121de08321f9b49374586887ef959b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 2 Feb 2018 23:14:48 +0100 Subject: [PATCH 27/44] fix missing bits and pieces --- DESCRIPTION | 2 +- NAMESPACE | 5 ++++- R/DBConnection.R | 35 +++++++++++++++++++++++++++++++++++ R/quote.R | 4 ++++ R/table.R | 8 ++------ man/hidden_aliases.Rd | 35 ++++++++++++++++++++++++----------- 6 files changed, 70 insertions(+), 19 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index dc5a51bb5..7fa1bf417 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,6 +33,7 @@ BugReports: https://github.com/r-dbi/DBI/issues Collate: 'DBObject.R' 'DBDriver.R' + 'table.R' 'DBConnection.R' 'ANSI.R' 'DBI-package.R' @@ -47,7 +48,6 @@ Collate: 'rownames.R' 'table-create.R' 'table-insert.R' - 'table.R' 'transactions.R' VignetteBuilder: knitr Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "pkgapi::api_roclet")) diff --git a/NAMESPACE b/NAMESPACE index 18b757fbc..aefe2750e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,7 @@ S3method("[",SQL) S3method("[[",SQL) -S3method(toString,Table) +S3method(toString,Id) export(.SQL92Keywords) export(ANSI) export(Id) @@ -72,6 +72,7 @@ exportClasses(DBIResult) exportClasses(SQL) exportMethods(dbDataType) exportMethods(dbExecute) +exportMethods(dbExistsTable) exportMethods(dbFetch) exportMethods(dbGetQuery) exportMethods(dbListFields) @@ -79,9 +80,11 @@ exportMethods(dbQuoteIdentifier) exportMethods(dbQuoteLiteral) exportMethods(dbQuoteString) exportMethods(dbReadTable) +exportMethods(dbRemoveTable) exportMethods(dbSendStatement) exportMethods(dbUnquoteIdentifier) exportMethods(dbWithTransaction) +exportMethods(dbWriteTable) exportMethods(show) exportMethods(sqlAppendTable) exportMethods(sqlCreateTable) diff --git a/R/DBConnection.R b/R/DBConnection.R index c447c87f7..dcea1b629 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -1,3 +1,6 @@ +#' @include table.R +NULL + #' DBIConnection class #' #' This virtual class encapsulates the connection to a DBMS, and it provides @@ -455,6 +458,14 @@ setMethod("dbReadTable", signature("DBIConnection", "character"), } ) +#' @rdname hidden_aliases +#' @export +setMethod("dbReadTable", signature("DBIConnection", "Id"), + function(conn, name, ...) { + dbReadTable(conn, dbQuoteIdentifier(conn, name), ...) + } +) + #' Copy data frames to database tables #' #' Writes, overwrites or appends a data frame to a database table, optionally @@ -493,6 +504,14 @@ setGeneric("dbWriteTable", def = function(conn, name, value, ...) standardGeneric("dbWriteTable") ) +#' @rdname hidden_aliases +#' @export +setMethod("dbWriteTable", signature("DBIConnection", "Id"), + function(conn, name, ...) { + dbWriteTable(conn, dbQuoteIdentifier(conn, name), ...) + } +) + #' Does a table exist? #' #' Returns if a table given by name exists in the database. @@ -521,6 +540,14 @@ setGeneric("dbExistsTable", valueClass = "logical" ) +#' @rdname hidden_aliases +#' @export +setMethod("dbExistsTable", signature("DBIConnection", "Id"), + function(conn, name, ...) { + dbExistsTable(conn, dbQuoteIdentifier(conn, name), ...) + } +) + #' Remove a table from the database #' #' Remove a remote table (e.g., created by [dbWriteTable()]) @@ -549,3 +576,11 @@ setGeneric("dbExistsTable", setGeneric("dbRemoveTable", def = function(conn, name, ...) standardGeneric("dbRemoveTable") ) + +#' @rdname hidden_aliases +#' @export +setMethod("dbRemoveTable", signature("DBIConnection", "Id"), + function(conn, name, ...) { + dbRemoveTable(conn, dbQuoteIdentifier(conn, name), ...) + } +) diff --git a/R/quote.R b/R/quote.R index f1fc3eb6f..d4f3bceec 100644 --- a/R/quote.R +++ b/R/quote.R @@ -140,6 +140,10 @@ setMethod("dbQuoteIdentifier", signature("DBIConnection", "character"), quote_id #' @export setMethod("dbQuoteIdentifier", signature("DBIConnection", "SQL"), quote_identifier) +#' @rdname hidden_aliases +#' @export +setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), quote_identifier) + #' Unquote identifiers #' #' Call this method to convert a [SQL] object created by [dbQuoteIdentifier()] diff --git a/R/table.R b/R/table.R index b97b5ed47..4db6b9775 100644 --- a/R/table.R +++ b/R/table.R @@ -27,10 +27,6 @@ setMethod("show", signature("Id"), function(object) { }) #' @export -toString.Table <- function(x, ...) { - paste0("
      ", paste(x@name, collapse = ".")) +toString.Id <- function(x, ...) { + paste0("
      ", paste0(names(x@name), " = ", x@name, collapse = ", ")) } - -#' @rdname hidden_aliases -#' @export -setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), quote_identifier) diff --git a/man/hidden_aliases.Rd b/man/hidden_aliases.Rd index a200551d1..9a61e9a54 100644 --- a/man/hidden_aliases.Rd +++ b/man/hidden_aliases.Rd @@ -1,18 +1,24 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/DBDriver.R, R/DBConnection.R, R/ANSI.R, -% R/DBResult.R, R/data.R, R/deprecated.R, R/hidden.R, R/interpolate.R, -% R/quote.R, R/table-create.R, R/table-insert.R, R/table.R, R/transactions.R +% Please edit documentation in R/DBDriver.R, R/table.R, R/DBConnection.R, +% R/ANSI.R, R/DBResult.R, R/data.R, R/deprecated.R, R/hidden.R, +% R/interpolate.R, R/quote.R, R/table-create.R, R/table-insert.R, +% R/transactions.R \docType{methods} \name{dbDriver,character-method} \alias{dbDriver,character-method} \alias{show,DBIDriver-method} \alias{dbDataType,DBIObject-method} +\alias{show,Id-method} \alias{show,DBIConnection-method} \alias{dbSendStatement,DBIConnection,character-method} \alias{dbGetQuery,DBIConnection,character-method} \alias{dbExecute,DBIConnection,character-method} \alias{dbListFields,DBIConnection,character-method} \alias{dbReadTable,DBIConnection,character-method} +\alias{dbReadTable,DBIConnection,Id-method} +\alias{dbWriteTable,DBIConnection,Id-method} +\alias{dbExistsTable,DBIConnection,Id-method} +\alias{dbRemoveTable,DBIConnection,Id-method} \alias{show,AnsiConnection-method} \alias{show,DBIResult-method} \alias{dbFetch,DBIResult-method} @@ -29,6 +35,7 @@ \alias{dbQuoteIdentifier,DBIConnection,ANY-method} \alias{dbQuoteIdentifier,DBIConnection,character-method} \alias{dbQuoteIdentifier,DBIConnection,SQL-method} +\alias{dbQuoteIdentifier,DBIConnection,Id-method} \alias{dbUnquoteIdentifier,DBIConnection-method} \alias{dbQuoteString,DBIConnection,ANY-method} \alias{dbQuoteString,DBIConnection,character-method} @@ -36,8 +43,6 @@ \alias{dbQuoteLiteral,DBIConnection-method} \alias{sqlCreateTable,DBIConnection-method} \alias{sqlAppendTable,DBIConnection-method} -\alias{show,Id-method} -\alias{dbQuoteIdentifier,DBIConnection,Id-method} \alias{dbWithTransaction,DBIConnection-method} \title{Internal page for hidden aliases} \usage{ @@ -47,6 +52,8 @@ \S4method{dbDataType}{DBIObject}(dbObj, obj, ...) +\S4method{show}{Id}(object) + \S4method{show}{DBIConnection}(object) \S4method{dbSendStatement}{DBIConnection,character}(conn, statement, ...) @@ -60,6 +67,14 @@ \S4method{dbReadTable}{DBIConnection,character}(conn, name, ..., row.names = FALSE, check.names = TRUE) +\S4method{dbReadTable}{DBIConnection,Id}(conn, name, ...) + +\S4method{dbWriteTable}{DBIConnection,Id}(conn, name, value, ...) + +\S4method{dbExistsTable}{DBIConnection,Id}(conn, name, ...) + +\S4method{dbRemoveTable}{DBIConnection,Id}(conn, name, ...) + \S4method{show}{AnsiConnection}(object) \S4method{show}{DBIResult}(object) @@ -92,6 +107,8 @@ \S4method{dbQuoteIdentifier}{DBIConnection,SQL}(conn, x, ...) +\S4method{dbQuoteIdentifier}{DBIConnection,Id}(conn, x, ...) + \S4method{dbUnquoteIdentifier}{DBIConnection}(conn, x, ...) \S4method{dbQuoteString}{DBIConnection,ANY}(conn, x, ...) @@ -108,10 +125,6 @@ \S4method{sqlAppendTable}{DBIConnection}(con, table, values, row.names = NA, ...) -\S4method{show}{Id}(object) - -\S4method{dbQuoteIdentifier}{DBIConnection,Id}(conn, x, ...) - \S4method{dbWithTransaction}{DBIConnection}(conn, code) } \arguments{ @@ -119,11 +132,11 @@ \item{n}{Number of rows to fetch, default -1} -\item{object}{Object to display} +\item{object}{Table object to print} \item{object}{Object to display} -\item{object}{Table object to print} +\item{object}{Object to display} } \description{ For S4 methods that require a documentation entry but only clutter the index. From 138c2fdc1ab0fa358416957f35a55ee7a3b9d652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 2 Feb 2018 22:59:11 +0000 Subject: [PATCH 28/44] Deploy from Travis build 976 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/336764897 Commit: e59d1cdcd68fc538088af7f73b475bc2a7ee0eeb --- docs/articles/spec.html | 49 +++++- docs/reference/DBIConnection-class.html | 9 +- docs/reference/DBIResult-class.html | 4 +- docs/reference/Id.html | 148 ++++++++++++++++++ docs/reference/dbBind.html | 4 +- docs/reference/dbClearResult.html | 4 +- docs/reference/dbColumnInfo.html | 4 +- docs/reference/dbDataType.html | 9 +- docs/reference/dbDisconnect.html | 9 +- docs/reference/dbExecute.html | 9 +- docs/reference/dbExistsTable.html | 9 +- docs/reference/dbFetch.html | 4 +- docs/reference/dbGetException.html | 8 +- docs/reference/dbGetInfo.html | 12 +- docs/reference/dbGetQuery.html | 8 +- docs/reference/dbGetRowCount.html | 4 +- docs/reference/dbGetRowsAffected.html | 4 +- docs/reference/dbGetStatement.html | 4 +- docs/reference/dbHasCompleted.html | 4 +- docs/reference/dbIsValid.html | 12 +- docs/reference/dbListFields.html | 8 +- docs/reference/dbListObjects.html | 185 ++++++++++++++++++++++ docs/reference/dbListResults.html | 8 +- docs/reference/dbListTables.html | 11 +- docs/reference/dbQuoteIdentifier.html | 14 +- docs/reference/dbQuoteLiteral.html | 5 +- docs/reference/dbQuoteString.html | 5 +- docs/reference/dbReadTable.html | 9 +- docs/reference/dbRemoveTable.html | 9 +- docs/reference/dbSendQuery.html | 6 +- docs/reference/dbSendStatement.html | 8 +- docs/reference/dbUnquoteIdentifier.html | 196 ++++++++++++++++++++++++ docs/reference/dbWriteTable.html | 9 +- docs/reference/hidden_aliases.html | 31 +++- docs/reference/index.html | 24 ++- 35 files changed, 737 insertions(+), 109 deletions(-) create mode 100644 docs/reference/Id.html create mode 100644 docs/reference/dbListObjects.html create mode 100644 docs/reference/dbUnquoteIdentifier.html diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 610911a18..565260d5b 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -1312,7 +1312,7 @@

      Description

      -Call this method to generate a string that is suitable for use in a query as a string literal, to make sure that you generate valid SQL and avoid SQL injection. +Call this method to generate a string that is suitable for use in a query as a string literal, to make sure that you generate valid SQL and protect against SQL injection attacks.

      Methods in other packages @@ -1421,7 +1421,7 @@

      Description

      -Call this method to generate a string that is suitable for use in a query as a column name, to make sure that you generate valid SQL and avoid SQL injection. +Call this method to generate a string that is suitable for use in a query as a column or table name, to make sure that you generate valid SQL and protect against SQL injection attacks. The inverse operation is dbUnquoteIdentifier().

      Methods in other packages @@ -1439,12 +1439,12 @@

    • -DBI::dbQuoteIdentifier(“DBIConnection”, “SQL”) +DBI::dbQuoteIdentifier(“DBIConnection”, “Id”)

    • -DBI::dbQuoteIdentifier(“DBIConnection”, “Table”) +DBI::dbQuoteIdentifier(“DBIConnection”, “SQL”)

    • @@ -1468,7 +1468,7 @@

      @@ -1487,7 +1487,7 @@

      Value

      -dbQuoteIdentifier() returns an object that can be coerced to character, of the same length as the input. For an empty character vector this function returns a length-0 object. An error is raised if the input contains NA, but not for an empty string. +dbQuoteIdentifier() returns an object that can be coerced to character, of the same length as the input. For an empty character vector this function returns a length-0 object. The names of the input argument are preserved in the output. An error is raised if the input contains NA, but not for an empty string.

      When passing the returned object again to dbQuoteIdentifier() as x argument, it is returned unchanged. Passing objects of class SQL should also return them unchanged. (For backends it may be most convenient to return SQL objects to achieve this behavior, but this is not required.) @@ -1544,6 +1544,11 @@

      DBI::dbReadTable(“DBIConnection”, “character”)

      +
    • +

      +DBI::dbReadTable(“DBIConnection”, “Id”) +

      +
    • Arguments @@ -1687,6 +1692,16 @@

      Writes, overwrites or appends a data frame to a database table, optionally converting row names to a column and specifying SQL data types for fields.

      +

      +Methods in other packages +

      +
        +
      • +

        +DBI::dbWriteTable(“DBIConnection”, “Id”) +

        +
      • +

      Arguments

      @@ -1938,7 +1953,7 @@

      Description

      -Returns the unquoted names of remote tables accessible through this connection. This should, where possible, include temporary tables, and views. +Returns the unquoted names of remote tables accessible through this connection. This should include views and temporary objects, but not all database backends (in particular RMariaDB and RMySQL) support this.

      Arguments @@ -2012,6 +2027,16 @@

      Returns if a table given by name exists in the database.

      +

      +Methods in other packages +

      +
        +
      • +

        +DBI::dbExistsTable(“DBIConnection”, “Id”) +

        +
      • +

      Arguments

      @@ -2115,6 +2140,16 @@

      Remove a remote table (e.g., created by dbWriteTable()) from the database.

      +

      +Methods in other packages +

      +
        +
      • +

        +DBI::dbRemoveTable(“DBIConnection”, “Id”) +

        +
      • +

      Arguments

      diff --git a/docs/reference/DBIConnection-class.html b/docs/reference/DBIConnection-class.html index 6268ab3c0..96bd3d611 100644 --- a/docs/reference/DBIConnection-class.html +++ b/docs/reference/DBIConnection-class.html @@ -125,10 +125,11 @@

      See a dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbSendStatement, dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

      Examples

      diff --git a/docs/reference/DBIResult-class.html b/docs/reference/DBIResult-class.html index dabb03fd3..98c6dda2c 100644 --- a/docs/reference/DBIResult-class.html +++ b/docs/reference/DBIResult-class.html @@ -132,7 +132,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      diff --git a/docs/reference/Id.html b/docs/reference/Id.html new file mode 100644 index 000000000..a43155e5d --- /dev/null +++ b/docs/reference/Id.html @@ -0,0 +1,148 @@ + + + + + + + + +Refer to a table nested in a hierarchy (e.g. within a schema) — Id-class • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + +
      + +
      +
      + + + +

      Objects of class Table have a single slot name, which is a named +character vector.

      + + +
      Id(...)
      + +

      Arguments

      +

      -A character vector to quote as identifier. +A character vector, SQL or Table object to quote as identifier.

      + + + + + +
      ...

      Components of the hierarchy, e.g. schema, table, +or cluster, catalog, schema, table. +For more on these concepts, see +http://stackoverflow.com/questions/7022755/

      + + + + + + +
      + + +
      +

      Site built with pkgdown.

      +
      + +
      + + + + diff --git a/docs/reference/dbBind.html b/docs/reference/dbBind.html index d5925de35..8c063b24d 100644 --- a/docs/reference/dbBind.html +++ b/docs/reference/dbBind.html @@ -260,7 +260,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbClearResult.html b/docs/reference/dbClearResult.html index 968ed5687..ee86a737b 100644 --- a/docs/reference/dbClearResult.html +++ b/docs/reference/dbClearResult.html @@ -155,7 +155,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbColumnInfo.html b/docs/reference/dbColumnInfo.html index 6a4d4f309..49ab3a283 100644 --- a/docs/reference/dbColumnInfo.html +++ b/docs/reference/dbColumnInfo.html @@ -142,7 +142,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbDataType.html b/docs/reference/dbDataType.html index 27e4a76c2..fa75bab23 100644 --- a/docs/reference/dbDataType.html +++ b/docs/reference/dbDataType.html @@ -202,10 +202,11 @@

      See a dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbSendStatement, dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

      Examples

      diff --git a/docs/reference/dbDisconnect.html b/docs/reference/dbDisconnect.html index 601477a0d..0938a0dbd 100644 --- a/docs/reference/dbDisconnect.html +++ b/docs/reference/dbDisconnect.html @@ -150,10 +150,11 @@

      See a dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbSendStatement, dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

      Examples

      diff --git a/docs/reference/dbExecute.html b/docs/reference/dbExecute.html index ba6b578c1..9878e64cb 100644 --- a/docs/reference/dbExecute.html +++ b/docs/reference/dbExecute.html @@ -162,10 +162,11 @@

      See a dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbSendStatement, dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement, + dbWriteTable

      Examples

      diff --git a/docs/reference/dbExistsTable.html b/docs/reference/dbExistsTable.html index 631463d48..41ae729af 100644 --- a/docs/reference/dbExistsTable.html +++ b/docs/reference/dbExistsTable.html @@ -108,6 +108,7 @@

      Does a table exist?

      Methods in other packages

      @@ -169,10 +170,10 @@

      See a dbExecute, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbFetch.html b/docs/reference/dbFetch.html index 46bae2ed7..f701fbd47 100644 --- a/docs/reference/dbFetch.html +++ b/docs/reference/dbFetch.html @@ -235,7 +235,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbGetException.html b/docs/reference/dbGetException.html index 6c58500c4..d3a51cce5 100644 --- a/docs/reference/dbGetException.html +++ b/docs/reference/dbGetException.html @@ -136,10 +136,10 @@

      See a dbExecute, dbExistsTable, dbGetInfo, dbGetQuery, dbIsValid, dbListFields, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      diff --git a/docs/reference/dbGetInfo.html b/docs/reference/dbGetInfo.html index 4513dbdfc..e5a73d68f 100644 --- a/docs/reference/dbGetInfo.html +++ b/docs/reference/dbGetInfo.html @@ -160,10 +160,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetQuery, dbIsValid, dbListFields, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, @@ -172,7 +172,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      diff --git a/docs/reference/dbGetQuery.html b/docs/reference/dbGetQuery.html index 1ae6be030..c4a20513f 100644 --- a/docs/reference/dbGetQuery.html +++ b/docs/reference/dbGetQuery.html @@ -188,10 +188,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbIsValid, dbListFields, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbGetRowCount.html b/docs/reference/dbGetRowCount.html index 856dbabb0..f5afdaaa8 100644 --- a/docs/reference/dbGetRowCount.html +++ b/docs/reference/dbGetRowCount.html @@ -158,7 +158,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbGetRowsAffected.html b/docs/reference/dbGetRowsAffected.html index b107b7ea3..c09594f5b 100644 --- a/docs/reference/dbGetRowsAffected.html +++ b/docs/reference/dbGetRowsAffected.html @@ -150,7 +150,9 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbGetStatement.html b/docs/reference/dbGetStatement.html index 1064aad92..4dfc9c3f8 100644 --- a/docs/reference/dbGetStatement.html +++ b/docs/reference/dbGetStatement.html @@ -145,7 +145,9 @@

      See a dbGetRowsAffected, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbHasCompleted.html b/docs/reference/dbHasCompleted.html index 29e16ac05..0656ffad2 100644 --- a/docs/reference/dbHasCompleted.html +++ b/docs/reference/dbHasCompleted.html @@ -162,7 +162,9 @@

      See a dbGetRowsAffected, dbGetStatement, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbIsValid.html b/docs/reference/dbIsValid.html index e7d55313c..c50e1020a 100644 --- a/docs/reference/dbIsValid.html +++ b/docs/reference/dbIsValid.html @@ -162,10 +162,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbListFields, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Other DBIResult generics: DBIResult-class, dbBind, dbClearResult, dbColumnInfo, dbFetch, @@ -174,7 +174,9 @@

      See a dbGetStatement, dbHasCompleted, dbQuoteIdentifier, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbListFields.html b/docs/reference/dbListFields.html index 8073dfa7e..c84cfd343 100644 --- a/docs/reference/dbListFields.html +++ b/docs/reference/dbListFields.html @@ -138,10 +138,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListResults, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListObjects, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbListObjects.html b/docs/reference/dbListObjects.html new file mode 100644 index 000000000..8fe4beb7d --- /dev/null +++ b/docs/reference/dbListObjects.html @@ -0,0 +1,185 @@ + + + + + + + + +List remote objects — dbListObjects • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + +
      + +
      +
      + + + +

      Returns the names of remote objects accessible through this connection +as a data frame. +This should include temporary objects, but not all database backends +(in particular RMariaDB and RMySQL) support this. +Compared to dbListTables(), this method also enumerates tables and views +in schemas, and returns fully qualified identifiers to access these objects. +This allows exploration of all database objects available to the current +user, including those that can only be accessed by giving the full +namespace.

      + + +
      dbListObjects(conn, prefix = NULL, ...)
      + +

      Arguments

      + + + + + + + + + + + + + + +
      conn

      A DBIConnection object, as returned by +dbConnect().

      prefix

      A fully qualified path in the database's namespace, or NULL. +will be passed to dbUnquoteIdentifier(). +If given the method will return all objects accessible through this prefix.

      ...

      Other parameters passed on to methods.

      + +

      See also

      + +

      Other DBIConnection generics: DBIConnection-class, + dbDataType, dbDisconnect, + dbExecute, dbExistsTable, + dbGetException, dbGetInfo, + dbGetQuery, dbIsValid, + dbListFields, dbListResults, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      + + +

      Examples

      +
      con <- dbConnect(RSQLite::SQLite(), ":memory:") + +dbListObjects(con)
      #> Error in (function (classes, fdef, mtable) { methods <- .findInheritedMethods(classes, fdef, mtable) if (length(methods) == 1L) return(methods[[1L]]) else if (length(methods) == 0L) { cnames <- paste0("\"", vapply(classes, as.character, ""), "\"", collapse = ", ") stop(gettextf("unable to find an inherited method for function %s for signature %s", sQuote(fdef@generic), sQuote(cnames)), domain = NA) } else stop("Internal error in finding inherited methods; didn't return a unique method", domain = NA)})(list(structure("SQLiteConnection", package = "RSQLite")), structure(function (conn, prefix = NULL, ...) { ans <- standardGeneric("dbListObjects") .valueClassTest(ans, "data.frame", "dbListObjects") }, generic = structure("dbListObjects", package = "DBI"), package = "DBI", group = list(), valueClass = "data.frame", signature = c("conn", "prefix"), default = `\001NULL\001`, skeleton = (function (conn, prefix = NULL, ...) stop("invalid call in method dispatch to 'dbListObjects' (no default method)", domain = NA))(conn, prefix, ...), class = structure("standardGeneric", package = "methods")), <environment>): unable to find an inherited method for function ‘dbListObjects’ for signature ‘"SQLiteConnection"’
      dbWriteTable(con, "mtcars", mtcars) +dbListObjects(con)
      #> Error in (function (classes, fdef, mtable) { methods <- .findInheritedMethods(classes, fdef, mtable) if (length(methods) == 1L) return(methods[[1L]]) else if (length(methods) == 0L) { cnames <- paste0("\"", vapply(classes, as.character, ""), "\"", collapse = ", ") stop(gettextf("unable to find an inherited method for function %s for signature %s", sQuote(fdef@generic), sQuote(cnames)), domain = NA) } else stop("Internal error in finding inherited methods; didn't return a unique method", domain = NA)})(list(structure("SQLiteConnection", package = "RSQLite")), structure(function (conn, prefix = NULL, ...) { ans <- standardGeneric("dbListObjects") .valueClassTest(ans, "data.frame", "dbListObjects") }, generic = structure("dbListObjects", package = "DBI"), package = "DBI", group = list(), valueClass = "data.frame", signature = c("conn", "prefix"), default = `\001NULL\001`, skeleton = (function (conn, prefix = NULL, ...) stop("invalid call in method dispatch to 'dbListObjects' (no default method)", domain = NA))(conn, prefix, ...), class = structure("standardGeneric", package = "methods")), <environment>): unable to find an inherited method for function ‘dbListObjects’ for signature ‘"SQLiteConnection"’
      +
      + +
      + +
      + + +
      +

      Site built with pkgdown.

      +
      + +
      +
      + + + diff --git a/docs/reference/dbListResults.html b/docs/reference/dbListResults.html index e695a1a6c..17f71b8bf 100644 --- a/docs/reference/dbListResults.html +++ b/docs/reference/dbListResults.html @@ -136,10 +136,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListTables, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListFields, dbListObjects, + dbListTables, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      diff --git a/docs/reference/dbListTables.html b/docs/reference/dbListTables.html index 7c0eb0952..e106e9c88 100644 --- a/docs/reference/dbListTables.html +++ b/docs/reference/dbListTables.html @@ -105,7 +105,8 @@

      List remote tables

      Returns the unquoted names of remote tables accessible through this connection. -This should, where possible, include temporary tables, and views. +This should include views and temporary objects, but not all database backends +(in particular RMariaDB and RMySQL) support this.

      Methods in other packages

      @@ -160,10 +161,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbReadTable, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbReadTable, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbQuoteIdentifier.html b/docs/reference/dbQuoteIdentifier.html index 3ebba16ba..9d94e30ce 100644 --- a/docs/reference/dbQuoteIdentifier.html +++ b/docs/reference/dbQuoteIdentifier.html @@ -104,16 +104,17 @@

      Quote identifiers

      Call this method to generate a string that is suitable for -use in a query as a column name, to make sure that you -generate valid SQL and avoid SQL injection. +use in a query as a column or table name, to make sure that you +generate valid SQL and protect against SQL injection attacks. The inverse +operation is dbUnquoteIdentifier().

      Methods in other packages

      @@ -131,7 +132,7 @@

      Ar x -

      A character vector to quote as identifier.

      +

      A character vector, SQL or Table object to quote as identifier.

      ... @@ -144,6 +145,7 @@

      Value

      dbQuoteIdentifier() returns an object that can be coerced to character, of the same length as the input. For an empty character vector this function returns a length-0 object. +The names of the input argument are preserved in the output. An error is raised if the input contains NA, but not for an empty string.

      When passing the returned object again to dbQuoteIdentifier() @@ -185,7 +187,9 @@

      See a dbGetRowsAffected, dbGetStatement, dbHasCompleted, dbIsValid, - dbQuoteLiteral, dbQuoteString

      + dbQuoteLiteral, + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbQuoteLiteral.html b/docs/reference/dbQuoteLiteral.html index 42b76a51e..b11ff81c6 100644 --- a/docs/reference/dbQuoteLiteral.html +++ b/docs/reference/dbQuoteLiteral.html @@ -105,7 +105,7 @@

      Quote literal values

      Call these methods to generate a string that is suitable for use in a query as a literal value of the correct type, to make sure that you -generate valid SQL and avoid SQL injection. +generate valid SQL and protect against SQL injection attacks.

      Methods in other packages

      @@ -144,7 +144,8 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteString

      + dbQuoteString, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbQuoteString.html b/docs/reference/dbQuoteString.html index 3e5c73855..d54b016e0 100644 --- a/docs/reference/dbQuoteString.html +++ b/docs/reference/dbQuoteString.html @@ -105,7 +105,7 @@

      Quote literal strings

      Call this method to generate a string that is suitable for use in a query as a string literal, to make sure that you -generate valid SQL and avoid SQL injection. +generate valid SQL and protect against SQL injection attacks.

      Methods in other packages

      @@ -181,7 +181,8 @@

      See a dbGetStatement, dbHasCompleted, dbIsValid, dbQuoteIdentifier, - dbQuoteLiteral

      + dbQuoteLiteral, + dbUnquoteIdentifier

      Examples

      diff --git a/docs/reference/dbReadTable.html b/docs/reference/dbReadTable.html index d3242db7f..dd99a239a 100644 --- a/docs/reference/dbReadTable.html +++ b/docs/reference/dbReadTable.html @@ -111,6 +111,7 @@

      Methods in other packages

      @@ -202,10 +203,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbRemoveTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbRemoveTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbRemoveTable.html b/docs/reference/dbRemoveTable.html index c58d4a575..cbe2024f3 100644 --- a/docs/reference/dbRemoveTable.html +++ b/docs/reference/dbRemoveTable.html @@ -109,6 +109,7 @@

      Remove a table from the database

      Methods in other packages

      @@ -167,10 +168,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbSendQuery, dbSendStatement, - dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbSendQuery, + dbSendStatement, dbWriteTable

      Examples

      diff --git a/docs/reference/dbSendQuery.html b/docs/reference/dbSendQuery.html index f193166ca..6da38f0c5 100644 --- a/docs/reference/dbSendQuery.html +++ b/docs/reference/dbSendQuery.html @@ -184,9 +184,9 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, dbSendStatement, dbWriteTable

      diff --git a/docs/reference/dbSendStatement.html b/docs/reference/dbSendStatement.html index bbd4b3ebf..e8417e2b9 100644 --- a/docs/reference/dbSendStatement.html +++ b/docs/reference/dbSendStatement.html @@ -179,10 +179,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbWriteTable

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbWriteTable

      Examples

      diff --git a/docs/reference/dbUnquoteIdentifier.html b/docs/reference/dbUnquoteIdentifier.html new file mode 100644 index 000000000..e5825b439 --- /dev/null +++ b/docs/reference/dbUnquoteIdentifier.html @@ -0,0 +1,196 @@ + + + + + + + + +Unquote identifiers — dbUnquoteIdentifier • DBI + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + +
      + +
      +
      + + + +

      Call this method to convert a SQL object created by dbQuoteIdentifier() +back to a list of Table objects. + +

      Methods in other packages

      + +

      + + +
      dbUnquoteIdentifier(conn, x, ...)
      + +

      Arguments

      + + + + + + + + + + + + + + +
      conn

      A subclass of DBIConnection, representing +an active connection to an DBMS.

      x

      An SQL or Table object or character vector, or a list of such +objects, to unquote.

      ...

      Other arguments passed on to methods.

      + +

      See also

      + +

      Other DBIResult generics: DBIResult-class, + dbBind, dbClearResult, + dbColumnInfo, dbFetch, + dbGetInfo, dbGetRowCount, + dbGetRowsAffected, + dbGetStatement, + dbHasCompleted, dbIsValid, + dbQuoteIdentifier, + dbQuoteLiteral, dbQuoteString

      + + +

      Examples

      +
      # Unquoting allows to understand the structure of a possibly complex quoted +# identifier + +dbUnquoteIdentifier( + ANSI(), + SQL(c('"Schema"."Table"', "UnqualifiedTable")) +)
      #> Error in match.fun(FUN): object 'Table' not found
      +# Character vectors are wrapped in a list +dbQuoteIdentifier( + ANSI(), + c(schema = "Schema", table = "Table") +)
      #> <SQL> "Schema" +#> <SQL> "Table"
      +# Lists of character vectors are returned unchanged +dbQuoteIdentifier( + ANSI(), + list(c(schema = "Schema", table = "Table"), "UnqualifiedTable") +)
      #> Error: x must be character or SQL
      +
      + +
      + +
      + + +
      +

      Site built with pkgdown.

      +
      + +
      +
      + + + diff --git a/docs/reference/dbWriteTable.html b/docs/reference/dbWriteTable.html index 85ec14dad..fd50b3eb9 100644 --- a/docs/reference/dbWriteTable.html +++ b/docs/reference/dbWriteTable.html @@ -109,6 +109,7 @@

      Copy data frames to database tables

      Methods in other packages

      @@ -253,10 +254,10 @@

      See a dbExecute, dbExistsTable, dbGetException, dbGetInfo, dbGetQuery, dbIsValid, - dbListFields, dbListResults, - dbListTables, dbReadTable, - dbRemoveTable, dbSendQuery, - dbSendStatement

      + dbListFields, dbListObjects, + dbListResults, dbListTables, + dbReadTable, dbRemoveTable, + dbSendQuery, dbSendStatement

      Examples

      diff --git a/docs/reference/hidden_aliases.html b/docs/reference/hidden_aliases.html index e4f626964..707687dbb 100644 --- a/docs/reference/hidden_aliases.html +++ b/docs/reference/hidden_aliases.html @@ -115,6 +115,9 @@

      Internal page for hidden aliases

      # S4 method for DBIObject dbDataType(dbObj, obj, ...) +# S4 method for Id +show(object) + # S4 method for DBIConnection show(object) @@ -134,6 +137,18 @@

      Internal page for hidden aliases

      dbReadTable(conn, name, ..., row.names = FALSE, check.names = TRUE) +# S4 method for DBIConnection,Id +dbReadTable(conn, name, ...) + +# S4 method for DBIConnection,Id +dbWriteTable(conn, name, value, ...) + +# S4 method for DBIConnection,Id +dbExistsTable(conn, name, ...) + +# S4 method for DBIConnection,Id +dbRemoveTable(conn, name, ...) + # S4 method for AnsiConnection show(object) @@ -181,6 +196,12 @@

      Internal page for hidden aliases

      # S4 method for DBIConnection,SQL dbQuoteIdentifier(conn, x, ...) +# S4 method for DBIConnection,Id +dbQuoteIdentifier(conn, x, ...) + +# S4 method for DBIConnection +dbUnquoteIdentifier(conn, x, ...) + # S4 method for DBIConnection,ANY dbQuoteString(conn, x, ...) @@ -201,12 +222,6 @@

      Internal page for hidden aliases

      sqlAppendTable(con, table, values, row.names = NA, ...) -# S4 method for Table -show(object) - -# S4 method for DBIConnection,Table -dbQuoteIdentifier(conn, x, ...) - # S4 method for DBIConnection dbWithTransaction(conn, code) @@ -223,7 +238,7 @@

      Ar object -

      Object to display

      +

      Table object to print

      object @@ -231,7 +246,7 @@

      Ar object -

      Table object to print

      +

      Object to display

      diff --git a/docs/reference/index.html b/docs/reference/index.html index 40a230bbc..8e6d0c97e 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -270,6 +270,12 @@

      dbListFields

      List field names of a remote table

      + + + +

      dbListObjects

      + +

      List remote objects

      @@ -324,6 +330,12 @@

      dbSendStatement

      Execute a data manipulation statement on a given database connection

      + + + +

      dbUnquoteIdentifier

      + +

      Unquote identifiers

      @@ -336,6 +348,12 @@

      dbWriteTable

      Copy data frames to database tables

      + + + +

      Id

      + +

      Refer to a table nested in a hierarchy (e.g. within a schema)

      @@ -378,12 +396,6 @@

      sqlInterpolate

      Safely interpolate values into an SQL string

      - - - -

      Table

      - -

      Refer to a table nested in a hierarchy (e.g. within a schema)

      From c7ee1b93dca05faaab020bb04bc6cdca5cb19add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 4 Feb 2018 08:28:49 +0000 Subject: [PATCH 29/44] Deploy from Travis build 978 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/337145538 Commit: 138c2fdc1ab0fa358416957f35a55ee7a3b9d652 --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 246ce5c01..88177aecb 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-02

      +

      2018-02-04

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 565260d5b..cbf60b16b 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-02

      +

      2018-02-04

      From 9f7beebaeba32fd98521d182a68e0596b3a9db58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Mon, 5 Feb 2018 08:30:09 +0000 Subject: [PATCH 30/44] Deploy from Travis build 979 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/337445000 Commit: c7ee1b93dca05faaab020bb04bc6cdca5cb19add --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 88177aecb..501f93922 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-04

      +

      2018-02-05

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index cbf60b16b..613b44f80 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-04

      +

      2018-02-05

      From 727083727ab8c1cc394f005b6983c2775920bade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 6 Feb 2018 08:29:17 +0000 Subject: [PATCH 31/44] Deploy from Travis build 980 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/337903656 Commit: 9f7beebaeba32fd98521d182a68e0596b3a9db58 --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index 501f93922..bf2dc6aa1 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-05

      +

      2018-02-06

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 613b44f80..2e701a57d 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-05

      +

      2018-02-06

      From f956d81d6381de2729961f1440e06c55061b4d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 7 Feb 2018 08:31:36 +0000 Subject: [PATCH 32/44] Deploy from Travis build 981 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/338381257 Commit: 727083727ab8c1cc394f005b6983c2775920bade --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index bf2dc6aa1..ff03ca00d 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-06

      +

      2018-02-07

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 2e701a57d..5d2c2c156 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-06

      +

      2018-02-07

      From 80d8b6dc43fe2a73769616ec5bfe681d2a644a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 9 Feb 2018 08:30:42 +0000 Subject: [PATCH 33/44] Deploy from Travis build 982 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/339355119 Commit: f956d81d6381de2729961f1440e06c55061b4d3b --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index ff03ca00d..e4fc02b55 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-07

      +

      2018-02-09

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index 5d2c2c156..ff5d76f85 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-07

      +

      2018-02-09

      From ba8708adbce2fb2b1db864e0b8223364db11777f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 10 Feb 2018 08:32:01 +0000 Subject: [PATCH 34/44] Deploy from Travis build 983 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/339785334 Commit: 80d8b6dc43fe2a73769616ec5bfe681d2a644a05 --- docs/articles/backend.html | 2 +- docs/articles/spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/articles/backend.html b/docs/articles/backend.html index e4fc02b55..78df9e667 100644 --- a/docs/articles/backend.html +++ b/docs/articles/backend.html @@ -77,7 +77,7 @@

      Implementing a new backend

      Hadley Wickham

      -

      2018-02-09

      +

      2018-02-10

      diff --git a/docs/articles/spec.html b/docs/articles/spec.html index ff5d76f85..b4da59279 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -77,7 +77,7 @@

      DBI specification

      Kirill Müller

      -

      2018-02-09

      +

      2018-02-10

      From d91b2a005881b09d479841c51d4c6882053e29ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 8 Feb 2018 04:31:21 +0100 Subject: [PATCH 35/44] document dbQuoteLiteral() --- man/dbQuoteLiteral.Rd | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/man/dbQuoteLiteral.Rd b/man/dbQuoteLiteral.Rd index a172bf23c..36d709f40 100644 --- a/man/dbQuoteLiteral.Rd +++ b/man/dbQuoteLiteral.Rd @@ -14,6 +14,18 @@ an active connection to an DBMS.} \item{...}{Other arguments passed on to methods.} } +\value{ +\code{dbQuoteLiteral()} returns an object that can be coerced to \link{character}, +of the same length as the input. +For an empty character vector this function returns a length-0 object. + +When passing the returned object again to \code{dbQuoteLiteral()} +as \code{x} +argument, it is returned unchanged. +Passing objects of class \link{SQL} should also return them unchanged. +(For backends it may be most convenient to return \link{SQL} objects +to achieve this behavior, but this is not required.) +} \description{ Call these methods to generate a string that is suitable for use in a query as a literal value of the correct type, to make sure that you @@ -21,6 +33,27 @@ generate valid SQL and protect against SQL injection attacks. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbQuoteLiteral")} } +\section{Specification}{ + + +The returned expression can be used in a \code{SELECT ...} query, +and the value of +\code{dbGetQuery(paste0("SELECT ", dbQuoteLiteral(x)))[[1]]} +must be equal to \code{x} +for any scalar +integer, +numeric, +string, +and logical. +If \code{x} is \code{NA}, the result must merely satisfy \code{\link[=is.na]{is.na()}}. +The literals \code{"NA"} or \code{"NULL"} are not treated specially. + +\code{NA} should be translated to an unquoted SQL \code{NULL}, +so that the query \code{SELECT * FROM (SELECT 1) a WHERE ... IS NULL} +returns one row. + +} + \examples{ # Quoting ensures that arbitrary input is safe for use in a query name <- "Robert'); DROP TABLE Students;--" From 1e3a4d62cc37bb6673ac268167cc7fda7af8ec24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 8 Feb 2018 04:40:54 +0100 Subject: [PATCH 36/44] implement default method for dbListObject() that forwards to dbListTables(), closes #223 --- NAMESPACE | 1 + R/DBConnection.R | 16 ++++++++++++++++ man/hidden_aliases.Rd | 3 +++ 3 files changed, 20 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index aefe2750e..e2de3b9b5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -76,6 +76,7 @@ exportMethods(dbExistsTable) exportMethods(dbFetch) exportMethods(dbGetQuery) exportMethods(dbListFields) +exportMethods(dbListObjects) exportMethods(dbQuoteIdentifier) exportMethods(dbQuoteLiteral) exportMethods(dbQuoteString) diff --git a/R/DBConnection.R b/R/DBConnection.R index dcea1b629..dcbb220ec 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -403,6 +403,22 @@ setGeneric("dbListObjects", valueClass = "data.frame" ) +#' @rdname hidden_aliases +#' @export +setMethod("dbListObjects", signature("DBIConnection", "ANY"), + function(conn, prefix = NULL, ...) { + names <- dbListTables(conn) + id <- SQL(dbQuoteIdentifier(conn, names)) + tables <- lapply(names, function(x) Id(table = x)) + data.frame( + table = I(unname(tables)), + id = quoted_names, + is_prefix = is_prefix, + stringsAsFactors = FALSE + ) + } +) + #' Copy data frames from database tables #' #' Reads a database table to a data frame, optionally converting diff --git a/man/hidden_aliases.Rd b/man/hidden_aliases.Rd index 9a61e9a54..eb58de0d7 100644 --- a/man/hidden_aliases.Rd +++ b/man/hidden_aliases.Rd @@ -14,6 +14,7 @@ \alias{dbGetQuery,DBIConnection,character-method} \alias{dbExecute,DBIConnection,character-method} \alias{dbListFields,DBIConnection,character-method} +\alias{dbListObjects,DBIConnection-method} \alias{dbReadTable,DBIConnection,character-method} \alias{dbReadTable,DBIConnection,Id-method} \alias{dbWriteTable,DBIConnection,Id-method} @@ -64,6 +65,8 @@ \S4method{dbListFields}{DBIConnection,character}(conn, name, ...) +\S4method{dbListObjects}{DBIConnection}(conn, prefix = NULL, ...) + \S4method{dbReadTable}{DBIConnection,character}(conn, name, ..., row.names = FALSE, check.names = TRUE) From 26806f246d71929ed815b8b9fb405ad3cf5bc2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 10 Feb 2018 09:57:20 +0100 Subject: [PATCH 37/44] remove id column --- R/DBConnection.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/R/DBConnection.R b/R/DBConnection.R index dcbb220ec..c3fcb156f 100644 --- a/R/DBConnection.R +++ b/R/DBConnection.R @@ -408,14 +408,13 @@ setGeneric("dbListObjects", setMethod("dbListObjects", signature("DBIConnection", "ANY"), function(conn, prefix = NULL, ...) { names <- dbListTables(conn) - id <- SQL(dbQuoteIdentifier(conn, names)) tables <- lapply(names, function(x) Id(table = x)) - data.frame( + ret <- data.frame( table = I(unname(tables)), - id = quoted_names, - is_prefix = is_prefix, stringsAsFactors = FALSE ) + ret$is_prefix <- rep_len(FALSE, nrow(ret)) + ret } ) From 3cd54e3326d1388ecaba64bc42ffe4f196bf3ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 10 Feb 2018 10:09:11 +0100 Subject: [PATCH 38/44] document --- man/dbListObjects.Rd | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/man/dbListObjects.Rd b/man/dbListObjects.Rd index 7551db0af..8f5ca6b2e 100644 --- a/man/dbListObjects.Rd +++ b/man/dbListObjects.Rd @@ -16,6 +16,29 @@ If given the method will return all objects accessible through this prefix.} \item{...}{Other parameters passed on to methods.} } +\value{ +\code{dbListObjects()} +returns a data frame +with columns +\code{table} and \code{is_prefix} (in that order), +optionally with other columns with a dot (\code{.}) prefix. +The \code{table} column is of type list. +Each object in this list is suitable for use as argument in \code{\link[=dbQuoteIdentifier]{dbQuoteIdentifier()}}. +The \code{is_prefix} column is a logical. +This data frame contains one row for each object (schema, table +and view) +accessible from the prefix (if passed) or from the global namespace +(if prefix is omitted). +Tables added with \code{\link[=dbWriteTable]{dbWriteTable()}} +are part of the data frame, +including temporary objects if supported by the database. +As soon a table is removed from the database, +it is also removed from the data frame of database objects. + +The returned names are suitable for quoting with \code{dbQuoteIdentifier()}. +An error is raised when calling this method for a closed +or invalid connection. +} \description{ Returns the names of remote objects accessible through this connection as a data frame. @@ -29,6 +52,16 @@ namespace. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbListObjects")} } +\section{Additional arguments}{ + + +TBD: \code{temporary = NA} + +This must be provided as named argument. +See the "Specification" section for details on their usage. + +} + \examples{ con <- dbConnect(RSQLite::SQLite(), ":memory:") From 8f2a2e9eb341a00d48467290a7587602ccd01642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 10 Feb 2018 10:09:38 +0100 Subject: [PATCH 39/44] Table -> Id --- R/quote.R | 6 +++--- man/dbQuoteIdentifier.Rd | 2 +- man/dbUnquoteIdentifier.Rd | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/R/quote.R b/R/quote.R index d4f3bceec..a04c78759 100644 --- a/R/quote.R +++ b/R/quote.R @@ -76,7 +76,7 @@ setMethod("show", "SQL", function(object) { #' #' @param conn A subclass of [DBIConnection-class], representing #' an active connection to an DBMS. -#' @param x A character vector, [SQL] or [Table] object to quote as identifier. +#' @param x A character vector, [SQL] or [Id] object to quote as identifier. #' @param ... Other arguments passed on to methods. #' #' @template methods @@ -147,11 +147,11 @@ setMethod("dbQuoteIdentifier", signature("DBIConnection", "Id"), quote_identifie #' Unquote identifiers #' #' Call this method to convert a [SQL] object created by [dbQuoteIdentifier()] -#' back to a list of [Table] objects. +#' back to a list of [Id] objects. #' #' @param conn A subclass of [DBIConnection-class], representing #' an active connection to an DBMS. -#' @param x An [SQL] or [Table] object or character vector, or a list of such +#' @param x An [SQL] or [Id] object or character vector, or a list of such #' objects, to unquote. #' @param ... Other arguments passed on to methods. #' diff --git a/man/dbQuoteIdentifier.Rd b/man/dbQuoteIdentifier.Rd index 9766976aa..360f6cc4a 100644 --- a/man/dbQuoteIdentifier.Rd +++ b/man/dbQuoteIdentifier.Rd @@ -10,7 +10,7 @@ dbQuoteIdentifier(conn, x, ...) \item{conn}{A subclass of \linkS4class{DBIConnection}, representing an active connection to an DBMS.} -\item{x}{A character vector, \link{SQL} or \link{Table} object to quote as identifier.} +\item{x}{A character vector, \link{SQL} or \link{Id} object to quote as identifier.} \item{...}{Other arguments passed on to methods.} } diff --git a/man/dbUnquoteIdentifier.Rd b/man/dbUnquoteIdentifier.Rd index 7b69a0526..04647e4aa 100644 --- a/man/dbUnquoteIdentifier.Rd +++ b/man/dbUnquoteIdentifier.Rd @@ -10,14 +10,14 @@ dbUnquoteIdentifier(conn, x, ...) \item{conn}{A subclass of \linkS4class{DBIConnection}, representing an active connection to an DBMS.} -\item{x}{An \link{SQL} or \link{Table} object or character vector, or a list of such +\item{x}{An \link{SQL} or \link{Id} object or character vector, or a list of such objects, to unquote.} \item{...}{Other arguments passed on to methods.} } \description{ Call this method to convert a \link{SQL} object created by \code{\link[=dbQuoteIdentifier]{dbQuoteIdentifier()}} -back to a list of \link{Table} objects. +back to a list of \link{Id} objects. \Sexpr[results=rd,stage=render]{DBI:::methods_as_rd("dbUnquoteIdentifier")} } From 2d42bda81330c41b7ed7abae6d0b3d3a0980d1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 10 Feb 2018 09:20:43 +0000 Subject: [PATCH 40/44] Deploy from Travis build 984 [ci skip] Build URL: https://travis-ci.org/r-dbi/DBI/builds/339793073 Commit: 8f2a2e9eb341a00d48467290a7587602ccd01642 --- docs/articles/spec.html | 2 +- docs/reference/dbListObjects.html | 48 +++++++++++++++++++++++-- docs/reference/dbQuoteIdentifier.html | 2 +- docs/reference/dbQuoteLiteral.html | 34 ++++++++++++++++++ docs/reference/dbUnquoteIdentifier.html | 4 +-- docs/reference/hidden_aliases.html | 3 ++ 6 files changed, 86 insertions(+), 7 deletions(-) diff --git a/docs/articles/spec.html b/docs/articles/spec.html index b4da59279..4a9210143 100644 --- a/docs/articles/spec.html +++ b/docs/articles/spec.html @@ -1468,7 +1468,7 @@

      -A character vector, SQL or Table object to quote as identifier. +A character vector, SQL or Id object to quote as identifier.

      diff --git a/docs/reference/dbListObjects.html b/docs/reference/dbListObjects.html index 8fe4beb7d..5c9772c16 100644 --- a/docs/reference/dbListObjects.html +++ b/docs/reference/dbListObjects.html @@ -111,7 +111,13 @@

      List remote objects

      in schemas, and returns fully qualified identifiers to access these objects. This allows exploration of all database objects available to the current user, including those that can only be accessed by giving the full -namespace.

      +namespace. + +

      Methods in other packages

      + +

      dbListObjects(conn, prefix = NULL, ...)
      @@ -136,6 +142,36 @@

      Ar +

      Value

      + +

      dbListObjects() +returns a data frame +with columns +table and is_prefix (in that order), +optionally with other columns with a dot (.) prefix. +The table column is of type list. +Each object in this list is suitable for use as argument in dbQuoteIdentifier(). +The is_prefix column is a logical. +This data frame contains one row for each object (schema, table +and view) +accessible from the prefix (if passed) or from the global namespace +(if prefix is omitted). +Tables added with dbWriteTable() +are part of the data frame, +including temporary objects if supported by the database. +As soon a table is removed from the database, +it is also removed from the data frame of database objects.

      +

      The returned names are suitable for quoting with dbQuoteIdentifier(). +An error is raised when calling this method for a closed +or invalid connection.

      + +

      Additional arguments

      + + +

      TBD: temporary = NA

      +

      This must be provided as named argument. +See the "Specification" section for details on their usage.

      +

      See also

      Other DBIConnection generics: DBIConnection-class, @@ -152,8 +188,10 @@

      See a

      Examples

      con <- dbConnect(RSQLite::SQLite(), ":memory:") -dbListObjects(con)
      #> Error in (function (classes, fdef, mtable) { methods <- .findInheritedMethods(classes, fdef, mtable) if (length(methods) == 1L) return(methods[[1L]]) else if (length(methods) == 0L) { cnames <- paste0("\"", vapply(classes, as.character, ""), "\"", collapse = ", ") stop(gettextf("unable to find an inherited method for function %s for signature %s", sQuote(fdef@generic), sQuote(cnames)), domain = NA) } else stop("Internal error in finding inherited methods; didn't return a unique method", domain = NA)})(list(structure("SQLiteConnection", package = "RSQLite")), structure(function (conn, prefix = NULL, ...) { ans <- standardGeneric("dbListObjects") .valueClassTest(ans, "data.frame", "dbListObjects") }, generic = structure("dbListObjects", package = "DBI"), package = "DBI", group = list(), valueClass = "data.frame", signature = c("conn", "prefix"), default = `\001NULL\001`, skeleton = (function (conn, prefix = NULL, ...) stop("invalid call in method dispatch to 'dbListObjects' (no default method)", domain = NA))(conn, prefix, ...), class = structure("standardGeneric", package = "methods")), <environment>): unable to find an inherited method for function ‘dbListObjects’ for signature ‘"SQLiteConnection"’
      dbWriteTable(con, "mtcars", mtcars) -dbListObjects(con)
      #> Error in (function (classes, fdef, mtable) { methods <- .findInheritedMethods(classes, fdef, mtable) if (length(methods) == 1L) return(methods[[1L]]) else if (length(methods) == 0L) { cnames <- paste0("\"", vapply(classes, as.character, ""), "\"", collapse = ", ") stop(gettextf("unable to find an inherited method for function %s for signature %s", sQuote(fdef@generic), sQuote(cnames)), domain = NA) } else stop("Internal error in finding inherited methods; didn't return a unique method", domain = NA)})(list(structure("SQLiteConnection", package = "RSQLite")), structure(function (conn, prefix = NULL, ...) { ans <- standardGeneric("dbListObjects") .valueClassTest(ans, "data.frame", "dbListObjects") }, generic = structure("dbListObjects", package = "DBI"), package = "DBI", group = list(), valueClass = "data.frame", signature = c("conn", "prefix"), default = `\001NULL\001`, skeleton = (function (conn, prefix = NULL, ...) stop("invalid call in method dispatch to 'dbListObjects' (no default method)", domain = NA))(conn, prefix, ...), class = structure("standardGeneric", package = "methods")), <environment>): unable to find an inherited method for function ‘dbListObjects’ for signature ‘"SQLiteConnection"’
      +dbListObjects(con)
      #> [1] table is_prefix +#> <0 rows> (or 0-length row.names)
      dbWriteTable(con, "mtcars", mtcars) +dbListObjects(con)
      #> table is_prefix +#> 1 <Table> table = mtcars FALSE