1
0
mirror of https://github.com/php/php-src.git synced 2026-04-27 18:23:26 +02:00
Files
archived-php-src/ext/pdo/specs/drivers/connect.xml
T
2007-11-27 19:33:10 +00:00

267 lines
8.6 KiB
XML

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<section id="drivers.connect.instantiation">
<title>Connection Establishment</title>
<para>
When a database connection is to be established, the PDO core will
create an instance of <type>pdo_dbh_t</type> and initialize it.
The factory method will then be invoked, which is responsible for
performing driver specific initialization, connecting to the underlying
data source and communicating certain database characteristics back to
the PDO core.
</para>
<section id="drivers.connect.inputs">
<title>Factory method inputs</title>
<para>
The PDO core initializes various pieces of a <type>pdo_dbh_t</type>
(we'll refer to it as <varname>dbh</varname> from now on). The
portions of the structure that are relevant as inputs to the factory
method are:
</para>
<programlisting role="C"><![CDATA[
struct _pdo_dbh_t {
/* credentials */
char *username, *password;
/* data source string used to open this handle */
const char *data_source;
unsigned long data_source_len;
/* if true, then data stored and pointed at by this handle must all be
* persistently allocated */
unsigned is_persistent:1;
/* if true, driver should act as though a COMMIT were executed between
* each executed statement; otherwise, COMMIT must be carried out manually
* */
unsigned auto_commit:1;
};
]]></programlisting>
<variablelist>
<varlistentry>
<term>username</term>
<term>password</term>
<term>data_source</term>
<term>data_source_len</term>
<listitem>
<para>
These fields describe the data source to which to connect, and the
credentials that should be used.
<structfield>username</structfield> and/or
<structfield>password</structfield> may be <literal>NULL</literal>
if they were not passed to the constructor. In this case, the
driver may then take credentials from the
<structfield>data_source</structfield> string.
</para>
<para>
The <structfield>data_source</structfield> is defined as a string
prefixed by a driver name and a colon, but is otherwise left
entirely to a driver to interpret. For instance, and ODBC driver
could define the data source string as a prefixed version of the
underlying ODBC data source name and pass
<structfield>data_source</structfield> directly to the ODBC API
calls needed for connection establishment.
</para>
<para>
If the underlying database client library doesn't have its own
concept of encoding the connection parameters in a data source
string, a driver may find it convenient to use
<function>php_pdo_parse_data_source</function> to parse defined
connection parameters out of the
<structfield>data_source</structfield> string.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>is_persistent</term>
<listitem>
<para>
PHP has a memory manager that can be used for per-request memory
or for memory that persists beyond the scope of a request. If
creating a persistent connection,
<structfield>is_persistent</structfield> will be set to 1
indicating that all state associated with the
<varname>dbh</varname> must be allocated using a persistent
allocator.
</para>
<para>
In practice, drivers will simply call
<function>pemalloc</function> or <function>pefree</function> and
pass in <structfield>is_persistent</structfield>, and be able to
satisfy this requirement.
</para>
<para>
Failure to observe this requirement can lead to memory leaks or
crashes. If a driver cannot operate correctly when
<structfield>is_persistent</structfield> is set, then it should
raise an error as described below.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>auto_commit</term>
<listitem>
<para>
When set to 1, the driver must act as though an implicit commit
were executed after each successfully executed statement.
</para>
<para>
When set to 0, the driver should implicitly start a transaction.
</para>
<para>
If the underlying data source does not support transactions and
auto-commit is disabled, the driver must raise an error, as
described below.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
In addition to the <varname>dbh</varname>, the factory method is also
passed a PHP <type>zval</type> pointer that may be NULL. If it is not
NULL, it will reference a PHP array type keyed by integer attribute
identifiers. The driver should use <function>pdo_attr_lval</function>
and/or <function>pdo_attr_strval</function> to determine if any
parameters that affect how it will establish the connection are present.
</para>
<para>
The PDO core will iterate all the options and inform the driver of them
immediately after the connection has been successfully established, so
the factory method should only process those parameters that are needed to
establish the connection.
</para>
</section>
<section id="drivers.connect.outputs">
<title>Factory method outputs</title>
<para>
The primary purpose of the factory method is to establish a connection
to a data source. It must also set certain fields of the
<varname>dbh</varname> so that the PDO core knows how best to interact
with it.
</para>
<para>
The portions of the <varname>dbh</varname> that are relevant as outputs
of the factory method are:
</para>
<programlisting role="C"><![CDATA[
struct _pdo_dbh_t {
/* driver specific methods */
struct pdo_dbh_methods *methods;
/* driver specific data */
void *driver_data;
/* if true, the driver requires that memory be allocated explicitly for
* the columns that are returned */
unsigned alloc_own_columns:1;
/* max length a single character can become after correct quoting */
unsigned max_escaped_char_length:3;
};
]]></programlisting>
<variablelist>
<varlistentry>
<term>methods</term>
<listitem>
<para>
This field <emphasis>must</emphasis> be set by the factory method
before it returns, even if the connection attempt failed. This
allows the core to correctly interrogate the connection handle if
an error occurs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>driver_data</term>
<listitem>
<para>
The driver_data field can be used by the driver to store an
arbitrary pointer to some state. This is typically a structure
that holds the connection context used by the underlying database
client library and any other additional state needed by the
driver.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>alloc_own_columns</term>
<listitem>
<para>
When set to 1, indicates the driver needs to pre-allocate memory
to hold the data for a result set. In this case, the PDO core
will trigger a describe immediately after executing a statement
for the first time. Otherwise, the describe occurs just-in-time.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>max_escaped_char_length</term>
<listitem>
<para>
This is used by the query rewriter to size buffers when quoting
parameters. If the driver supports parameter binding, then this
field is unused. If left at its default value of 0, the query
rewriter will assume 3 bytes per quoted character.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="drivers.connect.return">
<title>Factory method return value</title>
<para>
On success, the <structfield>methods</structfield> and
<structfield>driver_data</structfield> fields of <varname>dbh</varname>
must be set to non-NULL values. The other fields described above should
be set as appropriate. The factory method must return 1 to indicate
success.
</para>
<para>
On failure, the <structfield>methods</structfield> field of
<varname>dbh</varname> must be set to a non-NULL value, The other fields
described above may have been modified by the driver. The PDO core will
free all resources by calling the <structfield>closer</structfield>
method provided by the driver. The driver must trigger an exception and
return 0 to indicate failure.
</para>
<para>
The connection failure case might look something like this:
</para>
<programlisting role="C"><![CDATA[
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
"SQLSTATE[%s] connection failed", sqlstate);
return 0;
]]></programlisting>
<note>
<para>
Implementation bug: the intention was for the exception thrown during
connection errors to behave identically to the way it behaves after a
successful connect, in that it should have an errorInfo property as
described elsewhere. However, there is no exported convenience API for
this purpose, and so no drivers do this.
</para>
</note>
</section>
</section>
<!--
vim:ts=2:sw=2:et:tw=78:
-->