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. In fact, this document is derived from comments in the test definitions of the DBItest package. This ensures that an extension or update to the tests will be reflected in this document.
DBIDriver
class.
This section describes the construction of, and the methods defined for,
this driver class. Construction
The backend must support creation of an instance of this driver class
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.
For the automated tests, the constructor name can be tweaked using the
constructor_name
tweak. The constructor must be exported, and
it must be a function
that is callable without arguments.
For the automated tests, unless the
constructor_relax_args
tweak is set to TRUE
,
an empty argument list is expected.
Otherwise, an argument list where all arguments have default values
is also accepted. dbDataType("DBIDriver", "ANY")
The backend can override the DBI::dbDataType()
generic
for its driver class.
This generic expects an arbitrary object as second argument
and returns a corresponding SQL type
as atomic
character value
with at least one character.
As-is objects (i.e., wrapped by base::I()
) must be
supported and return the same results as their unwrapped counterparts. 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
base::logical()
,
base::integer()
,
base::numeric()
,
base::character()
,
dates (see base::Dates()
),
date-time (see base::DateTimeClasses()
),
and base::difftime()
.
It also must accept lists of raw
vectors
and map them to the BLOB (binary large object) data type.
The behavior for other object types is not specified. DBI::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:
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
DBI::dbSendQuery()
or DBI::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 DBI::dbClearResult()
via
on.exit()
right after calling dbSendQuery()
, see the last
enumeration item.
data.frame()
is internally stored as such
a list.
The parameter list is passed a call to dbBind()
on the DBIResult
object.
DBIResult
object.
dbSendQuery()
,
call DBI::dbFetch()
.
dbSendStatements()
,
call DBI::dbGetRowsAffected()
.
(Execution begins immediately after the dbBind()
call,
the statement is processed entirely before the function returns.
Calls to dbFetch()
are ignored.)
DBI::dbClearResult()
.
dbBegin("DBIConnection")
and dbCommit("DBIConnection")
Transactions are available in DBI, but actual support may vary between backends.
A transaction is initiated by a call to DBI::dbBegin()
and committed by a call to DBI::dbCommit()
.
Both generics expect an object of class DBIConnection
and return TRUE
(invisibly) upon success. The implementations are expected to raise an error in case of failure,
but this is difficult to test in an automated way.
In any way, both generics should throw an error with a closed connection.
In addition, a call to DBI::dbCommit()
without
a call to DBI::dbBegin()
should raise an error.
Nested transactions are not supported by DBI,
an attempt to call DBI::dbBegin()
twice
should yield an error. Data written in a transaction must persist after the transaction is committed.
For example, a table that is missing when the transaction is started
but is created
and populated during the transaction
must exist and contain the data added there
both during
and after the transaction. The behavior is not specified if other arguments are passed to these
functions. In particular, RSQLite issues named transactions
if the name
argument is set. The transaction isolation level is not specified by DBI.