17 changed files with 1596 additions and 0 deletions
-
51ext/pdo/specs/Makefile.in
-
8ext/pdo/specs/README
-
49ext/pdo/specs/book.xml.in
-
BINext/pdo/specs/build/docbook-xml-4.4.tgz
-
BINext/pdo/specs/build/docbook-xsl-1.69.1.tgz
-
39ext/pdo/specs/build/html-big.xsl
-
39ext/pdo/specs/build/html.xsl
-
70ext/pdo/specs/configure.in
-
114ext/pdo/specs/drivers/all.xml
-
18ext/pdo/specs/drivers/binding.xml
-
266ext/pdo/specs/drivers/connect.xml
-
285ext/pdo/specs/drivers/dbh_methods.xml
-
182ext/pdo/specs/drivers/prepare.xml
-
256ext/pdo/specs/drivers/stmt_methods.xml
-
162ext/pdo/specs/overview.xml
-
44ext/pdo/specs/preface.xml
-
13ext/pdo/specs/userspace/all.xml
@ -0,0 +1,51 @@ |
|||
# vim:ts=2:sw=2:noet:
|
|||
XSLTPROC=@XSLTPROC@ --nonet |
|||
HERE=@HERE@ |
|||
TAR=@TAR@ |
|||
SED=@SED@ |
|||
BASH=@BASH@ |
|||
AWK=@AWK@ |
|||
BUILDDIR=@srcdir@/build |
|||
GMAKE=@GMAKE@ |
|||
BITS=$(BUILDDIR)/bits |
|||
|
|||
.PHONY: book.xml.in |
|||
|
|||
XML_CATALOG_FILES=$(BUILDDIR)/docbook-xsl/catalog.xml $(BUILDDIR)/docbook-xml/catalog.xml |
|||
SGML_CATALOG_FILES=$(XML_CATALOG_FILES) |
|||
export XML_CATALOG_FILES FOP SGML_CATALOG_FILES SED TAR |
|||
|
|||
all: docbook-env book.xml html |
|||
|
|||
docbook-env: $(BUILDDIR)/docbook-xsl $(BUILDDIR)/docbook-xml $(BUILDDIR)/bits |
|||
|
|||
$(BUILDDIR)/bits: |
|||
mkdir $(BUILDDIR)/bits |
|||
|
|||
# need to touch the dir because the timestamp in the tarball
|
|||
# is older than that of the tarball :)
|
|||
build/docbook-xsl: $(BUILDDIR)/docbook-xsl-1.69.1.tgz |
|||
cd $(BUILDDIR) && $(TAR) xzf docbook-xsl-1.69.1.tgz && touch docbook-xsl |
|||
|
|||
build/docbook-xml: $(BUILDDIR)/docbook-xml-4.4.tgz |
|||
cd $(BUILDDIR) && $(TAR) xzf docbook-xml-4.4.tgz && touch docbook-xml |
|||
|
|||
clean: |
|||
-rm *.fo html/*.html book.xml |
|||
|
|||
# Build the docs in HTML format
|
|||
html: html/index.html html/big.html |
|||
|
|||
html/big.html: book.xml |
|||
$(XSLTPROC) --xinclude --output html/big.html $(BUILDDIR)/html-big.xsl book.xml |
|||
|
|||
html/index.html: book.xml |
|||
$(XSLTPROC) --xinclude --output html/index.html $(BUILDDIR)/html.xsl book.xml |
|||
|
|||
check: book.xml |
|||
xmllint --xinclude --nonet --noout --postvalid book.xml |
|||
|
|||
book.xml: $(BUILDDIR)/docbook-xsl $(BUILDDIR)/docbook-xml book.xml.in |
|||
sed -e "s/@PUBDATE@/`date`/g;" < book.xml.in > $(BITS)/book.xml |
|||
$(XSLTPROC) --output book.xml $(BUILDDIR)/docbook-xsl/profiling/profile.xsl $(BITS)/book.xml |
|||
|
|||
@ -1,3 +1,11 @@ |
|||
Work on the PDO specification to live here |
|||
|
|||
How to build: |
|||
|
|||
You need some unixy tools, including libxml2 (which provides xsltproc), make |
|||
and autoconf. |
|||
|
|||
% autoconf |
|||
% ./configure |
|||
% make |
|||
|
|||
@ -0,0 +1,49 @@ |
|||
<?xml version='1.0' encoding='UTF-8' ?> |
|||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" |
|||
> |
|||
<book id="skel" lang="en" |
|||
xmlns:xi="http://www.w3.org/2001/XInclude" |
|||
> |
|||
|
|||
<bookinfo> |
|||
<title>PDO Specification</title> |
|||
<!-- subtitle></subtitle --> |
|||
<edition>Version 1</edition> |
|||
<pubdate>@PUBDATE@</pubdate> |
|||
|
|||
<author> |
|||
<firstname>Wez</firstname> |
|||
<surname>Furlong</surname> |
|||
<affiliation> |
|||
<jobtitle>Lead Architect</jobtitle> |
|||
<orgname>OmniTI Computer Consulting, Inc.</orgname> |
|||
</affiliation> |
|||
</author> |
|||
|
|||
<copyright> |
|||
<year>2004</year> |
|||
<year>2005</year> |
|||
<year>2006</year> |
|||
<year>2007</year> |
|||
<holder>Wez Furlong</holder> |
|||
</copyright> |
|||
<copyright> |
|||
<year>2005</year> |
|||
<year>2006</year> |
|||
<year>2007</year> |
|||
<holder>OmniTI, Inc.</holder> |
|||
</copyright> |
|||
|
|||
</bookinfo> |
|||
|
|||
<xi:include href="preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="drivers/all.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="userspace/all.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
|
|||
<index id="the.index"/> |
|||
</book> |
|||
<!-- |
|||
vim:ts=2:sw=2:et: |
|||
--> |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
|||
xmlns:fo="http://www.w3.org/1999/XSL/Format" |
|||
version="1.0"> |
|||
|
|||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/onechunk.xsl"/> |
|||
<xsl:param name="use.extensions">0</xsl:param> |
|||
<xsl:param name="use.id.as.filename">0</xsl:param> |
|||
<xsl:param name="root.filename">big</xsl:param> |
|||
<xsl:param name="base.dir">./</xsl:param> |
|||
<xsl:param name="chunk.fast">1</xsl:param> |
|||
<xsl:param name="make.valid.html">1</xsl:param> |
|||
<xsl:param name="section.autolabel">1</xsl:param> |
|||
<xsl:param name="generate.index">1</xsl:param> |
|||
<xsl:param name="section.label.includes.component.label">1</xsl:param> |
|||
<xsl:param name="chunker.output.indent">yes</xsl:param> |
|||
<xsl:param name="chunker.output.encoding">UTF-8</xsl:param> |
|||
<xsl:param name="chunk.first.sections">0</xsl:param> |
|||
<xsl:param name="chunk.tocs.and.lots">0</xsl:param> |
|||
<xsl:param name="html.extra.head.links">1</xsl:param> |
|||
<xsl:param name="generate.manifest">0</xsl:param> |
|||
<xsl:param name="admon.graphics">0</xsl:param> |
|||
<xsl:param name="admon.style"></xsl:param> |
|||
<xsl:param name="html.stylesheet">/docbook/style.css</xsl:param> |
|||
<xsl:param name="header.rule">0</xsl:param> |
|||
<xsl:param name="footer.rule">0</xsl:param> |
|||
<xsl:param name="funcsynopsis.style">ansi</xsl:param> |
|||
<xsl:param name="callout.graphics.path">/docbook/images/callouts/</xsl:param> |
|||
<xsl:param name="admon.graphics.path">/docbook/images/</xsl:param> |
|||
|
|||
|
|||
|
|||
<xsl:template match="sect1[@role = 'NotInToc']" mode="toc" /> |
|||
<xsl:template match="sect2[@role = 'NotInToc']" mode="toc" /> |
|||
|
|||
</xsl:stylesheet> |
|||
<!-- |
|||
vim:ts=2:sw=2:et: |
|||
--> |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
|||
xmlns:fo="http://www.w3.org/1999/XSL/Format" |
|||
version="1.0"> |
|||
|
|||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/> |
|||
<!-- xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/profile-chunk.xsl"/ --> |
|||
<xsl:param name="use.extensions">0</xsl:param> |
|||
<xsl:param name="use.id.as.filename">1</xsl:param> |
|||
<xsl:param name="base.dir">./</xsl:param> |
|||
<xsl:param name="chunk.fast">1</xsl:param> |
|||
<xsl:param name="make.valid.html">1</xsl:param> |
|||
<xsl:param name="section.autolabel">1</xsl:param> |
|||
<xsl:param name="generate.index">1</xsl:param> |
|||
<xsl:param name="section.label.includes.component.label">1</xsl:param> |
|||
<xsl:param name="chunker.output.indent">yes</xsl:param> |
|||
<xsl:param name="chunker.output.encoding">UTF-8</xsl:param> |
|||
<xsl:param name="chunk.first.sections">0</xsl:param> |
|||
<xsl:param name="chunk.tocs.and.lots">0</xsl:param> |
|||
<xsl:param name="html.extra.head.links">0</xsl:param> |
|||
<xsl:param name="generate.manifest">0</xsl:param> |
|||
<xsl:param name="admon.graphics">0</xsl:param> |
|||
<xsl:param name="admon.style"></xsl:param> |
|||
<xsl:param name="html.stylesheet">/docbook/style.css</xsl:param> |
|||
<xsl:param name="header.rule">0</xsl:param> |
|||
<xsl:param name="footer.rule">0</xsl:param> |
|||
<xsl:param name="toc.section.depth">1</xsl:param> |
|||
<xsl:param name="funcsynopsis.style">ansi</xsl:param> |
|||
<xsl:param name="callout.graphics.path">/docbook/images/callouts/</xsl:param> |
|||
<xsl:param name="admon.graphics.path">/docbook/images/</xsl:param> |
|||
|
|||
|
|||
<xsl:template match="sect1[@role = 'NotInToc']" mode="toc" /> |
|||
<xsl:template match="sect2[@role = 'NotInToc']" mode="toc" /> |
|||
|
|||
</xsl:stylesheet> |
|||
<!-- |
|||
vim:ts=2:sw=2:et: |
|||
--> |
|||
@ -0,0 +1,70 @@ |
|||
dnl vim:ts=2:sw=2:et: |
|||
AC_INIT(Makefile.in) |
|||
|
|||
XSLTPROC=xsltproc |
|||
GTAR=gtar |
|||
TAR=tar |
|||
SED=sed |
|||
GSED=gsed |
|||
BASH=bash |
|||
AWK=awk |
|||
|
|||
AC_PATH_PROG(AWK, $AWK) |
|||
AC_PATH_PROG(GAWK, gawk) |
|||
AC_PATH_PROG(NAWK, nawk) |
|||
AC_PATH_PROG(GTAR, $GTAR) |
|||
AC_PATH_PROG(GSED, $GSED) |
|||
AC_PATH_PROG(BASH, $BASH) |
|||
|
|||
AC_ARG_WITH(xsltproc, [ --with-xsltproc Where to find xsltproc], |
|||
[ |
|||
if test "x$withval" != "xno"; then |
|||
XSLTPROC="$withval" |
|||
fi |
|||
] |
|||
) |
|||
AC_PATH_PROG(XSLTPROC, $XSLTPROC) |
|||
|
|||
if test -x "$GTAR" ; then |
|||
TAR=$GTAR |
|||
fi |
|||
if test -x "$GSED" ; then |
|||
SED=$GSED |
|||
fi |
|||
if test -x "$GAWK" ; then |
|||
AWK=$GAWK |
|||
else |
|||
if test -x "$NAWK" ; then |
|||
AWK=$NAWK |
|||
fi |
|||
fi |
|||
|
|||
GMAKE=make |
|||
case `uname -s` in |
|||
SunOS) |
|||
GMAKE=gmake |
|||
;; |
|||
esac |
|||
AC_SUBST(GMAKE) |
|||
|
|||
AC_SUBST(TAR) |
|||
AC_SUBST(SED) |
|||
AC_SUBST(BASH) |
|||
AC_SUBST(AWK) |
|||
|
|||
AC_SUBST(XINC) |
|||
AC_SUBST(XEP) |
|||
AC_SUBST(FOP) |
|||
AC_SUBST(XSLTPROC) |
|||
AC_SUBST(DBDOCLET) |
|||
HERE=`pwd` |
|||
AC_SUBST(HERE) |
|||
AC_OUTPUT(Makefile) |
|||
|
|||
cat > config.nice <<EOT |
|||
#!/bin/sh |
|||
./configure \ |
|||
--with-xsltproc='$XSLTPROC' |
|||
EOT |
|||
chmod +x config.nice |
|||
|
|||
@ -0,0 +1,114 @@ |
|||
<?xml version='1.0' encoding='UTF-8' ?> |
|||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|||
|
|||
<chapter id="drivers"> |
|||
<title>Driver Documentation</title> |
|||
|
|||
<para> |
|||
Any PHP extension that is linked against the PDO core module can elect to |
|||
register a PDO driver. A PDO driver is represented by the |
|||
<type>pdo_driver_t</type> type which describes the version of PDO against |
|||
which the driver was built, the name of the driver and a factory method |
|||
that can be used to instantiate a database connection handle. A |
|||
connection handle is represented by the <type>pdo_dbh_t</type> type which |
|||
describes, among other things, how to instantiate a prepared statement |
|||
handle, represented by the <type>pdo_stmt_t</type> type. |
|||
</para> |
|||
|
|||
<para> |
|||
These three types are the main interface between the PDO core and a PDO |
|||
driver. In this chapter, we'll refer to an imaginary skeleton driver, and |
|||
use <literal>SKEL</literal> as a placeholder for its various functions or |
|||
types. In practice, a given database vendor will typically choose to use |
|||
a short, lowercase, version of the name of their database or client |
|||
library in place of <literal>SKEL</literal>. |
|||
</para> |
|||
|
|||
<section id="drivers.registration"> |
|||
<title>Driver Registration</title> |
|||
|
|||
<para> |
|||
A driver extension will typically statically define an instance of |
|||
<type>pdo_driver_t</type> and pass the address of it to |
|||
<function>php_pdo_register_driver</function> during its module |
|||
initialization callback (also known as MINIT, for module init), and |
|||
again to <function>php_pdo_unregister_driver</function> during its |
|||
module shutdown callback (also known as MSHUTDOWN). |
|||
</para> |
|||
|
|||
<para> |
|||
<filename>php_pdo_driver.h</filename> defines <type>pdo_driver_t</type>, |
|||
<function>php_pdo_register_driver</function> and |
|||
<function>php_pdo_unregister_driver</function> as follows: |
|||
</para> |
|||
|
|||
<programlisting role="C"><![CDATA[ |
|||
/* This structure is registered with PDO when a PDO driver extension is |
|||
* initialized */ |
|||
typedef struct { |
|||
const char *driver_name; |
|||
unsigned long driver_name_len; |
|||
unsigned long api_version; /* needs to be compatible with PDO */ |
|||
|
|||
#define PDO_DRIVER_HEADER(name) \ |
|||
#name, sizeof(#name)-1, \ |
|||
PDO_DRIVER_API |
|||
|
|||
/* create driver specific portion of the database handle and stash it into |
|||
* the dbh. dbh contains the data source string and flags for this |
|||
* instance. You MUST respect dbh->is_persistent and pass that flag to |
|||
* pemalloc() for all allocations that are stored in the dbh or your instance |
|||
* data in the db, otherwise you will crash PHP when persistent connections |
|||
* are used. |
|||
*/ |
|||
int (*db_handle_factory)(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC); |
|||
} pdo_driver_t; |
|||
|
|||
/* call this in MINIT to register your PDO driver */ |
|||
PDO_API int php_pdo_register_driver(pdo_driver_t *driver); |
|||
/* call this in MSHUTDOWN to unregister your PDO driver */ |
|||
PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver); |
|||
]]></programlisting> |
|||
|
|||
<para> |
|||
A driver would typically use code like the following to register a |
|||
driver: |
|||
</para> |
|||
|
|||
<programlisting role="C"><![CDATA[ |
|||
static pdo_driver_t SKEL_driver = { |
|||
PDO_DRIVER_HEADER(SKEL), |
|||
SKEL_db_handle_factory |
|||
}; |
|||
|
|||
PHP_MINIT_FUNCTION(pdo_SKEL) |
|||
{ |
|||
return php_pdo_register_driver(&SKEL_driver); |
|||
} |
|||
|
|||
PHP_MSHUTDOWN_FUNCTION(pdo_SKEL) |
|||
{ |
|||
php_pdo_unregister_driver(&SKEL_driver); |
|||
return SUCCESS; |
|||
} |
|||
]]></programlisting> |
|||
|
|||
<para> |
|||
The <function>SKEL_db_handle_factory</function> is provided by the |
|||
driver; its operation will be discussed in the next section. |
|||
</para> |
|||
</section> |
|||
|
|||
<xi:include href="connect.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="dbh_methods.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="prepare.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="binding.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
<xi:include href="stmt_methods.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> |
|||
|
|||
</chapter> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:tw=78: |
|||
--> |
|||
|
|||
@ -0,0 +1,18 @@ |
|||
<?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.stmt.binding"> |
|||
<title>Parameter Binding</title> |
|||
|
|||
<para> |
|||
This section describes the parameter (and column) binding interface in PDO. |
|||
|
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:tw=78: |
|||
--> |
|||
|
|||
@ -0,0 +1,266 @@ |
|||
<?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: |
|||
--> |
|||
|
|||
@ -0,0 +1,285 @@ |
|||
<?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.dbh.methods"> |
|||
<title>Database Handle Methods</title> |
|||
|
|||
<para> |
|||
The <structname>pdo_dbh_methods</structname> structure defines the methods |
|||
for a given database connection handle. The methods are defined below; |
|||
each one is subject to the following error handling protocol: |
|||
</para> |
|||
|
|||
<section id="dbh.error.protocol"> |
|||
<title>Error handling protocol</title> |
|||
|
|||
<para> |
|||
When a driver encounters an error, it must update the |
|||
<structfield>error_code</structfield> field of the |
|||
<varname>dbh</varname> to hold an appropriate SQLSTATE error code, and |
|||
take some action to record the driver specific error code and human |
|||
readable message, if necessary. |
|||
</para> |
|||
<para> |
|||
The method descriptions below describe how to indicate an error |
|||
status. The PDO core may invoke the |
|||
<function>SKEL_fetch_error_func</function> to obtain the driver |
|||
specific error code and human readable message. |
|||
</para> |
|||
<para> |
|||
The driver should not unilaterally raise an exception in reponse to an |
|||
error. Instead, it should be left to the PDO core to handle reporting |
|||
the error to the script, based on the application preferences for |
|||
error handling. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
<section id="dbh.close_func"> |
|||
<title>SKEL_close_func</title> |
|||
|
|||
<synopsis>int SKEL_close_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function is called by the PDO core when freeing resources |
|||
associated with the <varname>dbh</varname>. It should release any |
|||
resources allocated by the driver. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 0. An implementation bug means that the return value is not |
|||
checked. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.prepare_func"> |
|||
<title>SKEL_prepare_func</title> |
|||
|
|||
<synopsis>int SKEL_prepare_func(pdo_dbh_t *dbh, const char *sql, |
|||
long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function is called when creating a statement handle. It is |
|||
described in more detail in <xref |
|||
linkend="drivers.stmt.prepare"/>. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 on success, 0 on failure. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.do_func"> |
|||
<title>SKEL_do_func</title> |
|||
|
|||
<synopsis>int SKEL_do_func(pdo_dbh_t *dbh, const char *sql, |
|||
long sql_len TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Execute a statement that does not return a result set. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns -1 on failure, or the number of affected rows otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.quote_func"> |
|||
<title>SKEL_quote_func</title> |
|||
|
|||
<synopsis>int SKEL_quote_func(pdo_dbh_t *dbh, const char *unquoted, |
|||
int unquoted_len, char **quoted, int *quotedlen, |
|||
enum pdo_param_type paramtype TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Quote a parameter, escaping SQL meta-characters as appropriate and |
|||
enclosing the parameter in appropriate quotation marks. This function |
|||
will allocate an appropriately sized buffer using |
|||
<function>emalloc</function> and return it to the caller by setting |
|||
<parameter>quoted</parameter> and <parameter>quotedlen</parameter> to |
|||
the buffer and its length. |
|||
</para> |
|||
|
|||
<para> |
|||
The return value should be 1 if the function generated a quoted |
|||
string, or 0 otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.begin_func"> |
|||
<title>SKEL_begin_func</title> |
|||
|
|||
<synopsis>int SKEL_begin_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function begins a transaction on the connection. If the driver |
|||
does not support transactions, it should not provide this method. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 to indicate that a new transaction has begun, 0 to indicate |
|||
error. The PDO core maintains its own idea of whether a transaction |
|||
is in progress, so the driver should not maintain its own. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.commit_func"> |
|||
<title>SKEL_commit_func</title> |
|||
|
|||
<synopsis>int SKEL_commit_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function commits a transaction on the connection. If the driver |
|||
does not support transactions, it should not provide this method. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 to indicate that the transaction was committed, 0 otherwise. |
|||
Once committed, PDO assumes that a transaction is no longer active. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.rollback_func"> |
|||
<title>SKEL_rollback_func</title> |
|||
|
|||
<synopsis>int SKEL_rollback_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function rolls back a transaction on the connection. If the driver |
|||
does not support transactions, it should not provide this method. |
|||
</para> |
|||
<para> |
|||
Returns 1 to indicate a successful rollback, 0 otherwise. |
|||
Once rolled back, PDO assumes that a transaction is no longer active. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.set_attr_func"> |
|||
<title>SKEL_set_attr_func</title> |
|||
|
|||
<synopsis>int SKEL_set_attr_func(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Sets an attribute on the database handle. Returns 1 if the attribute |
|||
was set successfully, 0 otherwise. There are a number of attributes |
|||
that can be set, and these are discussed in <xref |
|||
linkend="attributes.dbh"/>. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.last_id_func"> |
|||
<title>SKEL_last_id_func</title> |
|||
|
|||
<synopsis>char *SKEL_last_id_func(pdo_dbh_t *dbh, const char *name, |
|||
unsigned int *len TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Returns the last insert id. A NULL return value indicates an error |
|||
condition, otherwise the return value must be a NUL terminated string |
|||
allocated using <function>emalloc</function>. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.fetch_error_func"> |
|||
<title>SKEL_fetch_error_func</title> |
|||
|
|||
<synopsis>int SKEL_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt *stmt, |
|||
zval *info TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Fetch error information. If stmt is not NULL, fetch information |
|||
pertaining to the statement, otherwise fetch the connection level |
|||
error information. The driver should add the following information |
|||
to the array "info" in this order: a) the native error code and b) a |
|||
string representation of the error code. |
|||
</para> |
|||
<para> |
|||
A driver may optionally append any other arbitrary, useful, |
|||
information to the info array. |
|||
</para> |
|||
<para> |
|||
Returns 1 to indicate that it populated info, 0 otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.get_attr_func"> |
|||
<title>SKEL_get_attr_func</title> |
|||
|
|||
<synopsis>int SKEL_get_attr_func(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Retrieves an attribute from a database handle. Returns 0 if the |
|||
driver doesn't support the attribute. Returns -1 if the driver |
|||
encountered an error. Returns 1 on success. There are a number of |
|||
attributes that can be fetched, and these are discussed in <xref |
|||
linkend="attributes.dbh"/>. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.check_liveness"> |
|||
<title>SKEL_check_liveness_func</title> |
|||
|
|||
<synopsis>int SKEL_check_liveness_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Performs some driver dependent action to determine if a connection is |
|||
still valid for use, typically a low overhead ping. Returns |
|||
<constant>SUCCESS</constant> if the connection is still alive and |
|||
ready to be used, <constant>FAILURE</constant> if the connection is |
|||
no longer alive (perhaps it timed out). If this function is not |
|||
provided, it is equivalent to defining a function that always returns |
|||
<constant>SUCCESS</constant>. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.get_driver_methods"> |
|||
<title>SKEL_get_driver_methods_func</title> |
|||
|
|||
<synopsis>zend_function_entry *SKEL_get_driver_methods_func( |
|||
pdo_dbh_t *dbh, int kind TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
When a PHP script attempts to call a method on a PDO or PDOStatement |
|||
object that is not covered by either this specification or by a user |
|||
defined class that extends either PDO or a PDOStatement, then |
|||
<function>SKEL_get_driver_methods_func</function> is called to |
|||
determine the driver extension methods that are present. |
|||
</para> |
|||
<para> |
|||
When kind is <constant>PDO_DBH_DRIVER_METHOD_KIND_DBH</constant>, the |
|||
driver extension method table for the connection handle must be |
|||
returned. When kind is |
|||
<constant>PDO_DBH_DRIVER_METHOD_KIND_STMT</constant>, the driver |
|||
extension method table for the statement handle must be returned. |
|||
</para> |
|||
<para> |
|||
The return value is either a <type>zend_function_entry</type> pointer |
|||
referencing a table of methods, or NULL to indicate that there are no |
|||
extension methods available. |
|||
</para> |
|||
<para> |
|||
Driver extension methods must be prefixed with the driver name used to |
|||
register the driver so that they are less likely to collide with |
|||
either future PDO methods or user defined functions in derived |
|||
classes. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="dbh.request_shutdown"> |
|||
<title>SKEL_request_shutdown_func</title> |
|||
|
|||
<synopsis>void SKEL_request_shutdown_func(pdo_dbh_t *dbh TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Called when a script terminates (request shutdown) for a persistent |
|||
connection handle. This provides the opportunity to safely releases |
|||
resources that only have per-request scope. |
|||
</para> |
|||
</section> |
|||
</section> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:tw=78: |
|||
--> |
|||
|
|||
@ -0,0 +1,182 @@ |
|||
<?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.stmt.prepare"> |
|||
<title>Preparing Statements</title> |
|||
|
|||
<para> |
|||
When building a prepared statement, the PDO core will allocate and |
|||
initialize an instance of the <type>pdo_stmt_t</type> type and pass it to |
|||
the <function>SKEL_prepare_func</function> function. |
|||
</para> |
|||
|
|||
<para> |
|||
The <varname>stmt</varname> passed to the preparer will have |
|||
<structfield>query_string</structfield> and |
|||
<structfield>query_stringlen</structfield> initialized, along with some |
|||
other state that is not relevant to a driver implementation. |
|||
</para> |
|||
|
|||
<para> |
|||
The preparer is responsible for setting up the driver specific portion of |
|||
the prepared statement state. This typically involves invoking the PDO |
|||
query rewriter and then passing the resultant query string to a database |
|||
client library API that sets up the prepared statement handle. |
|||
</para> |
|||
|
|||
<para> |
|||
The <varname>stmt</varname> has the following fields that can be set by |
|||
the preparer function: |
|||
</para> |
|||
|
|||
<programlisting role="C"><![CDATA[ |
|||
struct _pdo_stmt_t { |
|||
/* driver specific methods */ |
|||
struct pdo_stmt_methods *methods; |
|||
/* driver specific data */ |
|||
void *driver_data; |
|||
|
|||
unsigned supports_placeholders:2; |
|||
|
|||
const char *named_rewrite_template; |
|||
}; |
|||
]]></programlisting> |
|||
|
|||
<variablelist> |
|||
<varlistentry> |
|||
<term>methods</term> |
|||
<listitem> |
|||
<para> |
|||
This field <emphasis>must</emphasis> be set by the preparer |
|||
before it returns, even if the prepare failed. This |
|||
allows the core to correctly interrogate the statement 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 statement context used by the underlying database |
|||
client library and any other additional state needed by the |
|||
driver. |
|||
</para> |
|||
</listitem> |
|||
</varlistentry> |
|||
<varlistentry> |
|||
<term>supports_placeholders</term> |
|||
<listitem> |
|||
<para> |
|||
The driver should set this to either |
|||
<constant>PDO_PLACEHOLDER_NONE</constant> or one or both of |
|||
<constant>PDO_PLACEHOLDER_NAMED</constant> or |
|||
<constant>PDO_PLACEHOLDER_POSITIONAL</constant> bitwise OR'd together. |
|||
This indicates to the query rewriter what level of parameter subsitution |
|||
is supported natively by the driver. <quote>named</quote> style |
|||
placeholders are Oracle style named parameters whereas |
|||
<quote>positional</quote> style parameters are ODBC style question mark |
|||
parameter placeholders. |
|||
</para> |
|||
</listitem> |
|||
</varlistentry> |
|||
<varlistentry> |
|||
<term>named_rewrite_template</term> |
|||
<listitem> |
|||
<para> |
|||
Some drivers may only support alternative named parameter syntax that is |
|||
not recognized by PDO. Those drivers may set |
|||
<structfield>named_rewrite_template</structfield> to a printf style |
|||
format string that can be used by the query rewriter to map the ordinal |
|||
position of a parameter to a name that is recognized by the driver. |
|||
</para> |
|||
<para> |
|||
<function>snprintf</function> will be invoked using this string as the |
|||
format specifier, and will be passed a single integer parameter |
|||
representing the ordinal position of the parameter. |
|||
</para> |
|||
<para> |
|||
The PostgreSQL driver sets |
|||
<structfield>named_rewrite_template</structfield> to |
|||
<literal>$%d</literal>, which allows PDO to rewrite Oracle style named |
|||
parameters to position style, and from there, uses the rewrite template |
|||
to map them to the PostgreSQL named format. |
|||
</para> |
|||
<para> |
|||
A driver must set <structfield>supports_placeholders</structfield> to |
|||
<constant>PDO_PLACEHOLDER_NAMED</constant> to make use of this feature. |
|||
</para> |
|||
</listitem> |
|||
</varlistentry> |
|||
|
|||
</variablelist> |
|||
|
|||
<para> |
|||
If the driver natively supports both placeholder styles, it can pass |
|||
<structfield>query_string</structfield> through to its native prepare API. |
|||
Otherwise, it must set <structfield>supports_placeholders</structfield> |
|||
appropriately and then invoke <function>pdo_parse_params</function> to analyze |
|||
and possibly rewrite the query string. |
|||
</para> |
|||
|
|||
<para> |
|||
If an error is encountered, the preparer function should record error |
|||
state in the <varname>dbh</varname> rather than the |
|||
<varname>stmt</varname> as a failed prepare will result in the |
|||
<varname>stmt</varname> being freed and it will thus not be available for |
|||
interrogation. The state recorded in the <varname>dbh</varname> must be |
|||
compatible with the error handling protocol described in <xref |
|||
linkend="dbh.error.protocol"/>. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 on success, 0 on failure. |
|||
</para> |
|||
|
|||
<section id="drivers.stmt.pdo_parse_params"> |
|||
<title>pdo_parse_params</title> |
|||
|
|||
<synopsis>PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, |
|||
int inquery_len, char **outquery, int *outquery_len TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Given an input <parameter>inquery</parameter> and its length, |
|||
<parameter>inquery_len</parameter>, analyzes the SQL and potentially |
|||
rewrites it to an appropriate native form based on the |
|||
<structfield>supports_placeholders</structfield> field in |
|||
<parameter>stmt</parameter>. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 0 if the input query is in a suitable native form that the |
|||
driver understands. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 if the query was rewritten; <parameter>outquery</parameter> |
|||
and <parameter>outquery_len</parameter> will be updated to reference the |
|||
rewritten query string and its length. If |
|||
<parameter>outquery</parameter> is not NULL, the caller is responsible |
|||
for freeing it via <function>efree</function> when it is no longer |
|||
required. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns -1 if an error ocurred. The |
|||
<structfield>error_code</structfield> field of |
|||
<parameter>stmt</parameter> will have been set to an appropriate |
|||
SQLSTATE error code. A driver will usually copy this code into the |
|||
equivalent field of the <varname>dbh</varname>. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
</section> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:tw=78: |
|||
--> |
|||
|
|||
@ -0,0 +1,256 @@ |
|||
<?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.stmt.methods"> |
|||
<title>Statement Handle Methods</title> |
|||
|
|||
<para> |
|||
The <structname>pdo_stmt_methods</structname> structure defines the |
|||
methods for a given prepared statement handle. The methods are defined |
|||
below; each one is subject to the error handling protocol below. |
|||
</para> |
|||
|
|||
<para> |
|||
Note that the <structfield>dbh</structfield> of the |
|||
<varname>stmt</varname> handle references the connection handle associated |
|||
with the statement. |
|||
</para> |
|||
|
|||
<section id="stmt.error.protocol"> |
|||
<title>Error handling protocol</title> |
|||
|
|||
<para> |
|||
When a driver encounters an error on a prepared statement handle, it |
|||
must update the <structfield>error_code</structfield> field of the |
|||
<varname>stmt</varname> to hold an appropriate SQLSTATE error code, and |
|||
take some action to record the driver specific error code and human |
|||
readable message, if necessary. |
|||
</para> |
|||
<para> |
|||
The method descriptions below describe how to indicate an error |
|||
status. The PDO core may invoke the |
|||
<function>SKEL_fetch_error_func</function> to obtain the driver |
|||
specific error code and human readable message. |
|||
</para> |
|||
<para> |
|||
The driver should not unilaterally raise an exception in reponse to an |
|||
error. Instead, it should be left to the PDO core to handle reporting |
|||
the error to the script, based on the application preferences for |
|||
error handling. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
<section id="stmt.dtor_func"> |
|||
<title>SKEL_stmt_dtor_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_dtor_func(pdo_stmt_t *stmt TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
This function is called by the PDO core when freeing resources |
|||
associated with the <varname>stmt</varname>. It should release any |
|||
resources allocated by the driver. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 0. An implementation bug means that the return value is not |
|||
checked. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="stmt.execute_func"> |
|||
<title>SKEL_stmt_execute_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_execute_func(pdo_stmt_t *stmt TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Starts the query. This is typically implemented as a call to the |
|||
database specific prepared statement execute function. Prior to calling |
|||
this function, the PDO core will trigger a |
|||
<constant>PDO_PARAM_EVT_EXEC_PRE</constant> event for each parameter, |
|||
offering the driver an opportunity to perform some final binding or |
|||
allocation actions prior to executing the statement. |
|||
</para> |
|||
<para> |
|||
<structfield>active_query_string</structfield> and |
|||
<structfield>active_query_stringlen</structfield> will be set by the PDO |
|||
core to reflect the query being executed. This is largely for the |
|||
convenience of drivers that don't natively support parameterized |
|||
queries; the query rewriter will have synthesized a query string with |
|||
the parameters expanded, if the |
|||
<structfield>supports_placeholders</structfield> indicates that it |
|||
should have. For drivers that do support parameterized queries, it is |
|||
anticipated that they will have already prepared their statement handles |
|||
and associated the parameters with it during the |
|||
<constant>PDO_PARAM_EVT_EXEC_PRE</constant> notification. |
|||
</para> |
|||
<para> |
|||
Immediately after executing, the PDO core will trigger a |
|||
<constant>PDO_PARAM_EVT_EXEC_POST</constant> event for each parameter, |
|||
offering the driver an opportunity to take some action, for example, |
|||
with parameters bound as OUT parameters. |
|||
</para> |
|||
|
|||
<para> |
|||
Returns 1 on success, 0 on failure. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="stmt.fetch_func"> |
|||
<title>SKEL_stmt_fetch_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_fetch_func(pdo_stmt_t *stmt, |
|||
enum pdo_fetch_orientation ori, long offset TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Requests that the driver fetch the next row into driver storage. Prior to |
|||
calling this function the PDO core will trigger a |
|||
<constant>PDO_PARAM_EVT_FETCH_PRE</constant> event for each column, |
|||
offering the driver an opportunity to perform per-column allocations or |
|||
binding. |
|||
</para> |
|||
<para> |
|||
After calling this function, the PDO core will trigger a describe of the |
|||
columns if they haven't already been queried, and will then trigger a |
|||
<constant>PDO_PARAM_EVT_FETCH_POST</constant> event. |
|||
</para> |
|||
<para> |
|||
The orientation and offset parameters allow scrolling cursor operation. |
|||
</para> |
|||
<para> |
|||
Returns 1 if data was returned, 0 otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="stmt.describe_col_func"> |
|||
<title>SKEL_stmt_describe_col_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_describe_col_func(pdo_stmt_t *stmt, |
|||
int colno TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Requests that the driver populate the <structfield>columns</structfield> |
|||
field of <varname>stmt</varname> with information about a given column. |
|||
Columns are numbered zero-based in this function. |
|||
</para> |
|||
<para> |
|||
Returns 1 if successful, 0 otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="stmt.get_col_data_func"> |
|||
<title>SKEL_stmt_get_col_data_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_get_col_data_func(pdo_stmt_t *stmt, |
|||
int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
Requests that the driver return a pointer and size of the data for a |
|||
particular column. PDO prefers that the driver manage the lifetime of |
|||
this data (it can often reuse the same memory block for repeated |
|||
fetches). The PDO core will translate this memory, copying it if |
|||
necessary. If the driver must allocate transient memory for a column, |
|||
then it should do so using emalloc() and set caller_frees to a non-zero |
|||
value. This informs PDO that it is responsible for freeing the column |
|||
data when it is no longer required. |
|||
</para> |
|||
<para> |
|||
The type of pointer is specified by the column description prepared by |
|||
SKEL_stmt_describe_col_func. |
|||
</para> |
|||
<para> |
|||
Returns 1 if successful, 0 otherwise. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="stmt.param_hook_func"> |
|||
<title>SKEL_stmt_param_hook_func</title> |
|||
|
|||
<synopsis>int SKEL_stmt_param_hook_func(pdo_stmt_t *stmt, |
|||
struct pdo_bound_param_data *param, enum pdo_param_event event_type |
|||
TSRMLS_DC);</synopsis> |
|||
|
|||
<para> |
|||
The param hook function is called by the PDO core at certain key points |
|||
in the setup of a statement handle, per parameter or column, to notify |
|||
the driver, so that it can perform some driver specific function. |
|||
</para> |
|||
<para> |
|||
The PDO core has no expectations for the hook function, except that it |
|||
should return 0 if there was an error, 1 otherwise. |
|||
</para> |
|||
<para> |
|||
The events that are possible are: |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_NORMALIZE</bridgehead> |
|||
<para> |
|||
Triggered before PDO_PARAM_EVT_ALLOC to normalize the parameter name. |
|||
This is not typically used by most drivers. The pgsql driver uses |
|||
this opportunity to fixup the parameter name and ordinal position before |
|||
the core registers its parameter state. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_ALLOC</bridgehead> |
|||
<para> |
|||
Triggered in response to binding a parameter or column. This is the |
|||
drivers opportunity to allocate its driver-specific state for the |
|||
parameter. |
|||
</para> |
|||
<para> |
|||
Some drivers will take this opportunity to set up bind descriptors |
|||
if enough information is present in the param data. Note that this |
|||
stage is too early to be sure of the value (it may change between the |
|||
bind call and statement execution), so drivers must not snapshot |
|||
the value of the parameter at this point. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_FREE</bridgehead> |
|||
<para> |
|||
Triggered when the core is done with a parameter, typically at statement |
|||
handle tear-down time. The driver must release any resources it may |
|||
have allocated for the parameter. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_EXEC_PRE</bridgehead> |
|||
<para> |
|||
Triggered for each parameter immediately before invoking the |
|||
<function>SKEL_stmt_execute_func</function>. This is the correct time |
|||
to capture or reference the parameter value and finalize the binding of |
|||
the parameter. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_EXEC_POST</bridgehead> |
|||
<para> |
|||
Triggered for each parameter immediately after invoking the |
|||
<function>SKEL_stmt_execute_func</function>. This allows a driver to |
|||
fixup or reconcile state, in particular for OUT parameters that have |
|||
been bound to a zval. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_FETCH_PRE</bridgehead> |
|||
<para> |
|||
Triggered for each bound column immediately before invoking the |
|||
<function>SKEL_stmt_fetch_func</function>. This has similar semantics |
|||
to PDO_PARAM_EVT_EXEC_PRE, except that it applies to binding columns in |
|||
a result set to zvals rather than parameters in a prepared statement. |
|||
</para> |
|||
|
|||
<bridgehead>PDO_PARAM_EVT_FETCH_POST</bridgehead> |
|||
<para> |
|||
Triggered for each bound column immediately after invoking the |
|||
<function>SKEL_stmt_fetch_func</function>. This has similar semantics |
|||
to PDO_PARAM_EVT_EXEC_POST, except that it applies to binding columns in |
|||
a result set to zvals rather than parameters in a prepared statement. |
|||
</para> |
|||
</section> |
|||
|
|||
|
|||
|
|||
</section> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:tw=78: |
|||
--> |
|||
|
|||
@ -0,0 +1,162 @@ |
|||
<?xml version='1.0' encoding='UTF-8' ?> |
|||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|||
|
|||
<chapter id="overview"> |
|||
<title>Overview</title> |
|||
|
|||
<para> |
|||
PDO is structured as depicted below; a core PDO module provides a framework |
|||
for loading driver extensions and calling into them, similar in some ways to |
|||
ODBC, although PDO is a very lightweight bridge when compared to ODBC. The |
|||
core module is responsible for managing the user-space portions of the the |
|||
PHP/Database interaction, delegating the database/vendor specific portions to |
|||
the appropriate driver extension module. It is typical for a driver |
|||
extension to delegate, in turn, to a pre-existing database client library to |
|||
carry out its duties. |
|||
</para> |
|||
|
|||
<para> |
|||
<screen> |
|||
+---------------------------------------------+ |
|||
| PDO Core | |
|||
+---------------------------------------------+ |
|||
+--------------------+ +--------------------+ |
|||
|PDO Driver Extension| |PDO Driver Extension| |
|||
+--------------------+ +--------------------+ |
|||
+--------------------+ +--------------------+ |
|||
| DB Client Library | | DB Client Library | |
|||
+--------------------+ +--------------------+ |
|||
</screen> |
|||
</para> |
|||
|
|||
<section id="overview.design"> |
|||
<title>Design Principles</title> |
|||
|
|||
<para> |
|||
PDO was built around the ideal of being able to provide a common data access |
|||
paradigm across a variety of data providers. The goal was to provide the |
|||
lowest common denominator of features using a common API, while still |
|||
being able to provide access to database/vendor specific features. |
|||
There are some important behavior traits in PDO; most are general behaviors |
|||
that most drivers exhibit; some deviation is allowed if it the net effect of |
|||
the deviation is not a big problem (for instance, type juggling). There are |
|||
a couple of hard rules that must be adhered to for conformance, however. |
|||
</para> |
|||
|
|||
<section id="overview.design.connection"> |
|||
<title>Connection Management</title> |
|||
|
|||
<para> |
|||
While an instance of the PDO class exists, it represents an open connection |
|||
to the database. |
|||
</para> |
|||
</section> |
|||
|
|||
<section id="overview.design.typing"> |
|||
<title>Data typing</title> |
|||
|
|||
<para> |
|||
As a "typeless" environment, PHP doesn't mind whether data is returned as |
|||
integer, floating point or string; it can convert to the appropriate type as |
|||
needed. This conversion process may cause loss in data fidelity in some |
|||
cases, in particular when it comes to floating point numbers. The type of |
|||
choice for PDO when binding or requesting data is to use the string type, as |
|||
this has the best data fidelity. |
|||
</para> |
|||
<para> |
|||
Note that some database client library implementations don't provide the |
|||
application with a means to specify their preferred data type, returning it |
|||
in their own perception of the best native data type. For those drivers it |
|||
would typically be wasted effort to convert to a string in the PDO driver |
|||
layer, so the native type is passed up and returned to the script in that |
|||
form. |
|||
</para> |
|||
<para> |
|||
The net result of this is that data is usually, but not always, returned as |
|||
strings unless otherwise specified by the PHP script. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
<section id="overview.design.xact"> |
|||
<title>Transaction Support</title> |
|||
|
|||
<para> |
|||
Many, but not all, database implementations support the notion of |
|||
transactions. The transaction reflects a block of database operations |
|||
that can be either committed or rolled back. Some database implementations |
|||
support nesting transactions, or transactions across multiple connection |
|||
handles. Most databases that support transactions start out in a mode known |
|||
as "auto-commit", which emulates non-transactional behavior. |
|||
</para> |
|||
|
|||
<para> |
|||
PDO, as an abstraction layer, is responsible for making sure that the |
|||
behavior of two freshly opened connections to different databases don't |
|||
exhibit drastically different behavior. The principle of least surprise is |
|||
particularly important when it comes to transactions, so PDO requires that |
|||
its driver extensions observe the following rules, since an application that |
|||
assumes that transactions are available when they are not could proceed and |
|||
cause damage to the data in the database when it attempts to rollback its |
|||
changes. |
|||
</para> |
|||
|
|||
<para> |
|||
Freshly created connections must start in auto-commit mode. This allows |
|||
non-transactional scripts to operate without having to do anything special |
|||
to get auto-commit enabled. |
|||
</para> |
|||
|
|||
<para> |
|||
Attempting to use transactions when the underlying database doesn't support |
|||
them must return an error to the PDO core layer. PDO itself will generate a |
|||
runtime exception which will cause the script to terminate unless handled by |
|||
the script. Note that PDO will not normally generate exceptions unless |
|||
explicitly told to do so by the script. Forcing an exception in this case |
|||
helps to reinforce that something is seriously wrong. |
|||
</para> |
|||
|
|||
<para> |
|||
PDO only supports the notion of being in a transaction or not. It does not |
|||
support nested transactions, it is an error to start a new transaction while |
|||
a transaction is active. |
|||
</para> |
|||
|
|||
<para> |
|||
Ad-hoc SQL executed by the script that affects the transactional state of |
|||
the connection as seen by the database is allowed, but its effect on the |
|||
PDO-core notion of the transactional state is undefined. A driver must not |
|||
attempt to reconcile the effect of ad-hoc SQL with the PDO-core |
|||
transactional state. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
<section id="overview.design.err"> |
|||
<title>Error Handling</title> |
|||
|
|||
<para> |
|||
The behavior of PDO in the face of errors varies based on application |
|||
preference. The default is to silently return error codes back to the |
|||
script, but also allows the option of emitting a warning in addition to |
|||
returning the error code, or to throw an exception object containing the |
|||
error state. |
|||
</para> |
|||
|
|||
<para> |
|||
In the interests of portability and fidelity of information, PDO requires |
|||
its drivers to record the ANSI SQL 92 SQLSTATE error code along with their |
|||
native and human readable error codes when an error is encountered. This |
|||
allows portable scripts the ability to use vendor-independent error handling |
|||
logic as well as the freedom to also use vendor-dependent logic if required. |
|||
</para> |
|||
|
|||
</section> |
|||
|
|||
</section> |
|||
</chapter> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:fileencoding=utf-8:encoding=utf-8: |
|||
--> |
|||
@ -0,0 +1,44 @@ |
|||
<?xml version='1.0' encoding='UTF-8' ?> |
|||
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|||
|
|||
<preface id="preface"> |
|||
<title>Preface</title> |
|||
<para> |
|||
This document specifies the implementation of PDO, PHP Data Objects, both |
|||
from the perspective of PHP script level APIs used by people developing PHP |
|||
applications, and from the perspective of C level APIs in the PDO internals |
|||
that will be used by people developing PDO drivers. |
|||
</para> |
|||
|
|||
<para> |
|||
Briefly summarize the chapters here. |
|||
</para> |
|||
|
|||
<bridgehead>Acknowledgments</bridgehead> |
|||
<para> |
|||
A number of people were involved in the development of PDO and its drivers; |
|||
without them it wouldn't be what it is, and you wouldn't be reading this |
|||
text. Those people are: |
|||
Ilia Alshanetsky, |
|||
Ard Biesheuvel, |
|||
Marcus Börger, |
|||
Sara Golemon, |
|||
Sterling Hughes, |
|||
Edin Kadribašić |
|||
Frank Kroman |
|||
and George Schlossnagle from the PHP community, |
|||
Chris Jones from Oracle, |
|||
Dan Scott, |
|||
Bill Abt, |
|||
Kellen Bombardier |
|||
Rick McGuire |
|||
and |
|||
Krishna Raman from IBM. |
|||
</para> |
|||
|
|||
</preface> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et:fileencoding=utf-8:encoding=utf-8: |
|||
--> |
|||
@ -0,0 +1,13 @@ |
|||
<?xml version='1.0' encoding='UTF-8' ?> |
|||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|||
|
|||
<chapter id="user"> |
|||
<title>User-space Documentation</title> |
|||
<para>bar</para> |
|||
</chapter> |
|||
|
|||
<!-- |
|||
vim:ts=2:sw=2:et: |
|||
--> |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue