<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 20115 -->
    <!-- Reviewed: no -->
<sect1 id="zend.db.adapter">

    <title>Zend_Db_Adapter</title>

    <para>
        <classname>Zend_Db</classname> y sus clases relacionadas proporcionan
        una interfaz simple de base de datos <acronym>SQL</acronym> para Zend
        Framework. El <classname>Zend_Db_Adapter</classname> es la clase base
        que se utiliza para conectar su aplicación <acronym>PHP</acronym> A una
        base de datos ( <acronym>RDBMS</acronym> ). Existen diferentes clases
        Adapters(Adaptador) para cada tipo de base de datos (
            <acronym>RDBMS</acronym> ). </para>

    <para> Las clases Adapters de <classname>Zend_Db</classname> crean un puente
        entre las extensiones de base de datos de <acronym>PHP</acronym> hacia
        una interfaz común, para ayudarle a escribir aplicaciones
            <acronym>PHP</acronym> una sola vez y poder desplegar múltiples
        tipos de base de datos ( <acronym>RDBMS</acronym> ) con muy poco
        esfuerzo. </para>

    <para> La Interfaz de la clase adaptador (adapter) es similar a la intefaz
        de la extensión <ulink url="http://www.php.net/pdo">PHP Data
            Objects</ulink> . <classname>Zend_Db</classname> proporciona clases
        Adaptadoras para los drivers <acronym>PDO</acronym> de los siguientes
        tipos de <acronym>RDBMS</acronym> : </para>

    <itemizedlist>
        <listitem>
            <para> IBM DB2 e Informix Dynamic Server (IDS), usando la extensión
                    <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>
            </para>
        </listitem>
        <listitem>
            <para> MySQL, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-mysql"> pdo_mysql </ulink>
            </para>
        </listitem>
        <listitem>
            <para> Microsoft SQL Server, usando la extensión
                    <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-mssql"> pdo_mssql </ulink>
            </para>
        </listitem>
        <listitem>
            <para> Oracle, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink>
            </para>
        </listitem>
        <listitem>
            <para> PostgreSQL, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-pgsql"> pdo_pgsql </ulink>
            </para>
        </listitem>
        <listitem>
            <para> SQLite, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/pdo-sqlite"> pdo_sqlite </ulink>
            </para>
        </listitem>

    </itemizedlist>

    <para> Ademas, <classname>Zend_Db</classname> proporciona clases Adaptadoras
        que utilizan las extensiones de base de datos de <acronym>PHP</acronym>
        de los siguientes tipos: </para>

    <itemizedlist>
        <listitem>
            <para> MySQL, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/mysqli">mysqli</ulink>
            </para>
        </listitem>
        <listitem>
            <para> Oracle, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/oci8">oci8</ulink>
            </para>
        </listitem>
        <listitem>
            <para> IBM DB2, usando la extensión <acronym>PHP</acronym>
                <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
            </para>
        </listitem>
        <listitem>
            <para> Firebird/Interbase, usando la extensión
                    <acronym>PHP</acronym>
                <ulink url="http://www.php.net/ibase"> php_interbase </ulink>
            </para>
        </listitem>
    </itemizedlist>

    <note>
        <para> Cada Zend_Db_Adaptador utiliza una extensión
                <acronym>PHP</acronym> . Se debe de tener habilitada la
            respectiva extensión en su entorno <acronym>PHP</acronym> para
            utilizar un <classname>Zend_Db_Adapter</classname> . Por ejemplo, si
            se utiliza una clase <classname>Zend_Db_Adapter</classname> basada
            en <acronym>PDO</acronym> , tiene que habilitar tanto la extensión
                <acronym>PDO</acronym> como el driver <acronym>PDO</acronym> del
            tipo de base de datos que se utiliza. </para>
    </note>

    <sect2 id="zend.db.adapter.connecting">

        <title> Conexión a una Base de Datos utilizando un Adaptador </title>

        <para> Esta sección describe cómo crear una instancia de un Adaptador de
            base de datos. Esto corresponde a establecer una conexión a un
            servidor de Base de Datos ( <acronym>RDBMS</acronym> ) desde su
            aplicación <acronym>PHP</acronym> . </para>

        <sect3 id="zend.db.adapter.connecting.constructor">

            <title>Usando un Constructor de Zend_Db Adapter</title>

            <para> Se puede crear una instancia de un Adaptador utilizando su
                constructor. Un constructor de adaptador toma un argumento, que
                es un conjunto de parámetros utilizados para declarar la
                conexión. </para>

            <example id="zend.db.adapter.connecting.constructor.example">
                <title>Usando el Constructor de un Adaptador</title>
                <programlisting language="php"><![CDATA[
$db = new Zend_Db_Adapter_Pdo_Mysql(array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test'
));
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.connecting.factory">

            <title>Usando el Zend_Db Factory</title>

            <para> Como alternativa a la utilización directa del constructor de
                un adaptador, se puede crear una instancia del adaptador que use
                el método estático <methodname>Zend_Db::factory()</methodname> .
                Este método carga dinámicamente el archivo de clase Adaptador
                bajo demanda, usando <link linkend="zend.loader.load.class">
                    Zend_Loader::loadClass() </link> . </para>

            <para> El primer argumento es una cadena que nombra al nombre base
                de la clase Adaptador. Por ejemplo, la cadena '
                    <classname>Pdo_Mysql</classname> ' corresponde a la clase
                    <classname>Zend_Db_Adapter_Pdo_Mysql</classname> . El
                segundo argumento es el mismo array de parámetros que hubiera
                enviado al constructor del adaptador. </para>

            <example id="zend.db.adapter.connecting.factory.example">
                <title>Usando el Adaptador del método factory</title>
                <programlisting language="php"><![CDATA[
// No necesitamos la siguiente declaración, porque
// el archivo Zend_Db_Adapter_Pdo_Mysql será cargado para nosotros por el método
// factory de Zend_Db.

// require_once 'Zend/Db/Adapter/Pdo/Mysql.php';

// carga automaticamente la clase Zend_Db_Adapter_Pdo_Mysql
// y crea una instancia de la misma
$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test'
));
]]></programlisting>
            </example>

            <para> Si crea su propia clase que extiende a
                    <classname>Zend_Db_Adapter_Abstract</classname> , pero no
                nombra su clase con el prefijo de paquete "
                    <classname>Zend_Db_Adapter</classname> ", se puede utilizar
                el método <methodname>factory()</methodname> para cargar su
                adaptador si se especifica la parte principal de la clase del
                adaptador con la clave "adapterNamespace" en el conjunto de
                parámetros </para>

            <example id="zend.db.adapter.connecting.factory.example2">
                <title> Usando el método factory para una clase Adaptador
                    personalizada </title>
                <programlisting language="php"><![CDATA[
// No tenemos que cargar el archivo de clase Adaptador
// porque será cargado para nosotros por el método factory de Zend_Db.

// Automáticamente carga la clase MyProject_Db_Adapter_Pdo_Mysql
// y crea una instancia de ella.

$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'             => '127.0.0.1',
    'username'         => 'webuser',
    'password'         => 'xxxxxxxx',
    'dbname'           => 'test',
    'adapterNamespace' => 'MyProject_Db_Adapter'
));
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.connecting.factory-config">

            <title>Uso de Zend_Config con Zend_Db Factory</title>

            <para> Opcionalmente, se puede especificar cualquier argumento del
                método <methodname>factory()</methodname> como un objeto de tipo
                    <link linkend="zend.config">Zend_Config</link> . </para>

            <para> Si el primer argumento es un objeto de configuración, se
                espera que contenga una propiedad llamada
                    <property>adapter</property> , conteniendo la cadena que da
                nombre al nombre base de la clase de adaptador. Opcionalmente,
                el objeto puede contener una propiedad llamada
                    <property>params</property> , con subpropiedades
                correspondientes a nombres de parámetros del adaptador. Esto es
                usado sólo si el segundo argumento del método
                    <methodname>factory()</methodname> se ha omitido. </para>

            <example id="zend.db.adapter.connecting.factory.example1">
                <title> Uso del método factory del Adaptador con un objeto
                    Zend_Config </title>
                <para> En el siguiente ejemplo, un objeto
                        <classname>Zend_Config</classname> es creado usando un
                    array. También puedes cargar los datos de un archivo
                    externo, por ejemplo con <link
                        linkend="zend.config.adapters.ini"> Zend_Config_Ini
                    </link> o <link linkend="zend.config.adapters.xml">
                        Zend_Config_Xml </link> . </para>
                <programlisting language="php"><![CDATA[
$config = new Zend_Config(
    array(
        'database' => array(
            'adapter' => 'Mysqli',
            'params' => array(
                'dbname' => 'test',
                'username' => 'webuser',
                'password' => 'secret',
            )
        )
    )
);

$db = Zend_Db::factory($config->database);
]]></programlisting>
            </example>

            <para> El segundo argumento del método
                    <methodname>factory()</methodname> puede ser un array
                asociativo con entradas correspondientes a los parámetros del
                adaptador. Este argumento es opcional. Si el primer argumento es
                de tipo <classname>Zend_Config</classname> , se asume que tiene
                todos los parametros, y el segundo argumento es ignorado. </para>

        </sect3>

        <sect3 id="zend.db.adapter.connecting.parameters">

            <title>Parámetros del Adaptador</title>

            <para> El siguiente listado explica parámetros comunes reconocidos
                por Adaptador de clases <classname>Zend_Db</classname> . </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <emphasis>host</emphasis> : una string conteniendo un
                        nombre de host o dirección IP del servidor de base de
                        datos. Si la base de datos está corriendo sobre el mismo
                        host que la aplicación <acronym>PHP</acronym> , usted
                        puede utilizar 'localhost' o '127.0.0.1'. </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis>username</emphasis> : identificador de cuenta
                        para autenticar una conexión al servidor
                            <acronym>RDBMS</acronym> . </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis>password</emphasis> : la contraseña de la
                        cuenta para la autenticación de credenciales de conexión
                        con el servidor <acronym>RDBMS</acronym>
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis>dbname</emphasis> : nombre de la base de datos
                        en el servidor <acronym>RDBMS</acronym> . </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis>port</emphasis> : algunos servidores
                            <acronym>RDBMS</acronym> pueden aceptar conexiones
                        de red sobre un número de puerto específico. El
                        parámetro del puerto le permite especificar el puerto al
                        que su aplicación <acronym>PHP</acronym> se conecta,
                        para que concuerde el puerto configurado en el servidor
                            <acronym>RDBMS</acronym> . </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis>charset</emphasis> : specify the charset used
                        for the connection. </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>options</emphasis> : : este parámetro es un
                        array asociativo de opciones que son genéricas a todas
                        las clases <classname>Zend_Db_Adapter</classname> .
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis> driver_options </emphasis> : este parámetro
                        es un array asociativo de opciones adicionales para una
                        extensión de base de datos dada. un uso típico de este
                        parámetro es establecer atributos de un driver
                            <acronym>PDO</acronym> . </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis> adapterNamespace </emphasis> : nombre de la
                        parte inicial del nombre de las clase para el adaptador,
                        en lugar de ' <classname>Zend_Db_Adapter</classname> '.
                        Utilice esto si usted necesita usar el método
                            <methodname>factory()</methodname> para cargar un
                        adaptador de clase de base de datos que no sea de Zend.
                    </para>
                </listitem>
            </itemizedlist>

            <example id="zend.db.adapter.connecting.parameters.example1">
                <title> Passing the case-folding option to the factory </title>
                <para> Usted puede pasar esta opción específica por la constante
                        <constant>Zend_Db::CASE_FOLDING</constant> . Este
                    corresponde al atributo <constant>ATTR_CASE</constant> en
                    los drivers de base de datos <acronym>PDO</acronym> e IBM
                    DB2, ajustando la sensibilidad de las claves tipo cadena en
                    los resultados de consultas. La opción toma los valores
                        <constant>Zend_Db::CASE_NATURAL</constant> (el
                    predeterminado), <constant>Zend_Db::CASE_UPPER</constant> ,
                    y <constant>Zend_Db::CASE_LOWER</constant> . </para>
                <programlisting language="php"><![CDATA[
$options = array(
    Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
);

$params = array(
    'host'           => '127.0.0.1',
    'username'       => 'webuser',
    'password'       => 'xxxxxxxx',
    'dbname'         => 'test',
    'options'        => $options
);

$db = Zend_Db::factory('Db2', $params);
]]></programlisting>
            </example>

            <example id="zend.db.adapter.connecting.parameters.example2">
                <title> Passing the auto-quoting option to the factory </title>
                <para> Usted puede especificar esta opción por la constante
                        <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> .
                    Si el valor es <constant>TRUE</constant> (el
                    predeterminado), los identificadores como nombres de tabla,
                    nombres de columna, e incluso los alias son delimitados en
                    la sintaxis <acronym>SQL</acronym> generada por el Adatador
                    del objeto. Esto hace que sea sencillo utilizar
                    identificadores que contengan palabras reservadas de
                        <acronym>SQL</acronym> , o caracteres especiales. Si el
                    valor es <constant>FALSE</constant> , los identificadores no
                    son delimitados automáticamente. Si usted necesita delimitar
                    identificadores, debe hacer usted mismo utilizando el método
                        <methodname>quoteIdentifier()</methodname> . </para>
                <programlisting language="php"><![CDATA[
$options = array(
    Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
);

$params = array(
    'host'           => '127.0.0.1',
    'username'       => 'webuser',
    'password'       => 'xxxxxxxx',
    'dbname'         => 'test',
    'options'        => $options
);

$db = Zend_Db::factory('Pdo_Mysql', $params);
]]></programlisting>
            </example>

            <example id="zend.db.adapter.connecting.parameters.example3">
                <title>Passing PDO driver options to the factory</title>
                <programlisting language="php"><![CDATA[
$pdoParams = array(
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
);

$params = array(
    'host'           => '127.0.0.1',
    'username'       => 'webuser',
    'password'       => 'xxxxxxxx',
    'dbname'         => 'test',
    'driver_options' => $pdoParams
);

$db = Zend_Db::factory('Pdo_Mysql', $params);

echo $db->getConnection()
        ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
]]></programlisting>
            </example>

            <example id="zend.db.adapter.connecting.parameters.example4">
                <title>Passing Serialization Options to the Factory</title>
                <programlisting language="php"><![CDATA[
$options = array(
    Zend_Db::ALLOW_SERIALIZATION => false
);

$params = array(
    'host'           => '127.0.0.1',
    'username'       => 'webuser',
    'password'       => 'xxxxxxxx',
    'dbname'         => 'test',
    'options'        => $options
);

$db = Zend_Db::factory('Pdo_Mysql', $params);
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.connecting.getconnection">
            <title>Managing Lazy Connections</title>

            <para> Creating an instance of an Adapter class does not immediately
                connect to the <acronym>RDBMS</acronym> server. The Adapter
                saves the connection parameters, and makes the actual connection
                on demand, the first time you need to execute a query. This
                ensures that creating an Adapter object is quick and
                inexpensive. You can create an instance of an Adapter even if
                you are not certain that you need to run any database queries
                during the current request your application is serving. </para>

            <para> If you need to force the Adapter to connect to the
                    <acronym>RDBMS</acronym> , use the
                    <methodname>getConnection()</methodname> method. This method
                returns an object for the connection as represented by the
                respective <acronym>PHP</acronym> database extension. For
                example, if you use any of the Adapter classes for
                    <acronym>PDO</acronym> drivers, then
                    <methodname>getConnection()</methodname> returns the
                    <acronym>PDO</acronym> object, after initiating it as a live
                connection to the specific database. </para>

            <para> It can be useful to force the connection if you want to catch
                any exceptions it throws as a result of invalid account
                credentials, or other failure to connect to the
                    <acronym>RDBMS</acronym> server. These exceptions are not
                thrown until the connection is made, so it can help simplify
                your application code if you handle the exceptions in one place,
                instead of at the time of the first query against the database. </para>

            <para> Additionally, an adapter can get serialized to store it, for
                example, in a session variable. This can be very useful not only
                for the adapter itself, but for other objects that aggregate it,
                like a <classname>Zend_Db_Select</classname> object. By default,
                adapters are allowed to be serialized, if you don't want it, you
                should consider passing the
                    <constant>Zend_Db::ALLOW_SERIALIZATION</constant> option
                with <constant>FALSE</constant> , see the example above. To
                respect lazy connections principle, the adapter won't reconnect
                itself after being unserialized. You must then call
                    <methodname>getConnection()</methodname> yourself. You can
                make the adapter auto-reconnect by passing the
                    <constant>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE</constant>
                with <constant>TRUE</constant> as an adapter option. </para>

            <example id="zend.db.adapter.connecting.getconnection.example">
                <title>Handling connection exceptions</title>
                <programlisting language="php"><![CDATA[
try {
    $db = Zend_Db::factory('Pdo_Mysql', $parameters);
    $db->getConnection();
} catch (Zend_Db_Adapter_Exception $e) {
    // perhaps a failed login credential, or perhaps the RDBMS is not running
} catch (Zend_Exception $e) {
    // perhaps factory() failed to load the specified Adapter class
}
]]></programlisting>
            </example>

        </sect3>

    </sect2>

    <sect2 id="zend.db.adapter.example-database">

        <title>La base de datos de ejemplo</title>

        <para> En la documentación de las clases <classname>Zend_Db</classname>
            , usamos un conjunto sencillo de tablas para ilustrar el uso de las
            clases y métodos. Estas tablas de ejemplo permiten almacenar
            información para localizar bugs en un proyecto de desarrollo de
            software. La base de datos contiene cuatro tablas: </para>

        <itemizedlist>
            <listitem>
                <para>
                    <emphasis>accounts</emphasis> almacena información sobre
                    cada usuario que hace el seguimiento de bugs. </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>products</emphasis> almacena información sobre
                    cada producto para el que pueden registrarse bugs. </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>bugs</emphasis> almacena información sobre bugs,
                    incluyendo el estado actual del bug, la persona que informó
                    sobre el bug, la persona que está asignada para corregir el
                    bug, y la persona que está asignada para verificar la
                    corrección. </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>bugs_products</emphasis> stores a relationship
                    between bugs and products. This implements a many-to-many
                    relationship, because a given bug may be relevant to
                    multiple products, and of course a given product can have
                    multiple bugs. </para>
            </listitem>
        </itemizedlist>

        <para> La siguiente definición de datos <acronym>SQL</acronym> en
            lenguaje pseudocódigo describe las tablas de esta base de datos de
            ejemplo. Estas tablas de ejemplo son usadas ampliamente por los
            tests unitarios automatizados de <classname>Zend_Db</classname> . </para>

        <programlisting language="sql"><![CDATA[
CREATE TABLE accounts (
  account_name      VARCHAR(100) NOT NULL PRIMARY KEY
);

CREATE TABLE products (
  product_id        INTEGER NOT NULL PRIMARY KEY,
  product_name      VARCHAR(100)
);

CREATE TABLE bugs (
  bug_id            INTEGER NOT NULL PRIMARY KEY,
  bug_description   VARCHAR(100),
  bug_status        VARCHAR(20),
  reported_by       VARCHAR(100) REFERENCES accounts(account_name),
  assigned_to       VARCHAR(100) REFERENCES accounts(account_name),
  verified_by       VARCHAR(100) REFERENCES accounts(account_name)
);

CREATE TABLE bugs_products (
  bug_id            INTEGER NOT NULL REFERENCES bugs,
  product_id        INTEGER NOT NULL REFERENCES products,
  PRIMARY KEY       (bug_id, product_id)
);
]]></programlisting>

        <para> Also notice that the <code>bugs</code> table contains multiple
            foreign key references to the <code>accounts</code> table. Each of
            these foreign keys may reference a different row in the
                <code>accounts</code> table for a given bug. </para>

        <para> The diagram below illustrates the physical data model of the
            example database. </para>

        <para>
            <inlinegraphic width="387" scale="100" align="center"
                valign="middle"
                fileref="figures/zend.db.adapter.example-database.png"
                format="PNG"/>
        </para>

    </sect2>

    <sect2 id="zend.db.adapter.select">

        <title>Reading Query Results</title>

        <para> This section describes methods of the Adapter class with which
            you can run SELECT queries and retrieve the query results. </para>

        <sect3 id="zend.db.adapter.select.fetchall">

            <title>Fetching a Complete Result Set</title>

            <para> You can run a <acronym>SQL</acronym> SELECT query and
                retrieve its results in one step using the
                    <methodname>fetchAll()</methodname> method. </para>

            <para> The first argument to this method is a string containing a
                SELECT statement. Alternatively, the first argument can be an
                object of class <link linkend="zend.db.select"
                    >Zend_Db_Select</link> . The Adapter automatically converts
                this object to a string representation of the SELECT statement. </para>

            <para> The second argument to <methodname>fetchAll()</methodname> is
                an array of values to substitute for parameter placeholders in
                the <acronym>SQL</acronym> statement. </para>

            <example id="zend.db.adapter.select.fetchall.example">
                <title>Using fetchAll()</title>
                <programlisting language="php"><![CDATA[
$sql = 'SELECT * FROM bugs WHERE bug_id = ?';

$result = $db->fetchAll($sql, 2);
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.select.fetch-mode">

            <title>Changing the Fetch Mode</title>

            <para> By default, <methodname>fetchAll()</methodname> returns an
                array of rows, each of which is an associative array. The keys
                of the associative array are the columns or column aliases named
                in the select query. </para>

            <para> You can specify a different style of fetching results using
                the <methodname>setFetchMode()</methodname> method. The modes
                supported are identified by constants: </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <constant>Zend_Db::FETCH_ASSOC</constant> : return data
                        in an array of associative arrays. The array keys are
                        column names, as strings. This is the default fetch mode
                        for <classname>Zend_Db_Adapter</classname> classes. </para>
                    <para> Note that if your select-list contains more than one
                        column with the same name, for example if they are from
                        two different tables in a JOIN, there can be only one
                        entry in the associative array for a given name. If you
                        use the FETCH_ASSOC mode, you should specify column
                        aliases in your SELECT query to ensure that the names
                        result in unique array keys. </para>
                    <para> By default, these strings are returned as they are
                        returned by the database driver. This is typically the
                        spelling of the column in the <acronym>RDBMS</acronym>
                        server. You can specify the case for these strings,
                        using the <constant>Zend_Db::CASE_FOLDING</constant>
                        option. Specify this when instantiating the Adapter. See
                            <xref
                            linkend="zend.db.adapter.connecting.parameters.example1"
                        /> . </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>Zend_Db::FETCH_NUM</constant> : return data in
                        an array of arrays. The arrays are indexed by integers,
                        corresponding to the position of the respective field in
                        the select-list of the query. </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>Zend_Db::FETCH_BOTH</constant> : return data
                        in an array of arrays. The array keys are both strings
                        as used in the FETCH_ASSOC mode, and integers as used in
                        the FETCH_NUM mode. Note that the number of elements in
                        the array is double that which would be in the array if
                        you used either FETCH_ASSOC or FETCH_NUM. </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>Zend_Db::FETCH_COLUMN</constant> : return data
                        in an array of values. The value in each array is the
                        value returned by one column of the result set. By
                        default, this is the first column, indexed by 0. </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>Zend_Db::FETCH_OBJ</constant> : return data in
                        an array of objects. The default class is the
                            <acronym>PHP</acronym> built-in class stdClass.
                        Columns of the result set are available as public
                        properties of the object. </para>
                </listitem>
            </itemizedlist>

            <example id="zend.db.adapter.select.fetch-mode.example">
                <title>Using setFetchMode()</title>
                <programlisting language="php"><![CDATA[
$db->setFetchMode(Zend_Db::FETCH_OBJ);

$result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);

// $result is an array of objects
echo $result[0]->bug_description;
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.select.fetchassoc">

            <title>Fetching a Result Set as an Associative Array</title>

            <para> The <methodname>fetchAssoc()</methodname> method returns data
                in an array of associative arrays, regardless of what value you
                have set for the fetch mode. </para>

            <example id="zend.db.adapter.select.fetchassoc.example">
                <title>Using fetchAssoc()</title>
                <programlisting language="php"><![CDATA[
$db->setFetchMode(Zend_Db::FETCH_OBJ);

$result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);

// $result is an array of associative arrays, in spite of the fetch mode
echo $result[0]['bug_description'];
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.select.fetchcol">

            <title>Fetching a Single Column from a Result Set</title>

            <para> The <methodname>fetchCol()</methodname> method returns data
                in an array of values, regardless of the value you have set for
                the fetch mode. This only returns the first column returned by
                the query. Any other columns returned by the query are
                discarded. If you need to return a column other than the first,
                see <xref linkend="zend.db.statement.fetching.fetchcolumn"/> . </para>

            <example id="zend.db.adapter.select.fetchcol.example">
                <title>Using fetchCol()</title>
                <programlisting language="php"><![CDATA[
$db->setFetchMode(Zend_Db::FETCH_OBJ);

$result = $db->fetchCol(
    'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);

// contains bug_description; bug_id is not returned
echo $result[0];
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.select.fetchpairs">

            <title>Fetching Key-Value Pairs from a Result Set</title>

            <para> The <methodname>fetchPairs()</methodname> method returns data
                in an array of key-value pairs, as an associative array with a
                single entry per row. The key of this associative array is taken
                from the first column returned by the SELECT query. The value is
                taken from the second column returned by the SELECT query. Any
                other columns returned by the query are discarded. </para>

            <para> You should design the SELECT query so that the first column
                returned has unique values. If there are duplicates values in
                the first column, entries in the associative array will be
                overwritten. </para>

            <example id="zend.db.adapter.select.fetchpairs.example">
                <title>Using fetchPairs()</title>
                <programlisting language="php"><![CDATA[
$db->setFetchMode(Zend_Db::FETCH_OBJ);

$result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');

echo $result[2];
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.adapter.select.fetchrow">

            <title>Fetching a Single Row from a Result Set</title>

            <para> The <methodname>fetchRow()</methodname> method returns data
                using the current fetch mode, but it returns only the first row
                fetched from the result set. </para>

            <example id="zend.db.adapter.select.fetchrow.example">
                <title>Using fetchRow()</title>
                <programlisting language="php"><![CDATA[
$db->setFetchMode(Zend_Db::FETCH_OBJ);

$result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');

// note that $result is a single object, not an array of objects
echo $result->bug_description;
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.adapter.select.fetchone">

            <title>Fetching a Single Scalar from a Result Set</title>

            <para> The <methodname>fetchOne()</methodname> method is like a
                combination of <methodname>fetchRow()</methodname> with
                    <methodname>fetchCol()</methodname> , in that it returns
                data only for the first row fetched from the result set, and it
                returns only the value of the first column in that row.
                Therefore it returns only a single scalar value, not an array or
                an object. </para>

            <example id="zend.db.adapter.select.fetchone.example">
                <title>Using fetchOne()</title>
                <programlisting language="php"><![CDATA[
$result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');

// this is a single string value
echo $result;
]]></programlisting>
            </example>
        </sect3>

    </sect2>

    <sect2 id="zend.db.adapter.write">

        <title>Writing Changes to the Database</title>

        <para> You can use the Adapter class to write new data or change
            existing data in your database. This section describes methods to do
            these operations. </para>

        <sect3 id="zend.db.adapter.write.insert">

            <title>Inserting Data</title>

            <para> You can add new rows to a table in your database using the
                    <methodname>insert()</methodname> method. The first argument
                is a string that names the table, and the second argument is an
                associative array, mapping column names to data values. </para>

            <example id="zend.db.adapter.write.insert.example">
                <title>Inserting in a Table</title>
                <programlisting language="php"><![CDATA[
$data = array(
    'created_on'      => '2007-03-22',
    'bug_description' => 'Something wrong',
    'bug_status'      => 'NEW'
);

$db->insert('bugs', $data);
]]></programlisting>
            </example>

            <para> Columns you exclude from the array of data are not specified
                to the database. Therefore, they follow the same rules that an
                    <acronym>SQL</acronym> INSERT statement follows: if the
                column has a DEFAULT clause, the column takes that value in the
                row created, otherwise the column is left in a  <acronym>NULL</acronym> state. </para>

            <para> By default, the values in your data array are inserted using
                parameters. This reduces risk of some types of security issues.
                You don't need to apply escaping or quoting to values in the
                data array. </para>

            <para> You might need values in the data array to be treated as
                    <acronym>SQL</acronym> expressions, in which case they
                should not be quoted. By default, all data values passed as
                strings are treated as string literals. To specify that the
                value is an <acronym>SQL</acronym> expression and therefore
                should not be quoted, pass the value in the data array as an
                object of type <classname>Zend_Db_Expr</classname> instead of a
                plain string. </para>

            <example id="zend.db.adapter.write.insert.example2">
                <title>Inserting Expressions in a Table</title>
                <programlisting language="php"><![CDATA[
$data = array(
    'created_on'      => new Zend_Db_Expr('CURDATE()'),
    'bug_description' => 'Something wrong',
    'bug_status'      => 'NEW'
);

$db->insert('bugs', $data);
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.write.lastinsertid">

            <title>Retrieving a Generated Value</title>

            <para> Some <acronym>RDBMS</acronym> brands support
                auto-incrementing primary keys. A table defined this way
                generates a primary key value automatically during an INSERT of
                a new row. The return value of the
                    <methodname>insert()</methodname> method is
                    <emphasis>not</emphasis> the last inserted ID, because the
                table might not have an auto-incremented column. Instead, the
                return value is the number of rows affected (usually 1). </para>

            <para> If your table is defined with an auto-incrementing primary
                key, you can call the <methodname>lastInsertId()</methodname>
                method after the insert. This method returns the last value
                generated in the scope of the current database connection. </para>

            <example id="zend.db.adapter.write.lastinsertid.example-1">
                <title>Using lastInsertId() for an Auto-Increment Key</title>
                <programlisting language="php"><![CDATA[
$db->insert('bugs', $data);

// return the last value generated by an auto-increment column
$id = $db->lastInsertId();
]]></programlisting>
            </example>

            <para> Some <acronym>RDBMS</acronym> brands support a sequence
                object, which generates unique values to serve as primary key
                values. To support sequences, the
                    <methodname>lastInsertId()</methodname> method accepts two
                optional string arguments. These arguments name the table and
                the column, assuming you have followed the convention that a
                sequence is named using the table and column names for which the
                sequence generates values, and a suffix "_seq". This is based on
                the convention used by PostgreSQL when naming sequences for
                SERIAL columns. For example, a table "bugs" with primary key
                column "bug_id" would use a sequence named "bugs_bug_id_seq". </para>

            <example id="zend.db.adapter.write.lastinsertid.example-2">
                <title>Using lastInsertId() for a Sequence</title>
                <programlisting language="php"><![CDATA[
$db->insert('bugs', $data);

// return the last value generated by sequence 'bugs_bug_id_seq'.
$id = $db->lastInsertId('bugs', 'bug_id');

// alternatively, return the last value generated by sequence 'bugs_seq'.
$id = $db->lastInsertId('bugs');
]]></programlisting>
            </example>

            <para> If the name of your sequence object does not follow this
                naming convention, use the
                    <methodname>lastSequenceId()</methodname> method instead.
                This method takes a single string argument, naming the sequence
                literally. </para>

            <example id="zend.db.adapter.write.lastinsertid.example-3">
                <title>Using lastSequenceId()</title>
                <programlisting language="php"><![CDATA[
$db->insert('bugs', $data);

// return the last value generated by sequence 'bugs_id_gen'.
$id = $db->lastSequenceId('bugs_id_gen');
]]></programlisting>
            </example>

            <para> For <acronym>RDBMS</acronym> brands that don't support
                sequences, including MySQL, Microsoft <acronym>SQL</acronym>
                Server, and SQLite, the arguments to the lastInsertId() method
                are ignored, and the value returned is the most recent value
                generated for any table by INSERT operations during the current
                connection. For these <acronym>RDBMS</acronym> brands, the
                lastSequenceId() method always returns <constant>NULL</constant>
                . </para>

            <note>
                <title>Why Not Use "SELECT MAX(id) FROM table"?</title>
                <para> Sometimes this query returns the most recent primary key
                    value inserted into the table. However, this technique is
                    not safe to use in an environment where multiple clients are
                    inserting records to the database. It is possible, and
                    therefore is bound to happen eventually, that another client
                    inserts another row in the instant between the insert
                    performed by your client application and your query for the
                    MAX(id) value. Thus the value returned does not identify the
                    row you inserted, it identifies the row inserted by some
                    other client. There is no way to know when this has
                    happened. </para>
                <para> Using a strong transaction isolation mode such as
                    "repeatable read" can mitigate this risk, but some
                        <acronym>RDBMS</acronym> brands don't support the
                    transaction isolation required for this, or else your
                    application may use a lower transaction isolation mode by
                    design. </para>
                <para> Furthermore, using an expression like "MAX(id)+1" to
                    generate a new value for a primary key is not safe, because
                    two clients could do this query simultaneously, and then
                    both use the same calculated value for their next INSERT
                    operation. </para>
                <para> All <acronym>RDBMS</acronym> brands provide mechanisms to
                    generate unique values, and to return the last value
                    generated. These mechanisms necessarily work outside of the
                    scope of transaction isolation, so there is no chance of two
                    clients generating the same value, and there is no chance
                    that the value generated by another client could be reported
                    to your client's connection as the last value generated.
                </para>
            </note>

        </sect3>

        <sect3 id="zend.db.adapter.write.update">
            <title>Updating Data</title>

            <para> You can update rows in a database table using the
                    <methodname>update()</methodname> method of an Adapter. This
                method takes three arguments: the first is the name of the
                table; the second is an associative array mapping columns to
                change to new values to assign to these columns. </para>

            <para> The values in the data array are treated as string literals.
                See <xref linkend="zend.db.adapter.write.insert"/> for
                information on using <acronym>SQL</acronym> expressions in the
                data array. </para>

            <para> The third argument is a string containing an
                    <acronym>SQL</acronym> expression that is used as criteria
                for the rows to change. The values and identifiers in this
                argument are not quoted or escaped. You are responsible for
                ensuring that any dynamic content is interpolated into this
                string safely. See <xref linkend="zend.db.adapter.quoting"/> for
                methods to help you do this. </para>

            <para> The return value is the number of rows affected by the update
                operation. </para>

            <example id="zend.db.adapter.write.update.example">
                <title>Updating Rows</title>
                <programlisting language="php"><![CDATA[
$data = array(
    'updated_on'      => '2007-03-23',
    'bug_status'      => 'FIXED'
);

$n = $db->update('bugs', $data, 'bug_id = 2');
]]></programlisting>
            </example>

            <para> If you omit the third argument, then all rows in the database
                table are updated with the values specified in the data array. </para>

            <para> If you provide an array of strings as the third argument,
                these strings are joined together as terms in an expression
                separated by <constant>AND</constant> operators. </para>

            <example id="zend.db.adapter.write.update.example-array">
                <title>Updating Rows Using an Array of Expressions</title>
                <programlisting language="php"><![CDATA[
$data = array(
    'updated_on'      => '2007-03-23',
    'bug_status'      => 'FIXED'
);

$where[] = "reported_by = 'goofy'";
$where[] = "bug_status = 'OPEN'";

$n = $db->update('bugs', $data, $where);

// Resulting SQL is:
//  UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
//  WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
]]></programlisting>
            </example>

        </sect3>

        <sect3 id="zend.db.adapter.write.delete">
            <title>Deleting Data</title>
            <para> You can delete rows from a database table using the
                    <methodname>delete()</methodname> method. This method takes
                two arguments: the first is a string naming the table. </para>

            <para> The second argument is a string containing an
                    <acronym>SQL</acronym> expression that is used as criteria
                for the rows to delete. The values and identifiers in this
                argument are not quoted or escaped. You are responsible for
                ensuring that any dynamic content is interpolated into this
                string safely. See <xref linkend="zend.db.adapter.quoting"/> for
                methods to help you do this. </para>

            <para> The return value is the number of rows affected by the delete
                operation. </para>

            <example id="zend.db.adapter.write.delete.example">
                <title>Deleting Rows</title>
                <programlisting language="php"><![CDATA[
$n = $db->delete('bugs', 'bug_id = 3');
]]></programlisting>
            </example>

            <para> If you omit the second argument, the result is that all rows
                in the database table are deleted. </para>

            <para> If you provide an array of strings as the second argument,
                these strings are joined together as terms in an expression
                separated by <constant>AND</constant> operators. </para>

        </sect3>

    </sect2>

    <sect2 id="zend.db.adapter.quoting">

        <title>Quoting Values and Identifiers</title>

        <para> When you form <acronym>SQL</acronym> queries, often it is the
            case that you need to include the values of PHP variables in
                <acronym>SQL</acronym> expressions. This is risky, because if
            the value in a PHP string contains certain symbols, such as the
            quote symbol, it could result in invalid <acronym>SQL</acronym> .
            For example, notice the imbalanced quote characters in the following
            query: <programlisting language="php"><![CDATA[
$name = "O'Reilly";
$sql = "SELECT * FROM bugs WHERE reported_by = '$name'";

echo $sql;
// SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
]]></programlisting>
        </para>

        <para> Even worse is the risk that such code mistakes might be exploited
            deliberately by a person who is trying to manipulate the function of
            your web application. If they can specify the value of a
                <acronym>PHP</acronym> variable through the use of an
                <acronym>HTTP</acronym> parameter or other mechanism, they might
            be able to make your <acronym>SQL</acronym> queries do things that
            you didn't intend them to do, such as return data to which the
            person should not have privilege to read. This is a serious and
            widespread technique for violating application security, known as
            "SQL Injection" (see <ulink
                url="http://en.wikipedia.org/wiki/SQL_Injection"
                >http://en.wikipedia.org/wiki/SQL_Injection</ulink> ). </para>

        <para> The <classname>Zend_Db</classname> Adapter class provides
            convenient functions to help you reduce vulnerabilities to
                <acronym>SQL</acronym> Injection attacks in your
                <acronym>PHP</acronym> code. The solution is to escape special
            characters such as quotes in <acronym>PHP</acronym> values before
            they are interpolated into your <acronym>SQL</acronym> strings. This
            protects against both accidental and deliberate manipulation of
                <acronym>SQL</acronym> strings by <acronym>PHP</acronym>
            variables that contain special characters. </para>

        <sect3 id="zend.db.adapter.quoting.quote">

            <title>Using quote()</title>

            <para> The <methodname>quote()</methodname> method accepts a single
                argument, a scalar string value. It returns the value with
                special characters escaped in a manner appropriate for the
                    <acronym>RDBMS</acronym> you are using, and surrounded by
                string value delimiters. The standard <acronym>SQL</acronym>
                string value delimiter is the single-quote ( <code>'</code> ). </para>

            <example id="zend.db.adapter.quoting.quote.example">
                <title>Using quote()</title>
                <programlisting language="php"><![CDATA[
$name = $db->quote("O'Reilly");
echo $name;
// 'O\'Reilly'

$sql = "SELECT * FROM bugs WHERE reported_by = $name";

echo $sql;
// SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
]]></programlisting>
            </example>

            <para> Note that the return value of
                    <methodname>quote()</methodname> includes the quote
                delimiters around the string. This is different from some
                functions that escape special characters but do not add the
                quote delimiters, for example <ulink
                    url="http://www.php.net/mysqli_real_escape_string"
                    >mysql_real_escape_string()</ulink> . </para>

            <para> Values may need to be quoted or not quoted according to the
                    <acronym>SQL</acronym> datatype context in which they are
                used. For instance, in some RDBMS brands, an integer value must
                not be quoted as a string if it is compared to an integer-type
                column or expression. In other words, the following is an error
                in some <acronym>SQL</acronym> implementations, assuming
                    <code>intColumn</code> has a <acronym>SQL</acronym> datatype
                of <constant>INTEGER</constant>
                <programlisting language="php"><![CDATA[
SELECT * FROM atable WHERE intColumn = '123'
]]></programlisting>
            </para>

            <para> You can use the optional second argument to the
                    <methodname>quote()</methodname> method to apply quoting
                selectively for the <acronym>SQL</acronym> datatype you specify. </para>

            <example id="zend.db.adapter.quoting.quote.example-2">
                <title>Using quote() with a SQL Type</title>
                <programlisting language="php"><![CDATA[
$value = '1234';
$sql = 'SELECT * FROM atable WHERE intColumn = '
     . $db->quote($value, 'INTEGER');
]]></programlisting>
            </example>

            <para> Each <classname>Zend_Db_Adapter</classname> class has encoded
                the names of numeric <acronym>SQL</acronym> datatypes for the
                respective brand of <acronym>RDBMS</acronym> . You can also use
                the constants <constant>Zend_Db::INT_TYPE</constant> ,
                    <constant>Zend_Db::BIGINT_TYPE</constant> , and
                    <constant>Zend_Db::FLOAT_TYPE</constant> to write code in a
                more <acronym>RDBMS</acronym> -independent way. </para>

            <para>
                <classname>Zend_Db_Table</classname> specifies
                    <acronym>SQL</acronym> types to
                    <methodname>quote()</methodname> automatically when
                generating <acronym>SQL</acronym> queries that reference a
                table's key columns. </para>

        </sect3>

        <sect3 id="zend.db.adapter.quoting.quote-into">

            <title>Using quoteInto()</title>

            <para> The most typical usage of quoting is to interpolate a
                    <acronym>PHP</acronym> variable into a
                    <acronym>SQL</acronym> expression or statement. You can use
                the <methodname>quoteInto()</methodname> method to do this in
                one step. This method takes two arguments: the first argument is
                a string containing a placeholder symbol ( <code>?</code> ), and
                the second argument is a value or <acronym>PHP</acronym>
                variable that should be substituted for that placeholder. </para>

            <para> The placeholder symbol is the same symbol used by many
                    <acronym>RDBMS</acronym> brands for positional parameters,
                but the <methodname>quoteInto()</methodname> method only
                emulates query parameters. The method simply interpolates the
                value into the string, escapes special characters, and applies
                quotes around it. True query parameters maintain the separation
                between the <acronym>SQL</acronym> string and the parameters as
                the statement is parsed in the <acronym>RDBMS</acronym> server. </para>

            <example id="zend.db.adapter.quoting.quote-into.example">
                <title>Using quoteInto()</title>
                <programlisting language="php"><![CDATA[
$sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");

echo $sql;
// SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
]]></programlisting>
            </example>

            <para> You can use the optional third parameter of
                    <methodname>quoteInto()</methodname> to specify the
                    <acronym>SQL</acronym> datatype. Numeric datatypes are not
                quoted, and other types are quoted. </para>

            <example id="zend.db.adapter.quoting.quote-into.example-2">
                <title>Using quoteInto() with a SQL Type</title>
                <programlisting language="php"><![CDATA[
$sql = $db
    ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');

echo $sql;
// SELECT * FROM bugs WHERE reported_by = 1234
]]></programlisting>
            </example>

        </sect3>
        <sect3 id="zend.db.adapter.quoting.quote-identifier">

            <title>Using quoteIdentifier()</title>

            <para> Values are not the only part of <acronym>SQL</acronym> syntax
                that might need to be variable. If you use
                    <acronym>PHP</acronym> variables to name tables, columns, or
                other identifiers in your <acronym>SQL</acronym> statements, you
                might need to quote these strings too. By default,
                    <acronym>SQL</acronym> identifiers have syntax rules like
                    <acronym>PHP</acronym> and most other programming languages.
                For example, identifiers should not contain spaces, certain
                punctuation or special characters, or international characters.
                Also certain words are reserved for <acronym>SQL</acronym>
                syntax, and should not be used as identifiers. </para>

            <para> However, <acronym>SQL</acronym> has a feature called
                    <emphasis>delimited identifiers</emphasis> , which allows
                broader choices for the spelling of identifiers. If you enclose
                a <acronym>SQL</acronym> identifier in the proper types of
                quotes, you can use identifiers with spellings that would be
                invalid without the quotes. Delimited identifiers can contain
                spaces, punctuation, or international characters. You can also
                use <acronym>SQL</acronym> reserved words if you enclose them in
                identifier delimiters. </para>

            <para> The <methodname>quoteIdentifier()</methodname> method works
                like <methodname>quote()</methodname> , but it applies the
                identifier delimiter characters to the string according to the
                type of Adapter you use. For example, standard
                    <acronym>SQL</acronym> uses double-quotes ( <code>"</code> )
                for identifier delimiters, and most <acronym>RDBMS</acronym>
                brands use that symbol. MySQL uses back-quotes ( <code>`</code>
                ) by default. The <methodname>quoteIdentifier()</methodname>
                method also escapes special characters within the string
                argument. </para>

            <example id="zend.db.adapter.quoting.quote-identifier.example">
                <title>Using quoteIdentifier()</title>
                <programlisting language="php"><![CDATA[
// we might have a table name that is an SQL reserved word
$tableName = $db->quoteIdentifier("order");

$sql = "SELECT * FROM $tableName";

echo $sql
// SELECT * FROM "order"
]]></programlisting>
            </example>

            <para>
                <acronym>SQL</acronym> delimited identifiers are case-sensitive,
                unlike unquoted identifiers. Therefore, if you use delimited
                identifiers, you must use the spelling of the identifier exactly
                as it is stored in your schema, including the case of the
                letters. </para>

            <para> In most cases where <acronym>SQL</acronym> is generated
                within <classname>Zend_Db</classname> classes, the default is
                that all identifiers are delimited automatically. You can change
                this behavior with the option
                    <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> .
                Specify this when instantiating the Adapter. See <xref
                    linkend="zend.db.adapter.connecting.parameters.example2"/> . </para>

        </sect3>

    </sect2>

    <sect2 id="zend.db.adapter.transactions">

        <title>Controlling Database Transactions</title>

        <para> Databases define transactions as logical units of work that can
            be committed or rolled back as a single change, even if they operate
            on multiple tables. All queries to a database are executed within
            the context of a transaction, even if the database driver manages
            them implicitly. This is called <emphasis>auto-commit</emphasis>
            mode, in which the database driver creates a transaction for every
            statement you execute, and commits that transaction after your
                <acronym>SQL</acronym> statement has been executed. By default,
            all <classname>Zend_Db</classname> Adapter classes operate in
            auto-commit mode. </para>

        <para> Alternatively, you can specify the beginning and resolution of a
            transaction, and thus control how many <acronym>SQL</acronym>
            queries are included in a single group that is committed (or rolled
            back) as a single operation. Use the
                <methodname>beginTransaction()</methodname> method to initiate a
            transaction. Subsequent <acronym>SQL</acronym> statements are
            executed in the context of the same transaction until you resolve it
            explicitly. </para>

        <para> To resolve the transaction, use either the
                <methodname>commit()</methodname> or
                <methodname>rollBack()</methodname> methods. The
                <methodname>commit()</methodname> method marks changes made
            during your transaction as committed, which means the effects of
            these changes are shown in queries run in other transactions. </para>

        <para> The <methodname>rollBack()</methodname> method does the opposite:
            it discards the changes made during your transaction. The changes
            are effectively undone, and the state of the data returns to how it
            was before you began your transaction. However, rolling back your
            transaction has no effect on changes made by other transactions
            running concurrently. </para>

        <para> After you resolve this transaction,
                <classname>Zend_Db_Adapter</classname> returns to auto-commit
            mode until you call <methodname>beginTransaction()</methodname>
            again. </para>

        <example id="zend.db.adapter.transactions.example">
            <title>Managing a Transaction to Ensure Consistency</title>
            <programlisting language="php"><![CDATA[
// Start a transaction explicitly.
$db->beginTransaction();

try {
    // Attempt to execute one or more queries:
    $db->query(...);
    $db->query(...);
    $db->query(...);

    // If all succeed, commit the transaction and all changes
    // are committed at once.
    $db->commit();

} catch (Exception $e) {
    // If any of the queries failed and threw an exception,
    // we want to roll back the whole transaction, reversing
    // changes made in the transaction, even those that succeeded.
    // Thus all changes are committed together, or none are.
    $db->rollBack();
    echo $e->getMessage();
}
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.db.adapter.list-describe">

        <title>Listing and Describing Tables</title>

        <para> The <methodname>listTables()</methodname> method returns an array
            of strings, naming all tables in the current database. </para>

        <para> The <methodname>describeTable()</methodname> method returns an
            associative array of metadata about a table. Specify the name of the
            table as a string in the first argument to this method. The second
            argument is optional, and names the schema in which the table
            exists. </para>

        <para> The keys of the associative array returned are the column names
            of the table. The value corresponding to each column is also an
            associative array, with the following keys and values: </para>

        <table frame="all" cellpadding="5"
            id="zend.db.adapter.list-describe.metadata">
            <title>Metadata Fields Returned by describeTable()</title>
            <tgroup cols="3" align="left" colsep="1" rowsep="1">
                <thead>
                    <row>
                        <entry>Key</entry>
                        <entry>Type</entry>
                        <entry>Description</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>
                            <constant>SCHEMA_NAME</constant>
                        </entry>
                        <entry>(string)</entry>
                        <entry>Name of the database schema in which this table
                            exists.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>TABLE_NAME</constant>
                        </entry>
                        <entry>(string)</entry>
                        <entry>Name of the table to which this column
                            belongs.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>COLUMN_NAME</constant>
                        </entry>
                        <entry>(string)</entry>
                        <entry>Name of the column.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>COLUMN_POSITION</constant>
                        </entry>
                        <entry>(integer)</entry>
                        <entry>Ordinal position of the column in the
                            table.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>DATA_TYPE</constant>
                        </entry>
                        <entry>(string)</entry>
                        <entry>RDBMS name of the datatype of the column.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>DEFAULT</constant>
                        </entry>
                        <entry>(string)</entry>
                        <entry>Default value for the column, if any.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>NULLABLE</constant>
                        </entry>
                        <entry>(boolean)</entry>
                        <entry> <constant>TRUE</constant> if the column accepts
                            <acronym>SQL</acronym>  <constant>NULL</constant>s, <constant>FALSE</constant> if the
                            column has a <constant>NOT</constant> <constant>NULL</constant> constraint. </entry>
                    </row>
                    <row>
                        <entry>
                            <constant>LENGTH</constant>
                        </entry>
                        <entry>(integer)</entry>
                        <entry> Length or size of the column as reported by the
                                <acronym>RDBMS</acronym> . </entry>
                    </row>
                    <row>
                        <entry>
                            <constant>SCALE</constant>
                        </entry>
                        <entry>(integer)</entry>
                        <entry> Scale of <acronym>SQL</acronym> NUMERIC or
                                <constant>DECIMAL</constant> type. </entry>
                    </row>
                    <row>
                        <entry>
                            <constant>PRECISION</constant>
                        </entry>
                        <entry>(integer)</entry>
                        <entry> Precision of <acronym>SQL</acronym> NUMERIC or
                                <constant>DECIMAL</constant> type. </entry>
                    </row>
                    <row>
                        <entry>
                            <constant>UNSIGNED</constant>
                        </entry>
                        <entry>(boolean)</entry>
                        <entry> <constant>TRUE</constant> if an integer-based type is reported as
                                <constant>UNSIGNED</constant> . </entry>
                    </row>
                    <row>
                        <entry>
                            <constant>PRIMARY</constant>
                        </entry>
                        <entry>(boolean)</entry>
                        <entry><constant>TRUE</constant> if the column is part of the primary key of
                            this table.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>PRIMARY_POSITION</constant>
                        </entry>
                        <entry>(integer)</entry>
                        <entry>Ordinal position (1-based) of the column in the
                            primary key.</entry>
                    </row>
                    <row>
                        <entry>
                            <constant>IDENTITY</constant>
                        </entry>
                        <entry>(boolean)</entry>
                        <entry><constant>TRUE</constant> if the column uses an auto-generated
                            value.</entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <note>
            <title>How the IDENTITY Metadata Field Relates to Specific
                RDBMSs</title>
            <para> The IDENTITY metadata field was chosen as an 'idiomatic' term
                to represent a relation to surrogate keys. This field can be
                commonly known by the following values:- </para>
            <itemizedlist>
                <listitem>
                    <para>
                        <constant>IDENTITY</constant> - DB2, MSSQL </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>AUTO_INCREMENT</constant> - MySQL </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>SERIAL</constant> - PostgreSQL </para>
                </listitem>
                <listitem>
                    <para>
                        <constant>SEQUENCE</constant> - Oracle </para>
                </listitem>
            </itemizedlist>
        </note>

        <para> If no table exists matching the table name and optional schema
            name specified, then <methodname>describeTable()</methodname>
            returns an empty array. </para>

    </sect2>

    <sect2 id="zend.db.adapter.closing">

        <title>Closing a Connection</title>

        <para> Normally it is not necessary to close a database connection.
                <acronym>PHP</acronym> automatically cleans up all resources and
            the end of a request. Database extensions are designed to close the
            connection as the reference to the resource object is cleaned up. </para>

        <para> However, if you have a long-duration <acronym>PHP</acronym>
            script that initiates many database connections, you might need to
            close the connection, to avoid exhausting the capacity of your
                <acronym>RDBMS</acronym> server. You can use the Adapter's
                <methodname>closeConnection()</methodname> method to explicitly
            close the underlying database connection. </para>

        <para> Since release 1.7.2, you could check you are currently connected
            to the <acronym>RDBMS</acronym> server with the method
                <methodname>isConnected()</methodname> . This means that a
            connection resource has been initiated and wasn't closed. This
            function is not currently able to test for example a server side
            closing of the connection. This is internally use to close the
            connection. It allow you to close the connection multiple times
            without errors. It was already the case before 1.7.2 for
                <acronym>PDO</acronym> adapters but not for the others. </para>

        <example id="zend.db.adapter.closing.example">
            <title>Closing a Database Connection</title>
            <programlisting language="php"><![CDATA[
$db->closeConnection();
]]></programlisting>
        </example>

        <note>
            <title>Does Zend_Db Support Persistent Connections?</title>
            <para> Yes, persistence is supported through the addition of the
                <property>persistent</property> flag set to true in the
                configuration (not driver_configuration) of an adapter in
                    <classname>Zend_Db</classname> . </para>

            <example id="zend.db.adapter.connecting.persistence.example">
                <title>Using the Persitence Flag with the Oracle Adapter</title>
                <programlisting language="php"><![CDATA[
$db = Zend_Db::factory('Oracle', array(
    'host'       => '127.0.0.1',
    'username'   => 'webuser',
    'password'   => 'xxxxxxxx',
    'dbname'     => 'test',
    'persistent' => true
));
]]></programlisting>
            </example>

            <para> Please note that using persistent connections can cause an
                excess of idle connections on the <acronym>RDBMS</acronym>
                server, which causes more problems than any performance gain you
                might achieve by reducing the overhead of making connections. </para>
            <para> Database connections have state. That is, some objects in the
                    <acronym>RDBMS</acronym> server exist in session scope.
                Examples are locks, user variables, temporary tables, and
                information about the most recently executed query, such as rows
                affected, and last generated id value. If you use persistent
                connections, your application could access invalid or privileged
                data that were created in a previous <acronym>PHP</acronym>
                request. </para>
            <para> Currently, only Oracle, DB2, and the <acronym>PDO</acronym>
                adapters (where specified by <acronym>PHP</acronym> ) support
                persistence in <classname>Zend_Db</classname> . </para>
        </note>

    </sect2>

    <sect2 id="zend.db.adapter.other-statements">

        <title>Running Other Database Statements</title>

        <para> There might be cases in which you need to access the connection
            object directly, as provided by the <acronym>PHP</acronym> database
            extension. Some of these extensions may offer features that are not
            surfaced by methods of
                <classname>Zend_Db_Adapter_Abstract</classname> . </para>

        <para> For example, all <acronym>SQL</acronym> statements run by
                <classname>Zend_Db</classname> are prepared, then executed.
            However, some database features are incompatible with prepared
            statements. DDL statements like CREATE and ALTER cannot be prepared
            in MySQL. Also, <acronym>SQL</acronym> statements don't benefit from
            the <ulink
                url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html"
                >MySQL Query Cache</ulink> , prior to MySQL 5.1.17. </para>

        <para> Most <acronym>PHP</acronym> database extensions provide a method
            to execute <acronym>SQL</acronym> statements without preparing them.
            For example, in <acronym>PDO</acronym> , this method is
                <methodname>exec()</methodname> . You can access the connection
            object in the <acronym>PHP</acronym> extension directly using
            getConnection(). </para>

        <example id="zend.db.adapter.other-statements.example">
            <title>Running a Non-Prepared Statement in a PDO Adapter</title>
            <programlisting language="php"><![CDATA[
$result = $db->getConnection()->exec('DROP TABLE bugs');
]]></programlisting>
        </example>

        <para> Similarly, you can access other methods or properties that are
            specific to <acronym>PHP</acronym> database extensions. Be aware,
            though, that by doing this you might constrain your application to
            the interface provided by the extension for a specific brand of
                <acronym>RDBMS</acronym> . </para>

        <para> In future versions of <classname>Zend_Db</classname> , there will
            be opportunities to add method entry points for functionality that
            is common to the supported <acronym>PHP</acronym> database
            extensions. This will not affect backward compatibility. </para>

    </sect2>

    <sect2 id="zend.db.adapter.server-version">
        <title>Retrieving Server Version</title>

        <para> Since release 1.7.2, you could retrieve the server version in
                <acronym>PHP</acronym> syntax style to be able to use
                <methodname>version_compare()</methodname> . If the information
            isn't available, you will receive <constant>NULL</constant> . </para>

        <example id="zend.db.adapter.server-version.example">
            <title>Verifying server version before running a query</title>
            <programlisting language="php"><![CDATA[
$version = $db->getServerVersion();
if (!is_null($version)) {
    if (version_compare($version, '5.0.0', '>=')) {
        // do something
    } else {
        // do something else
    }
} else {
    // impossible to read server version
}
]]></programlisting>
        </example>
    </sect2>

    <sect2 id="zend.db.adapter.adapter-notes">

        <title>Notes on Specific Adapters</title>

        <para> This section lists differences between the Adapter classes of
            which you should be aware. </para>

        <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
            <title>IBM DB2</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the factory() method with the
                        name 'Db2'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extension ibm_db2. </para>
                </listitem>
                <listitem>
                    <para> IBM DB2 supports both sequences and auto-incrementing
                        keys. Therefore the arguments to
                            <methodname>lastInsertId()</methodname> are
                        optional. If you give no arguments, the Adapter returns
                        the last value generated for an auto-increment key. If
                        you give arguments, the Adapter returns the last value
                        generated by the sequence named according to the
                        convention ' <emphasis>table</emphasis> _
                            <emphasis>column</emphasis> _seq'. </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.mysqli">
            <title>MySQLi</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Mysqli'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter utilizes the <acronym>PHP</acronym>
                        extension mysqli. </para>
                </listitem>
                <listitem>
                    <para> MySQL does not support sequences, so
                            <methodname>lastInsertId()</methodname> ignores its
                        arguments and always returns the last value generated
                        for an auto-increment key. The
                            <methodname>lastSequenceId()</methodname> method
                        returns <constant>NULL</constant> . </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.oracle">
            <title>Oracle</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Oracle'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extension oci8. </para>
                </listitem>
                <listitem>
                    <para> Oracle does not support auto-incrementing keys, so
                        you should specify the name of a sequence to
                            <methodname>lastInsertId()</methodname> or
                            <methodname>lastSequenceId()</methodname> . </para>
                </listitem>
                <listitem>
                    <para> The Oracle extension does not support positional
                        parameters. You must use named parameters. </para>
                </listitem>
                <listitem>
                    <para> Currently the
                            <constant>Zend_Db::CASE_FOLDING</constant> option is
                        not supported by the Oracle adapter. To use this option
                        with Oracle, you must use the <acronym>PDO</acronym> OCI
                        adapter. </para>
                </listitem>
                <listitem>
                    <para> By default, LOB fields are returned as OCI-Lob
                        objects. You could retrieve them as string for all
                        requests by using driver options
                            <code>'lob_as_string'</code> or for particular
                        request by using
                            <methodname>setLobAsString(boolean)</methodname> on
                        adapter or on statement. </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
            <title>Microsoft SQL Server</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Sqlsrv'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extension sqlsrv </para>
                </listitem>
                <listitem>
                    <para> Microsoft <acronym>SQL</acronym> Server does not
                        support sequences, so
                            <methodname>lastInsertId()</methodname> ignores
                        primary key argument and returns the last value
                        generated for an auto-increment key if a table name is
                        specified or a last insert query returned id. The
                            <methodname>lastSequenceId()</methodname> method
                        returns <constant>NULL</constant> . </para>
                </listitem>
                <listitem>
                    <para>
                        <classname>Zend_Db_Adapter_Sqlsrv</classname> sets
                            <constant>QUOTED_IDENTIFIER ON</constant>
                        immediately after connecting to a <acronym>SQL</acronym>
                        Server database. This makes the driver use the standard
                            <acronym>SQL</acronym> identifier delimiter symbol (
                            <emphasis>"</emphasis> ) instead of the proprietary
                        square-brackets syntax <acronym>SQL</acronym> Server
                        uses for delimiting identifiers. </para>
                </listitem>
                <listitem>
                    <para> You can specify <property>driver_options</property>
                        as a key in the options array. The value can be a
                        anything from here <ulink
                            url="http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx"
                            >http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx</ulink>
                        . </para>
                </listitem>
                <listitem>
                    <para> You can use
                            <methodname>setTransactionIsolationLevel()</methodname>
                        to set isolation level for current connection. The value
                        can be <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>
                        , <constant>SQLSRV_TXN_READ_COMMITTED</constant> ,
                            <constant>SQLSRV_TXN_REPEATABLE_READ</constant> ,
                            <constant>SQLSRV_TXN_SNAPSHOT</constant> or
                            <constant>SQLSRV_TXN_SERIALIZABLE</constant> .
                    </para>
                </listitem>
                <listitem>
                    <para> As of Zend Framework 1.9, the minimal supported build
                        of the <acronym>PHP</acronym>
                        <acronym>SQL</acronym> Server extension from Microsoft
                        is 1.0.1924.0. and the <acronym>MSSQL</acronym> Server
                        Native Client version 9.00.3042.00. </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
            <title>PDO for IBM DB2 and Informix Dynamic Server (IDS)</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Ibm'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_ibm. </para>
                </listitem>
                <listitem>
                    <para> You must use at least <acronym>PDO</acronym> _IBM
                        extension version 1.2.2. If you have an earlier version
                        of this extension, you must upgrade the
                            <acronym>PDO</acronym> _IBM extension from
                            <acronym>PECL</acronym> . </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
            <title>PDO Microsoft SQL Server</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Mssql'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_mssql. </para>
                </listitem>
                <listitem>
                    <para> Microsoft <acronym>SQL</acronym> Server does not
                        support sequences, so
                            <methodname>lastInsertId()</methodname> ignores its
                        arguments and always returns the last value generated
                        for an auto-increment key. The
                            <methodname>lastSequenceId()</methodname> method
                        returns <constant>NULL</constant> . </para>
                </listitem>
                <listitem>
                    <para> If you are working with unicode strings in an
                        encoding other than UCS-2 (such as UTF-8), you may have
                        to perform a conversion in your application code or
                        store the data in a binary column. Please refer to
                            <ulink url="http://support.microsoft.com/kb/232580"
                            >Microsoft's Knowledge Base</ulink> for more
                        information. </para>
                </listitem>
                <listitem>
                    <para>
                        <classname>Zend_Db_Adapter_Pdo_Mssql</classname> sets
                            <constant>QUOTED_IDENTIFIER ON</constant>
                        immediately after connecting to a <acronym>SQL</acronym>
                        Server database. This makes the driver use the standard
                            <acronym>SQL</acronym> identifier delimiter symbol (
                            <code>"</code> ) instead of the proprietary
                        square-brackets syntax <acronym>SQL</acronym> Server
                        uses for delimiting identifiers. </para>
                </listitem>
                <listitem>
                    <para> You can specify <code>pdoType</code> as a key in the
                        options array. The value can be "mssql" (the default),
                        "dblib", "freetds", or "sybase". This option affects the
                        DSN prefix the adapter uses when constructing the DSN
                        string. Both "freetds" and "sybase" imply a prefix of
                        "sybase:", which is used for the <ulink
                            url="http://www.freetds.org/">FreeTDS</ulink> set of
                        libraries. See also <ulink
                            url="http://www.php.net/manual/en/ref.pdo-dblib.connection.php"
                            >
                            http://www.php.net/manual/en/ref.pdo-dblib.connection.php</ulink>
                        for more information on the DSN prefixes used in this
                        driver. </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
            <title>PDO MySQL</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Mysql'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_mysql. </para>
                </listitem>
                <listitem>
                    <para> MySQL does not support sequences, so
                            <methodname>lastInsertId()</methodname> ignores its
                        arguments and always returns the last value generated
                        for an auto-increment key. The
                            <methodname>lastSequenceId()</methodname> method
                        returns <constant>NULL</constant> . </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
            <title>PDO Oracle</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Oci'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_oci. </para>
                </listitem>
                <listitem>
                    <para> Oracle does not support auto-incrementing keys, so
                        you should specify the name of a sequence to
                            <methodname>lastInsertId()</methodname> or
                            <methodname>lastSequenceId()</methodname> . </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
            <title>PDO PostgreSQL</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Pgsql'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_pgsql. </para>
                </listitem>
                <listitem>
                    <para> PostgreSQL supports both sequences and
                        auto-incrementing keys. Therefore the arguments to
                            <methodname>lastInsertId()</methodname> are
                        optional. If you give no arguments, the Adapter returns
                        the last value generated for an auto-increment key. If
                        you give arguments, the Adapter returns the last value
                        generated by the sequence named according to the
                        convention ' <emphasis>table</emphasis> _
                            <emphasis>column</emphasis> _seq'. </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
            <title>PDO SQLite</title>
            <itemizedlist>
                <listitem>
                    <para> Specify this Adapter to the
                            <methodname>factory()</methodname> method with the
                        name 'Pdo_Sqlite'. </para>
                </listitem>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extensions pdo and pdo_sqlite. </para>
                </listitem>
                <listitem>
                    <para> SQLite does not support sequences, so
                            <methodname>lastInsertId()</methodname> ignores its
                        arguments and always returns the last value generated
                        for an auto-increment key. The
                            <methodname>lastSequenceId()</methodname> method
                        returns <constant>NULL</constant> . </para>
                </listitem>
                <listitem>
                    <para> To connect to an SQLite2 database, specify
                            <code>'sqlite2'=>true</code> in the array of
                        parameters when creating an instance of the
                            <classname>Pdo_Sqlite</classname> Adapter. </para>
                </listitem>
                <listitem>
                    <para> To connect to an in-memory SQLite database, specify
                            <code>'dbname'=>':memory:'</code> in the array of
                        parameters when creating an instance of the
                            <classname>Pdo_Sqlite</classname> Adapter. </para>
                </listitem>
                <listitem>
                    <para> Older versions of the SQLite driver for
                            <acronym>PHP</acronym> do not seem to support the
                        PRAGMA commands necessary to ensure that short column
                        names are used in result sets. If you have problems that
                        your result sets are returned with keys of the form
                        "tablename.columnname" when you do a join query, then
                        you should upgrade to the current version of
                            <acronym>PHP</acronym> . </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.db.adapter.adapter-notes.firebird">
            <title>Firebird/Interbase</title>
            <itemizedlist>
                <listitem>
                    <para> This Adapter uses the <acronym>PHP</acronym>
                        extension php_interbase. </para>
                </listitem>
                <listitem>
                    <para> Firebird/interbase does not support auto-incrementing
                        keys, so you should specify the name of a sequence to
                            <methodname>lastInsertId()</methodname> or
                            <methodname>lastSequenceId()</methodname> . </para>
                </listitem>
                <listitem>
                    <para> Currently the
                            <constant>Zend_Db::CASE_FOLDING</constant> option is
                        not supported by the Firebird/interbase adapter.
                        Unquoted identifiers are automatically returned in upper
                        case. </para>
                </listitem>

                <listitem>
                    <para> Adapter name is
                            <classname>ZendX_Db_Adapter_Firebird</classname> . </para>
                    <para> Remember to use the param adapterNamespace with value
                            <classname>ZendX_Db_Adapter</classname> . </para>
                    <para> We recommend to update the gds32.dll (or linux
                        equivalent) bundled with php, to the same version of the
                        server. For Firebird the equivalent gds32.dll is
                        fbclient.dll. </para>
                    <para> By default all identifiers (tables names, fields) are
                        returned in upper case. </para>
                </listitem>
            </itemizedlist>
        </sect3>

    </sect2>

</sect1>
