Qore Programming Language
1.7.2
|
To write a DBI driver, you have to provide implementations for the following functions supporting the Datasource class (listed by their function signatures):
For databases where transactions must be started explicitly (for example, with a "begin transaction" statement), the following two functions should be implemented (and must not be implemented for databases where transactions are started implicitly):
The following functions are always optional:
More detail about each function is provided in the following sections.
These functions must be registered in the DBI subsystem by populating a qore_dbi_method_list structure with pointers to the methods and then calling DBIDriverList::registerDriver() on the DBI object. This should be done in the module_init()
function as in the following example from the mysql driver:
Function signature: q_dbi_open_t
This method will be called whenever the connection to the database must be opened. The connection parameters can be queried from the Datasource argument as follows:
If Datasource::getDBEncoding() returns 0, then the character encoding for the connection should be set based on QCS_DEFAULT.
Here is a connection example from the sybase driver:
If the connection is successfully established, then Datasource::setPrivateData() should be called to save the connection state and 0 should be returned. This state will lated be retrieved in each DBI method with Datasource::getPrivateData().
If a connection cannot be established, then -1 should be returned and a Qore-language exception should be added to the ExceptionSink object.
Qore DBI drivers must initialize each connection manually to use transaction isolation level "read committed" if necessary when opening the connection. For example the mysql driver does this for each connection as follows after opening a connection:
Function signature: q_dbi_close_t
This method should unconditionally close the connection to the database. There is currently no facility for registering errors when closing a connection; the return value for this function is currently ignored.
This function must clear the private data structure by calling Datasource::setPrivateData() with the argument 0. The private data structure should also be deleted here.
Here is the implementation of this function in the sybase driver:
Function signature: q_dbi_select_t
This function must be capable of executing an SQL select against an open connection and returning the result as a QoreHashNode (the columns) of QoreListNode objects (the rows). This is the minimum requirement for this function, but some Qore DBI drivers use the same implementation for this and the DBI Exec Method exec method. It depends on the database's API if it's possible or not. Some database API's have a different functions for each operation.
Note that the SQL string passed as an argument may not be in the encoding required by the connection. It is the resposibility of this function to convert the string to the proper encoding before passing it to the database's API for execution.
Furthermore, DBI placeholders and bind specifications must be processed as well before executing the query. The following DBI-specific format codes can appear in the query string:
v
means bind the corresponding argument by value
:name means "name"
is an output parameter and should be returned as an output value in an output hash (only valid for DBI Exec Method exec)s
means include the string directly in the query as-is without any escaping (useful for table or database name prefixes)d
means interpret the corresponding argument as a number (either integer or float, depending on the type of the argument) and include directly in the stringIf an Qore-language exceptions are thrown due to errors while processing the select request, 0 must be returned.
Function signature: q_dbi_select_rows_t
This function is the same as the select method, except that a QoreListNode (the rows) of QoreHashNode objects (the columns) should be returned.
This format is less efficient than the QoreHashNode or QoreListNode objects, but is easier to work with in some circumstances by Qore code.
Function signature: q_dbi_exec_t
This function is designed for executing insert
or update
statements or for executing stored procedures, functions, or other database code. The same rules about placeholders and bind specifications apply as documented in the select method.
For insert
and update
statements, the number of affected rows should be returned as an integer.
For all other statements, a data structure appropriate to the action executed should be returned.
Function signature: q_dbi_commit_t
This function should commit any open transaction in the database.
Here is an example from the mysql driver (simplified for the example):
Function signature: q_dbi_rollback_t
This function should roll back any open transaction in the database.
Here is an example from the mysql driver (simplified for the example):
Function signature: q_dbi_begin_transaction_t
This function should only be implemented for datasources that require an explicit "begin transaction" statement to begin a transaction (such as the pgsql driver).
Here is an example from the pgsql driver:
"This is not implemented in Qore in 0.9"
Function signature: q_dbi_abort_transaction_start_t
This function is required for datasources that implement the begin_transaction method, and if an error occurs as the first statement of after the begin_transaction method is implictly executed, a rollback call must immediately be made in order to continue to use the connection.
This method is implemented for the pgsql driver by aliasing it to the rollback function, for example.
Function signature: q_dbi_get_server_version_t
This function should return version information for the database server. As such it requires an active connection (which will be established by the Qore library before this function is called).
There is no pre-defined format for the output of this function. Here is the implementation of this method for the oracle driver:
Function signature: q_dbi_get_client_version_t
This function should return version information for the database client library in use, and therefore does not require an open connection to the database.
Like the get_server_version method, there is no pre-defined format for the output of this function. Here is the implementation of this method for the oracle driver: