inc/dal.inc.php
changeset 4 55ed92aa7cf5
parent 1 58094faf794d
equal deleted inserted replaced
3:64525a2eb098 4:55ed92aa7cf5
     1 <?php
     1 <?php
     2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
     2 
     3 // +----------------------------------------------------------------------+
     3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
     4 // | PHP Version 4                                                        |
     4 
     5 // +----------------------------------------------------------------------+
     5 /**
     6 // | Copyright (c) 1997-2002 The PHP Group                                |
     6  * Database independent query interface
     7 // +----------------------------------------------------------------------+
     7  *
     8 // | This source file is subject to version 2.02 of the PHP license,      |
     8  * PHP versions 4 and 5
     9 // | that is bundled with this package in the file LICENSE, and is        |
     9  *
    10 // | available at through the world-wide-web at                           |
    10  * LICENSE: This source file is subject to version 3.0 of the PHP license
    11 // | http://www.php.net/license/2_02.txt.                                 |
    11  * that is available through the world-wide-web at the following URI:
    12 // | If you did not receive a copy of the PHP license and are unable to   |
    12  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
    13 // | obtain it through the world-wide-web, please send a note to          |
    13  * the PHP License and are unable to obtain it through the web, please
    14 // | license@php.net so we can mail you a copy immediately.               |
    14  * send a note to license@php.net so we can mail you a copy immediately.
    15 // +----------------------------------------------------------------------+
    15  *
    16 // | Authors: Stig Bakken <ssb@fast.no>                                   |
    16  * @category   Database
    17 // |          Tomas V.V.Cox <cox@idecnet.com>                             |
    17  * @package    DB
    18 // +----------------------------------------------------------------------+
    18  * @author     Stig Bakken <ssb@php.net>
    19 //
    19  * @author     Tomas V.V.Cox <cox@idecnet.com>
    20 // $Id: dal.inc.php,v 1.1 2002/10/27 19:18:42 azurazu Exp $
    20  * @author     Daniel Convissor <danielc@php.net>
    21 //
    21  * @copyright  1997-2005 The PHP Group
    22 // Database independent query interface.
    22  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
    23 //
    23  * @version    CVS: $Id: DB.php,v 1.80 2005/02/16 02:16:00 danielc Exp $
    24 
    24  * @link       http://pear.php.net/package/DB
    25 require_once "PEAR.php";
    25  */
    26 
    26 
    27 /*
    27 /**
    28  * The method mapErrorCode in each DB_dbtype implementation maps
    28  * Obtain the PEAR class so it can be extended from
    29  * native error codes to one of these.
    29  */
    30  *
    30 require_once 'PEAR.php';
    31  * If you add an error code here, make sure you also add a textual
    31 
    32  * version of it in DB::errorMessage().
    32 
    33  */
    33 // {{{ constants
    34 
    34 // {{{ error codes
    35 define("DB_OK",                         1);
    35 
    36 define("DB_ERROR",                     -1);
    36 /**#@+
    37 define("DB_ERROR_SYNTAX",              -2);
    37  * One of PEAR DB's portable error codes.
    38 define("DB_ERROR_CONSTRAINT",          -3);
    38  * @see DB_common::errorCode(), DB::errorMessage()
    39 define("DB_ERROR_NOT_FOUND",           -4);
    39  *
    40 define("DB_ERROR_ALREADY_EXISTS",      -5);
    40  * {@internal If you add an error code here, make sure you also add a textual
    41 define("DB_ERROR_UNSUPPORTED",         -6);
    41  * version of it in DB::errorMessage().}}
    42 define("DB_ERROR_MISMATCH",            -7);
    42  */
    43 define("DB_ERROR_INVALID",             -8);
    43 
    44 define("DB_ERROR_NOT_CAPABLE",         -9);
    44 /**
    45 define("DB_ERROR_TRUNCATED",          -10);
    45  * The code returned by many methods upon success
    46 define("DB_ERROR_INVALID_NUMBER",     -11);
    46  */
    47 define("DB_ERROR_INVALID_DATE",       -12);
    47 define('DB_OK', 1);
    48 define("DB_ERROR_DIVZERO",            -13);
    48 
    49 define("DB_ERROR_NODBSELECTED",       -14);
    49 /**
    50 define("DB_ERROR_CANNOT_CREATE",      -15);
    50  * Unkown error
    51 define("DB_ERROR_CANNOT_DELETE",      -16);
    51  */
    52 define("DB_ERROR_CANNOT_DROP",        -17);
    52 define('DB_ERROR', -1);
    53 define("DB_ERROR_NOSUCHTABLE",        -18);
    53 
    54 define("DB_ERROR_NOSUCHFIELD",        -19);
    54 /**
    55 define("DB_ERROR_NEED_MORE_DATA",     -20);
    55  * Syntax error
    56 define("DB_ERROR_NOT_LOCKED",         -21);
    56  */
    57 define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
    57 define('DB_ERROR_SYNTAX', -2);
    58 define("DB_ERROR_INVALID_DSN",        -23);
    58 
    59 define("DB_ERROR_CONNECT_FAILED",     -24);
    59 /**
    60 define("DB_ERROR_EXTENSION_NOT_FOUND",-25);
    60  * Tried to insert a duplicate value into a primary or unique index
    61 define("DB_ERROR_ACCESS_VIOLATION",   -26);
    61  */
    62 define("DB_ERROR_NOSUCHDB",           -27);
    62 define('DB_ERROR_CONSTRAINT', -3);
    63 
    63 
    64 /*
    64 /**
    65  * Warnings are not detected as errors by DB::isError(), and are not
    65  * An identifier in the query refers to a non-existant object
    66  * fatal.  You can detect whether an error is in fact a warning with
    66  */
    67  * DB::isWarning().
    67 define('DB_ERROR_NOT_FOUND', -4);
    68  *
    68 
    69  * @deprecated
    69 /**
    70  */
    70  * Tried to create a duplicate object
    71 
    71  */
    72 define('DB_WARNING',           -1000);
    72 define('DB_ERROR_ALREADY_EXISTS', -5);
    73 define('DB_WARNING_READ_ONLY', -1001);
    73 
    74 
    74 /**
    75 /*
    75  * The current driver does not support the action you attempted
    76  * These constants are used when storing information about prepared
    76  */
    77  * statements (using the "prepare" method in DB_dbtype).
    77 define('DB_ERROR_UNSUPPORTED', -6);
    78  *
    78 
    79  * The prepare/execute model in DB is mostly borrowed from the ODBC
    79 /**
    80  * extension, in a query the "?" character means a scalar parameter.
    80  * The number of parameters does not match the number of placeholders
    81  * There are two extensions though, a "&" character means an opaque
    81  */
    82  * parameter.  An opaque parameter is simply a file name, the real
    82 define('DB_ERROR_MISMATCH', -7);
    83  * data are in that file (useful for putting uploaded files into your
    83 
    84  * database and such). The "!" char means a parameter that must be
    84 /**
    85  * left as it is.
    85  * A literal submitted did not match the data type expected
    86  * They modify the quote behavoir:
    86  */
    87  * DB_PARAM_SCALAR (?) => 'original string quoted'
    87 define('DB_ERROR_INVALID', -8);
    88  * DB_PARAM_OPAQUE (&) => 'string from file quoted'
    88 
    89  * DB_PARAM_MISC   (!) => original string
    89 /**
    90  */
    90  * The current DBMS does not support the action you attempted
    91 
    91  */
       
    92 define('DB_ERROR_NOT_CAPABLE', -9);
       
    93 
       
    94 /**
       
    95  * A literal submitted was too long so the end of it was removed
       
    96  */
       
    97 define('DB_ERROR_TRUNCATED', -10);
       
    98 
       
    99 /**
       
   100  * A literal number submitted did not match the data type expected
       
   101  */
       
   102 define('DB_ERROR_INVALID_NUMBER', -11);
       
   103 
       
   104 /**
       
   105  * A literal date submitted did not match the data type expected
       
   106  */
       
   107 define('DB_ERROR_INVALID_DATE', -12);
       
   108 
       
   109 /**
       
   110  * Attempt to divide something by zero
       
   111  */
       
   112 define('DB_ERROR_DIVZERO', -13);
       
   113 
       
   114 /**
       
   115  * A database needs to be selected
       
   116  */
       
   117 define('DB_ERROR_NODBSELECTED', -14);
       
   118 
       
   119 /**
       
   120  * Could not create the object requested
       
   121  */
       
   122 define('DB_ERROR_CANNOT_CREATE', -15);
       
   123 
       
   124 /**
       
   125  * Could not drop the database requested because it does not exist
       
   126  */
       
   127 define('DB_ERROR_CANNOT_DROP', -17);
       
   128 
       
   129 /**
       
   130  * An identifier in the query refers to a non-existant table
       
   131  */
       
   132 define('DB_ERROR_NOSUCHTABLE', -18);
       
   133 
       
   134 /**
       
   135  * An identifier in the query refers to a non-existant column
       
   136  */
       
   137 define('DB_ERROR_NOSUCHFIELD', -19);
       
   138 
       
   139 /**
       
   140  * The data submitted to the method was inappropriate
       
   141  */
       
   142 define('DB_ERROR_NEED_MORE_DATA', -20);
       
   143 
       
   144 /**
       
   145  * The attempt to lock the table failed
       
   146  */
       
   147 define('DB_ERROR_NOT_LOCKED', -21);
       
   148 
       
   149 /**
       
   150  * The number of columns doesn't match the number of values
       
   151  */
       
   152 define('DB_ERROR_VALUE_COUNT_ON_ROW', -22);
       
   153 
       
   154 /**
       
   155  * The DSN submitted has problems
       
   156  */
       
   157 define('DB_ERROR_INVALID_DSN', -23);
       
   158 
       
   159 /**
       
   160  * Could not connect to the database
       
   161  */
       
   162 define('DB_ERROR_CONNECT_FAILED', -24);
       
   163 
       
   164 /**
       
   165  * The PHP extension needed for this DBMS could not be found
       
   166  */
       
   167 define('DB_ERROR_EXTENSION_NOT_FOUND',-25);
       
   168 
       
   169 /**
       
   170  * The present user has inadequate permissions to perform the task requestd
       
   171  */
       
   172 define('DB_ERROR_ACCESS_VIOLATION', -26);
       
   173 
       
   174 /**
       
   175  * The database requested does not exist
       
   176  */
       
   177 define('DB_ERROR_NOSUCHDB', -27);
       
   178 
       
   179 /**
       
   180  * Tried to insert a null value into a column that doesn't allow nulls
       
   181  */
       
   182 define('DB_ERROR_CONSTRAINT_NOT_NULL',-29);
       
   183 /**#@-*/
       
   184 
       
   185 
       
   186 // }}}
       
   187 // {{{ prepared statement-related
       
   188 
       
   189 
       
   190 /**#@+
       
   191  * Identifiers for the placeholders used in prepared statements.
       
   192  * @see DB_common::prepare()
       
   193  */
       
   194 
       
   195 /**
       
   196  * Indicates a scalar (<kbd>?</kbd>) placeholder was used
       
   197  *
       
   198  * Quote and escape the value as necessary.
       
   199  */
    92 define('DB_PARAM_SCALAR', 1);
   200 define('DB_PARAM_SCALAR', 1);
       
   201 
       
   202 /**
       
   203  * Indicates an opaque (<kbd>&</kbd>) placeholder was used
       
   204  *
       
   205  * The value presented is a file name.  Extract the contents of that file
       
   206  * and place them in this column.
       
   207  */
    93 define('DB_PARAM_OPAQUE', 2);
   208 define('DB_PARAM_OPAQUE', 2);
       
   209 
       
   210 /**
       
   211  * Indicates a misc (<kbd>!</kbd>) placeholder was used
       
   212  *
       
   213  * The value should not be quoted or escaped.
       
   214  */
    94 define('DB_PARAM_MISC',   3);
   215 define('DB_PARAM_MISC',   3);
    95 
   216 /**#@-*/
    96 /*
   217 
    97  * These constants define different ways of returning binary data
   218 
    98  * from queries.  Again, this model has been borrowed from the ODBC
   219 // }}}
    99  * extension.
   220 // {{{ binary data-related
   100  *
   221 
   101  * DB_BINMODE_PASSTHRU sends the data directly through to the browser
   222 
   102  * when data is fetched from the database.
   223 /**#@+
   103  * DB_BINMODE_RETURN lets you return data as usual.
   224  * The different ways of returning binary data from queries.
   104  * DB_BINMODE_CONVERT returns data as well, only it is converted to
   225  */
   105  * hex format, for example the string "123" would become "313233".
   226 
   106  */
   227 /**
   107 
   228  * Sends the fetched data straight through to output
       
   229  */
   108 define('DB_BINMODE_PASSTHRU', 1);
   230 define('DB_BINMODE_PASSTHRU', 1);
   109 define('DB_BINMODE_RETURN',   2);
   231 
   110 define('DB_BINMODE_CONVERT',  3);
   232 /**
   111 
   233  * Lets you return data as usual
   112 /**
   234  */
   113  * This is a special constant that tells DB the user hasn't specified
   235 define('DB_BINMODE_RETURN', 2);
   114  * any particular get mode, so the default should be used.
   236 
   115  */
   237 /**
   116 
   238  * Converts the data to hex format before returning it
       
   239  *
       
   240  * For example the string "123" would become "313233".
       
   241  */
       
   242 define('DB_BINMODE_CONVERT', 3);
       
   243 /**#@-*/
       
   244 
       
   245 
       
   246 // }}}
       
   247 // {{{ fetch modes
       
   248 
       
   249 
       
   250 /**#@+
       
   251  * Fetch Modes.
       
   252  * @see DB_common::setFetchMode()
       
   253  */
       
   254 
       
   255 /**
       
   256  * Indicates the current default fetch mode should be used
       
   257  * @see DB_common::$fetchmode
       
   258  */
   117 define('DB_FETCHMODE_DEFAULT', 0);
   259 define('DB_FETCHMODE_DEFAULT', 0);
   118 
   260 
   119 /**
   261 /**
   120  * Column data indexed by numbers, ordered from 0 and up
   262  * Column data indexed by numbers, ordered from 0 and up
   121  */
   263  */
   122 
       
   123 define('DB_FETCHMODE_ORDERED', 1);
   264 define('DB_FETCHMODE_ORDERED', 1);
   124 
   265 
   125 /**
   266 /**
   126  * Column data indexed by column names
   267  * Column data indexed by column names
   127  */
   268  */
   128 
       
   129 define('DB_FETCHMODE_ASSOC', 2);
   269 define('DB_FETCHMODE_ASSOC', 2);
   130 
   270 
   131 /**
   271 /**
   132  * Column data as object properties
   272  * Column data as object properties
   133  */
   273  */
   134 
       
   135 define('DB_FETCHMODE_OBJECT', 3);
   274 define('DB_FETCHMODE_OBJECT', 3);
   136 
   275 
   137 /**
   276 /**
   138  * For multi-dimensional results: normally the first level of arrays
   277  * For multi-dimensional results, make the column name the first level
   139  * is the row number, and the second level indexed by column number or name.
   278  * of the array and put the row number in the second level of the array
   140  * DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
   279  *
   141  * is the column name, and the second level the row number.
   280  * This is flipped from the normal behavior, which puts the row numbers
   142  */
   281  * in the first level of the array and the column names in the second level.
   143 
   282  */
   144 define('DB_FETCHMODE_FLIPPED', 4);
   283 define('DB_FETCHMODE_FLIPPED', 4);
   145 
   284 /**#@-*/
   146 /* for compatibility */
   285 
   147 
   286 /**#@+
       
   287  * Old fetch modes.  Left here for compatibility.
       
   288  */
   148 define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
   289 define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
   149 define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
   290 define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
   150 define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
   291 define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
   151 
   292 /**#@-*/
   152 /**
   293 
   153  * these are constants for the tableInfo-function
   294 
   154  * they are bitwised or'ed. so if there are more constants to be defined
   295 // }}}
   155  * in the future, adjust DB_TABLEINFO_FULL accordingly
   296 // {{{ tableInfo() && autoPrepare()-related
   156  */
   297 
   157 
   298 
       
   299 /**#@+
       
   300  * The type of information to return from the tableInfo() method.
       
   301  *
       
   302  * Bitwised constants, so they can be combined using <kbd>|</kbd>
       
   303  * and removed using <kbd>^</kbd>.
       
   304  *
       
   305  * @see DB_common::tableInfo()
       
   306  *
       
   307  * {@internal Since the TABLEINFO constants are bitwised, if more of them are
       
   308  * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}}
       
   309  */
   158 define('DB_TABLEINFO_ORDER', 1);
   310 define('DB_TABLEINFO_ORDER', 1);
   159 define('DB_TABLEINFO_ORDERTABLE', 2);
   311 define('DB_TABLEINFO_ORDERTABLE', 2);
   160 define('DB_TABLEINFO_FULL', 3);
   312 define('DB_TABLEINFO_FULL', 3);
   161 
   313 /**#@-*/
   162 /*
   314 
   163  * Used by autoPrepare()
   315 
       
   316 /**#@+
       
   317  * The type of query to create with the automatic query building methods.
       
   318  * @see DB_common::autoPrepare(), DB_common::autoExecute()
   164  */
   319  */
   165 define('DB_AUTOQUERY_INSERT', 1);
   320 define('DB_AUTOQUERY_INSERT', 1);
   166 define('DB_AUTOQUERY_UPDATE', 2);
   321 define('DB_AUTOQUERY_UPDATE', 2);
   167 
   322 /**#@-*/
   168 
   323 
   169 /**
   324 
       
   325 // }}}
       
   326 // {{{ portability modes
       
   327 
       
   328 
       
   329 /**#@+
       
   330  * Portability Modes.
       
   331  *
       
   332  * Bitwised constants, so they can be combined using <kbd>|</kbd>
       
   333  * and removed using <kbd>^</kbd>.
       
   334  *
       
   335  * @see DB_common::setOption()
       
   336  *
       
   337  * {@internal Since the PORTABILITY constants are bitwised, if more of them are
       
   338  * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}}
       
   339  */
       
   340 
       
   341 /**
       
   342  * Turn off all portability features
       
   343  */
       
   344 define('DB_PORTABILITY_NONE', 0);
       
   345 
       
   346 /**
       
   347  * Convert names of tables and fields to lower case
       
   348  * when using the get*(), fetch*() and tableInfo() methods
       
   349  */
       
   350 define('DB_PORTABILITY_LOWERCASE', 1);
       
   351 
       
   352 /**
       
   353  * Right trim the data output by get*() and fetch*()
       
   354  */
       
   355 define('DB_PORTABILITY_RTRIM', 2);
       
   356 
       
   357 /**
       
   358  * Force reporting the number of rows deleted
       
   359  */
       
   360 define('DB_PORTABILITY_DELETE_COUNT', 4);
       
   361 
       
   362 /**
       
   363  * Enable hack that makes numRows() work in Oracle
       
   364  */
       
   365 define('DB_PORTABILITY_NUMROWS', 8);
       
   366 
       
   367 /**
       
   368  * Makes certain error messages in certain drivers compatible
       
   369  * with those from other DBMS's
       
   370  *
       
   371  * + mysql, mysqli:  change unique/primary key constraints
       
   372  *   DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
       
   373  *
       
   374  * + odbc(access):  MS's ODBC driver reports 'no such field' as code
       
   375  *   07001, which means 'too few parameters.'  When this option is on
       
   376  *   that code gets mapped to DB_ERROR_NOSUCHFIELD.
       
   377  */
       
   378 define('DB_PORTABILITY_ERRORS', 16);
       
   379 
       
   380 /**
       
   381  * Convert null values to empty strings in data output by
       
   382  * get*() and fetch*()
       
   383  */
       
   384 define('DB_PORTABILITY_NULL_TO_EMPTY', 32);
       
   385 
       
   386 /**
       
   387  * Turn on all portability features
       
   388  */
       
   389 define('DB_PORTABILITY_ALL', 63);
       
   390 /**#@-*/
       
   391 
       
   392 // }}}
       
   393 
       
   394 
       
   395 // }}}
       
   396 // {{{ class DB
       
   397 
       
   398 /**
       
   399  * Database independent query interface
       
   400  *
   170  * The main "DB" class is simply a container class with some static
   401  * The main "DB" class is simply a container class with some static
   171  * methods for creating DB objects as well as some utility functions
   402  * methods for creating DB objects as well as some utility functions
   172  * common to all parts of DB.
   403  * common to all parts of DB.
   173  *
   404  *
   174  * The object model of DB is as follows (indentation means inheritance):
   405  * The object model of DB is as follows (indentation means inheritance):
   175  *
   406  * <pre>
   176  * DB           The main DB class.  This is simply a utility class
   407  * DB           The main DB class.  This is simply a utility class
   177  *              with some "static" methods for creating DB objects as
   408  *              with some "static" methods for creating DB objects as
   178  *              well as common utility functions for other DB classes.
   409  *              well as common utility functions for other DB classes.
   179  *
   410  *
   180  * DB_common    The base for each DB implementation.  Provides default
   411  * DB_common    The base for each DB implementation.  Provides default
   184  * |
   415  * |
   185  * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
   416  * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
   186  *              When calling DB::factory or DB::connect for MySQL
   417  *              When calling DB::factory or DB::connect for MySQL
   187  *              connections, the object returned is an instance of this
   418  *              connections, the object returned is an instance of this
   188  *              class.
   419  *              class.
   189  *
   420  * </pre>
   190  * @package  DB
   421  *
   191  * @author   Stig Bakken <ssb@fast.no>
   422  * @category   Database
   192  * @since    PHP 4.0
   423  * @package    DB
   193  */
   424  * @author     Stig Bakken <ssb@php.net>
   194 
   425  * @author     Tomas V.V.Cox <cox@idecnet.com>
       
   426  * @author     Daniel Convissor <danielc@php.net>
       
   427  * @copyright  1997-2005 The PHP Group
       
   428  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
       
   429  * @version    Release: @package_version@
       
   430  * @link       http://pear.php.net/package/DB
       
   431  */
   195 class DB
   432 class DB
   196 {
   433 {
   197     /**
   434     // {{{ &factory()
   198      * Create a new DB connection object for the specified database
   435 
   199      * type
   436     /**
   200      *
   437      * Create a new DB object for the specified database type but don't
   201      * @param string $type database type, for example "mysql"
   438      * connect to the database
   202      *
   439      *
   203      * @return mixed a newly created DB object, or a DB error code on
   440      * @param string $type     the database type (eg "mysql")
   204      * error
   441      * @param array  $options  an associative array of option names and values
   205      *
   442      *
   206      * access public
   443      * @return object  a new DB object.  A DB_Error object on failure.
   207      */
   444      *
   208 
   445      * @see DB_common::setOption()
   209     function &factory($type)
   446      */
   210     {
   447     function &factory($type, $options = false)
   211         @include_once("DB/${type}.php");
   448     {
       
   449         if (!is_array($options)) {
       
   450             $options = array('persistent' => $options);
       
   451         }
       
   452 
       
   453         if (isset($options['debug']) && $options['debug'] >= 2) {
       
   454             // expose php errors with sufficient debug level
       
   455             include_once "DB/{$type}.php";
       
   456         } else {
       
   457             @include_once "DB/{$type}.php";
       
   458         }
   212 
   459 
   213         $classname = "DB_${type}";
   460         $classname = "DB_${type}";
   214 
   461 
   215         if (!class_exists($classname)) {
   462         if (!class_exists($classname)) {
   216             return PEAR::raiseError(null, DB_ERROR_NOT_FOUND,
   463             $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
   217                                     null, null, null, 'DB_Error', true);
   464                                     "Unable to include the DB/{$type}.php"
       
   465                                     . " file for '$dsn'",
       
   466                                     'DB_Error', true);
       
   467             return $tmp;
   218         }
   468         }
   219 
   469 
   220         @$obj =& new $classname;
   470         @$obj =& new $classname;
   221 
   471 
       
   472         foreach ($options as $option => $value) {
       
   473             $test = $obj->setOption($option, $value);
       
   474             if (DB::isError($test)) {
       
   475                 return $test;
       
   476             }
       
   477         }
       
   478 
   222         return $obj;
   479         return $obj;
   223     }
   480     }
   224 
   481 
   225     /**
   482     // }}}
   226      * Create a new DB connection object and connect to the specified
   483     // {{{ &connect()
   227      * database
   484 
   228      *
   485     /**
   229      * @param mixed $dsn "data source name", see the DB::parseDSN
   486      * Create a new DB object including a connection to the specified database
   230      * method for a description of the dsn format.  Can also be
   487      *
   231      * specified as an array of the format returned by DB::parseDSN.
   488      * Example 1.
   232      *
   489      * <code>
   233      * @param mixed $options An associative array of option names and
   490      * require_once 'DB.php';
   234      * their values.  For backwards compatibility, this parameter may
   491      *
   235      * also be a boolean that tells whether the connection should be
   492      * $dsn = 'pgsql://user:password@host/database';
   236      * persistent.  See DB_common::setOption for more information on
   493      * $options = array(
   237      * connection options.
   494      *     'debug'       => 2,
   238      *
   495      *     'portability' => DB_PORTABILITY_ALL,
   239      * @return mixed a newly created DB connection object, or a DB
   496      * );
   240      * error object on error
   497      *
   241      *
   498      * $db =& DB::connect($dsn, $options);
   242      * @see DB::parseDSN
   499      * if (PEAR::isError($db)) {
   243      * @see DB::isError
   500      *     die($db->getMessage());
   244      * @see DB_common::setOption
   501      * }
   245      */
   502      * </code>
   246     function &connect($dsn, $options = false)
   503      *
   247     {
   504      * @param mixed $dsn      the string "data source name" or array in the
   248         if (is_array($dsn)) {
   505      *                         format returned by DB::parseDSN()
   249             $dsninfo = $dsn;
   506      * @param array $options  an associative array of option names and values
   250         } else {
   507      *
   251             $dsninfo = DB::parseDSN($dsn);
   508      * @return object  a new DB object.  A DB_Error object on failure.
   252         }
   509      *
   253         $type = $dsninfo["phptype"];
   510      * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(),
   254 
   511      *       DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(),
   255         if (is_array($options) && isset($options["debug"]) &&
   512      *       DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(),
   256             $options["debug"] >= 2) {
   513      *       DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(),
       
   514      *       DB_sybase::connect()
       
   515      *
       
   516      * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
       
   517      */
       
   518     function &connect($dsn, $options = array())
       
   519     {
       
   520         $dsninfo = DB::parseDSN($dsn);
       
   521         $type = $dsninfo['phptype'];
       
   522 
       
   523         if (!is_array($options)) {
       
   524             /*
       
   525              * For backwards compatibility.  $options used to be boolean,
       
   526              * indicating whether the connection should be persistent.
       
   527              */
       
   528             $options = array('persistent' => $options);
       
   529         }
       
   530 
       
   531         if (isset($options['debug']) && $options['debug'] >= 2) {
   257             // expose php errors with sufficient debug level
   532             // expose php errors with sufficient debug level
   258             include_once "DB/${type}.php";
   533             include_once "DB/${type}.php";
   259         } else {
   534         } else {
   260             @include_once "DB/${type}.php";
   535             @include_once "DB/${type}.php";
   261         }
   536         }
   262 
   537 
   263         $classname = "DB_${type}";
   538         $classname = "DB_${type}";
   264         if (!class_exists($classname)) {
   539         if (!class_exists($classname)) {
   265             return PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
   540             $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
   266                                     "Unable to include the DB/{$type}.php file for `$dsn'",
   541                                     "Unable to include the DB/{$type}.php"
       
   542                                     . " file for '$dsn'",
   267                                     'DB_Error', true);
   543                                     'DB_Error', true);
       
   544             return $tmp;
   268         }
   545         }
   269 
   546 
   270         @$obj =& new $classname;
   547         @$obj =& new $classname;
   271 
   548 
   272         if (is_array($options)) {
   549         foreach ($options as $option => $value) {
   273             foreach ($options as $option => $value) {
   550             $test = $obj->setOption($option, $value);
   274                 $test = $obj->setOption($option, $value);
   551             if (DB::isError($test)) {
   275                 if (DB::isError($test)) {
   552                 return $test;
   276                     return $test;
   553             }
   277                 }
   554         }
   278             }
   555 
   279         } else {
       
   280             $obj->setOption('persistent', $options);
       
   281         }
       
   282         $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
   556         $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
   283         if (DB::isError($err)) {
   557         if (DB::isError($err)) {
   284             $err->addUserInfo($dsn);
   558             $err->addUserInfo($dsn);
   285             return $err;
   559             return $err;
   286         }
   560         }
   287 
   561 
   288         return $obj;
   562         return $obj;
   289     }
   563     }
   290 
   564 
       
   565     // }}}
       
   566     // {{{ apiVersion()
       
   567 
   291     /**
   568     /**
   292      * Return the DB API version
   569      * Return the DB API version
   293      *
   570      *
   294      * @return int the DB API version number
   571      * @return string  the DB API version number
   295      *
       
   296      * @access public
       
   297      */
   572      */
   298     function apiVersion()
   573     function apiVersion()
   299     {
   574     {
   300         return 2;
   575         return '@package_version@';
   301     }
   576     }
   302 
   577 
   303     /**
   578     // }}}
   304      * Tell whether a result code from a DB method is an error
   579     // {{{ isError()
   305      *
   580 
   306      * @param int $value result code
   581     /**
   307      *
   582      * Determines if a variable is a DB_Error object
   308      * @return bool whether $value is an error
   583      *
   309      *
   584      * @param mixed $value  the variable to check
   310      * @access public
   585      *
       
   586      * @return bool  whether $value is DB_Error object
   311      */
   587      */
   312     function isError($value)
   588     function isError($value)
   313     {
   589     {
   314         return (is_object($value) &&
   590         return is_a($value, 'DB_Error');
   315                 (get_class($value) == 'db_error' ||
   591     }
   316                  is_subclass_of($value, 'db_error')));
   592 
   317     }
   593     // }}}
   318 
   594     // {{{ isConnection()
   319     /**
   595 
   320      * Tell whether a value is a DB connection
   596     /**
   321      *
   597      * Determines if a value is a DB_<driver> object
   322      * @param mixed $value value to test
   598      *
   323      *
   599      * @param mixed $value  the value to test
   324      * @return bool whether $value is a DB connection
   600      *
   325      *
   601      * @return bool  whether $value is a DB_<driver> object
   326      * @access public
       
   327      */
   602      */
   328     function isConnection($value)
   603     function isConnection($value)
   329     {
   604     {
   330         return (is_object($value) &&
   605         return (is_object($value) &&
   331                 is_subclass_of($value, 'db_common') &&
   606                 is_subclass_of($value, 'db_common') &&
   332                 method_exists($value, 'simpleQuery'));
   607                 method_exists($value, 'simpleQuery'));
   333     }
   608     }
   334 
   609 
   335     /**
   610     // }}}
   336      * Tell whether a query is a data manipulation query (insert,
   611     // {{{ isManip()
   337      * update or delete) or a data definition query (create, drop,
   612 
   338      * alter, grant, revoke).
   613     /**
   339      *
   614      * Tell whether a query is a data manipulation or data definition query
   340      * @access public
   615      *
   341      *
   616      * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
   342      * @param string $query the query
   617      * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
   343      *
   618      * REVOKE.
   344      * @return boolean whether $query is a data manipulation query
   619      *
       
   620      * @param string $query  the query
       
   621      *
       
   622      * @return boolean  whether $query is a data manipulation query
   345      */
   623      */
   346     function isManip($query)
   624     function isManip($query)
   347     {
   625     {
   348         $manips = 'INSERT|UPDATE|DELETE|'.'REPLACE|CREATE|DROP|'.
   626         $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
   349                   'ALTER|GRANT|REVOKE|'.'LOCK|UNLOCK';
   627                 . 'CREATE|DROP|'
   350         if (preg_match('/^\s*"?('.$manips.')\s+/i', $query)) {
   628                 . 'LOAD DATA|SELECT .* INTO|COPY|'
       
   629                 . 'ALTER|GRANT|REVOKE|'
       
   630                 . 'LOCK|UNLOCK';
       
   631         if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
   351             return true;
   632             return true;
   352         }
   633         }
   353         return false;
   634         return false;
   354     }
   635     }
   355 
   636 
       
   637     // }}}
       
   638     // {{{ errorMessage()
       
   639 
   356     /**
   640     /**
   357      * Return a textual error message for a DB error code
   641      * Return a textual error message for a DB error code
   358      *
   642      *
   359      * @param integer $value error code
   643      * @param integer $value  the DB error code
   360      *
   644      *
   361      * @return string error message, or false if the error code was
   645      * @return string  the error message or false if the error code was
   362      * not recognized
   646      *                  not recognized
   363      */
   647      */
   364     function errorMessage($value)
   648     function errorMessage($value)
   365     {
   649     {
   366         static $errorMessages;
   650         static $errorMessages;
   367         if (!isset($errorMessages)) {
   651         if (!isset($errorMessages)) {
   368             $errorMessages = array(
   652             $errorMessages = array(
   369                 DB_ERROR                    => 'unknown error',
   653                 DB_ERROR                    => 'unknown error',
       
   654                 DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
   370                 DB_ERROR_ALREADY_EXISTS     => 'already exists',
   655                 DB_ERROR_ALREADY_EXISTS     => 'already exists',
   371                 DB_ERROR_CANNOT_CREATE      => 'can not create',
   656                 DB_ERROR_CANNOT_CREATE      => 'can not create',
   372                 DB_ERROR_CANNOT_DELETE      => 'can not delete',
       
   373                 DB_ERROR_CANNOT_DROP        => 'can not drop',
   657                 DB_ERROR_CANNOT_DROP        => 'can not drop',
       
   658                 DB_ERROR_CONNECT_FAILED     => 'connect failed',
   374                 DB_ERROR_CONSTRAINT         => 'constraint violation',
   659                 DB_ERROR_CONSTRAINT         => 'constraint violation',
       
   660                 DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
   375                 DB_ERROR_DIVZERO            => 'division by zero',
   661                 DB_ERROR_DIVZERO            => 'division by zero',
       
   662                 DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
   376                 DB_ERROR_INVALID            => 'invalid',
   663                 DB_ERROR_INVALID            => 'invalid',
   377                 DB_ERROR_INVALID_DATE       => 'invalid date or time',
   664                 DB_ERROR_INVALID_DATE       => 'invalid date or time',
       
   665                 DB_ERROR_INVALID_DSN        => 'invalid DSN',
   378                 DB_ERROR_INVALID_NUMBER     => 'invalid number',
   666                 DB_ERROR_INVALID_NUMBER     => 'invalid number',
   379                 DB_ERROR_MISMATCH           => 'mismatch',
   667                 DB_ERROR_MISMATCH           => 'mismatch',
       
   668                 DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
   380                 DB_ERROR_NODBSELECTED       => 'no database selected',
   669                 DB_ERROR_NODBSELECTED       => 'no database selected',
       
   670                 DB_ERROR_NOSUCHDB           => 'no such database',
   381                 DB_ERROR_NOSUCHFIELD        => 'no such field',
   671                 DB_ERROR_NOSUCHFIELD        => 'no such field',
   382                 DB_ERROR_NOSUCHTABLE        => 'no such table',
   672                 DB_ERROR_NOSUCHTABLE        => 'no such table',
   383                 DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
   673                 DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
   384                 DB_ERROR_NOT_FOUND          => 'not found',
   674                 DB_ERROR_NOT_FOUND          => 'not found',
   385                 DB_ERROR_NOT_LOCKED         => 'not locked',
   675                 DB_ERROR_NOT_LOCKED         => 'not locked',
   386                 DB_ERROR_SYNTAX             => 'syntax error',
   676                 DB_ERROR_SYNTAX             => 'syntax error',
   387                 DB_ERROR_UNSUPPORTED        => 'not supported',
   677                 DB_ERROR_UNSUPPORTED        => 'not supported',
       
   678                 DB_ERROR_TRUNCATED          => 'truncated',
   388                 DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
   679                 DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
   389                 DB_ERROR_INVALID_DSN        => 'invalid DSN',
       
   390                 DB_ERROR_CONNECT_FAILED     => 'connect failed',
       
   391                 DB_OK                       => 'no error',
   680                 DB_OK                       => 'no error',
   392                 DB_WARNING                  => 'unknown warning',
       
   393                 DB_WARNING_READ_ONLY        => 'read only',
       
   394                 DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
       
   395                 DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
       
   396                 DB_ERROR_NOSUCHDB           => 'no such database',
       
   397                 DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions'
       
   398             );
   681             );
   399         }
   682         }
   400 
   683 
   401         if (DB::isError($value)) {
   684         if (DB::isError($value)) {
   402             $value = $value->getCode();
   685             $value = $value->getCode();
   403         }
   686         }
   404 
   687 
   405         return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR];
   688         return isset($errorMessages[$value]) ? $errorMessages[$value]
   406     }
   689                      : $errorMessages[DB_ERROR];
       
   690     }
       
   691 
       
   692     // }}}
       
   693     // {{{ parseDSN()
   407 
   694 
   408     /**
   695     /**
   409      * Parse a data source name
   696      * Parse a data source name
   410      *
   697      *
   411      * A array with the following keys will be returned:
   698      * Additional keys can be added by appending a URI query string to the
   412      *  phptype: Database backend used in PHP (mysql, odbc etc.)
   699      * end of the DSN.
   413      *  dbsyntax: Database used with regards to SQL syntax etc.
       
   414      *  protocol: Communication protocol to use (tcp, unix etc.)
       
   415      *  hostspec: Host specification (hostname[:port])
       
   416      *  database: Database to use on the DBMS server
       
   417      *  username: User name for login
       
   418      *  password: Password for login
       
   419      *
   700      *
   420      * The format of the supplied DSN is in its fullest form:
   701      * The format of the supplied DSN is in its fullest form:
   421      *
   702      * <code>
   422      *  phptype(dbsyntax)://username:password@protocol+hostspec/database
   703      *  phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
       
   704      * </code>
   423      *
   705      *
   424      * Most variations are allowed:
   706      * Most variations are allowed:
   425      *
   707      * <code>
   426      *  phptype://username:password@protocol+hostspec:110//usr/db_file.db
   708      *  phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
   427      *  phptype://username:password@hostspec/database_name
   709      *  phptype://username:password@hostspec/database_name
   428      *  phptype://username:password@hostspec
   710      *  phptype://username:password@hostspec
   429      *  phptype://username@hostspec
   711      *  phptype://username@hostspec
   430      *  phptype://hostspec/database
   712      *  phptype://hostspec/database
   431      *  phptype://hostspec
   713      *  phptype://hostspec
   432      *  phptype(dbsyntax)
   714      *  phptype(dbsyntax)
   433      *  phptype
   715      *  phptype
       
   716      * </code>
   434      *
   717      *
   435      * @param string $dsn Data Source Name to be parsed
   718      * @param string $dsn Data Source Name to be parsed
   436      *
   719      *
   437      * @return array an associative array
   720      * @return array an associative array with the following keys:
   438      *
   721      *  + phptype:  Database backend used in PHP (mysql, odbc etc.)
   439      * @author Tomas V.V.Cox <cox@idecnet.com>
   722      *  + dbsyntax: Database used with regards to SQL syntax etc.
       
   723      *  + protocol: Communication protocol to use (tcp, unix etc.)
       
   724      *  + hostspec: Host specification (hostname[:port])
       
   725      *  + database: Database to use on the DBMS server
       
   726      *  + username: User name for login
       
   727      *  + password: Password for login
   440      */
   728      */
   441     function parseDSN($dsn)
   729     function parseDSN($dsn)
   442     {
   730     {
   443         if (is_array($dsn)) {
       
   444             return $dsn;
       
   445         }
       
   446 
       
   447         $parsed = array(
   731         $parsed = array(
   448             'phptype'  => false,
   732             'phptype'  => false,
   449             'dbsyntax' => false,
   733             'dbsyntax' => false,
   450             'username' => false,
   734             'username' => false,
   451             'password' => false,
   735             'password' => false,
   452             'protocol' => false,
   736             'protocol' => false,
   453             'hostspec' => false,
   737             'hostspec' => false,
   454             'port'     => false,
   738             'port'     => false,
   455             'socket'   => false,
   739             'socket'   => false,
   456             'database' => false
   740             'database' => false,
   457         );
   741         );
       
   742 
       
   743         if (is_array($dsn)) {
       
   744             $dsn = array_merge($parsed, $dsn);
       
   745             if (!$dsn['dbsyntax']) {
       
   746                 $dsn['dbsyntax'] = $dsn['phptype'];
       
   747             }
       
   748             return $dsn;
       
   749         }
   458 
   750 
   459         // Find phptype and dbsyntax
   751         // Find phptype and dbsyntax
   460         if (($pos = strpos($dsn, '://')) !== false) {
   752         if (($pos = strpos($dsn, '://')) !== false) {
   461             $str = substr($dsn, 0, $pos);
   753             $str = substr($dsn, 0, $pos);
   462             $dsn = substr($dsn, $pos + 3);
   754             $dsn = substr($dsn, $pos + 3);
   463         } else {
   755         } else {
   464             $str = $dsn;
   756             $str = $dsn;
   465             $dsn = NULL;
   757             $dsn = null;
   466         }
   758         }
   467 
   759 
   468         // Get phptype and dbsyntax
   760         // Get phptype and dbsyntax
   469         // $str => phptype(dbsyntax)
   761         // $str => phptype(dbsyntax)
   470         if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
   762         if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
   471             $parsed['phptype']  = $arr[1];
   763             $parsed['phptype']  = $arr[1];
   472             $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
   764             $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
   473         } else {
   765         } else {
   474             $parsed['phptype']  = $str;
   766             $parsed['phptype']  = $str;
   475             $parsed['dbsyntax'] = $str;
   767             $parsed['dbsyntax'] = $str;
   476         }
   768         }
   477 
   769 
   478         if (empty($dsn)) {
   770         if (!count($dsn)) {
   479             return $parsed;
   771             return $parsed;
   480         }
   772         }
   481 
   773 
   482         // Get (if found): username and password
   774         // Get (if found): username and password
   483         // $dsn => username:password@protocol+hostspec/database
   775         // $dsn => username:password@protocol+hostspec/database
   484         if (($at = strrpos($dsn,'@')) !== false) {
   776         if (($at = strrpos($dsn,'@')) !== false) {
   485             $str = substr($dsn, 0, $at);
   777             $str = substr($dsn, 0, $at);
   486             $dsn = substr($dsn, $at + 1);
   778             $dsn = substr($dsn, $at + 1);
   487             if (($pos = strpos($str, ':')) !== false) {
   779             if (($pos = strpos($str, ':')) !== false) {
   488                 $parsed['username'] = urldecode(substr($str, 0, $pos));
   780                 $parsed['username'] = rawurldecode(substr($str, 0, $pos));
   489                 $parsed['password'] = urldecode(substr($str, $pos + 1));
   781                 $parsed['password'] = rawurldecode(substr($str, $pos + 1));
   490             } else {
   782             } else {
   491                 $parsed['username'] = urldecode($str);
   783                 $parsed['username'] = rawurldecode($str);
   492             }
   784             }
   493         }
   785         }
   494 
   786 
   495         // Find protocol and hostspec
   787         // Find protocol and hostspec
   496 
   788 
   497         // $dsn => proto(proto_opts)/database
       
   498         if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
   789         if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
       
   790             // $dsn => proto(proto_opts)/database
   499             $proto       = $match[1];
   791             $proto       = $match[1];
   500             $proto_opts  = (!empty($match[2])) ? $match[2] : false;
   792             $proto_opts  = $match[2] ? $match[2] : false;
   501             $dsn         = $match[3];
   793             $dsn         = $match[3];
   502 
   794 
   503         // $dsn => protocol+hostspec/database (old format)
       
   504         } else {
   795         } else {
       
   796             // $dsn => protocol+hostspec/database (old format)
   505             if (strpos($dsn, '+') !== false) {
   797             if (strpos($dsn, '+') !== false) {
   506                 list($proto, $dsn) = explode('+', $dsn, 2);
   798                 list($proto, $dsn) = explode('+', $dsn, 2);
   507             }
   799             }
   508             if (strpos($dsn, '/') !== false) {
   800             if (strpos($dsn, '/') !== false) {
   509                 list($proto_opts, $dsn) = explode('/', $dsn, 2);
   801                 list($proto_opts, $dsn) = explode('/', $dsn, 2);
   513             }
   805             }
   514         }
   806         }
   515 
   807 
   516         // process the different protocol options
   808         // process the different protocol options
   517         $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
   809         $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
   518         $proto_opts = urldecode($proto_opts);
   810         $proto_opts = rawurldecode($proto_opts);
   519         if ($parsed['protocol'] == 'tcp') {
   811         if ($parsed['protocol'] == 'tcp') {
   520             if (strpos($proto_opts, ':') !== false) {
   812             if (strpos($proto_opts, ':') !== false) {
   521                 list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts);
   813                 list($parsed['hostspec'],
       
   814                      $parsed['port']) = explode(':', $proto_opts);
   522             } else {
   815             } else {
   523                 $parsed['hostspec'] = $proto_opts;
   816                 $parsed['hostspec'] = $proto_opts;
   524             }
   817             }
   525         } elseif ($parsed['protocol'] == 'unix') {
   818         } elseif ($parsed['protocol'] == 'unix') {
   526             $parsed['socket'] = $proto_opts;
   819             $parsed['socket'] = $proto_opts;
   527         }
   820         }
   528 
   821 
   529         // Get dabase if any
   822         // Get dabase if any
   530         // $dsn => database
   823         // $dsn => database
   531         if (!empty($dsn)) {
   824         if ($dsn) {
   532             // /database
       
   533             if (($pos = strpos($dsn, '?')) === false) {
   825             if (($pos = strpos($dsn, '?')) === false) {
   534                 $parsed['database'] = $dsn;
   826                 // /database
   535             // /database?param1=value1&param2=value2
   827                 $parsed['database'] = rawurldecode($dsn);
   536             } else {
   828             } else {
   537                 $parsed['database'] = substr($dsn, 0, $pos);
   829                 // /database?param1=value1&param2=value2
       
   830                 $parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
   538                 $dsn = substr($dsn, $pos + 1);
   831                 $dsn = substr($dsn, $pos + 1);
   539                 if (strpos($dsn, '&') !== false) {
   832                 if (strpos($dsn, '&') !== false) {
   540                     $opts = explode('&', $dsn);
   833                     $opts = explode('&', $dsn);
   541                 } else { // database?param1=value1
   834                 } else { // database?param1=value1
   542                     $opts = array($dsn);
   835                     $opts = array($dsn);
   543                 }
   836                 }
   544                 foreach ($opts as $opt) {
   837                 foreach ($opts as $opt) {
   545                     list($key, $value) = explode('=', $opt);
   838                     list($key, $value) = explode('=', $opt);
   546                     if (!isset($parsed[$key])) { // don't allow params overwrite
   839                     if (!isset($parsed[$key])) {
   547                         $parsed[$key] = urldecode($value);
   840                         // don't allow params overwrite
       
   841                         $parsed[$key] = rawurldecode($value);
   548                     }
   842                     }
   549                 }
   843                 }
   550             }
   844             }
   551         }
   845         }
   552 
   846 
   553         return $parsed;
   847         return $parsed;
   554     }
   848     }
   555 
   849 
   556     /**
   850     // }}}
   557      * Load a PHP database extension if it is not loaded already.
       
   558      *
       
   559      * @access public
       
   560      *
       
   561      * @param string $name the base name of the extension (without the .so or
       
   562      *                     .dll suffix)
       
   563      *
       
   564      * @return boolean true if the extension was already or successfully
       
   565      *                 loaded, false if it could not be loaded
       
   566      */
       
   567     function assertExtension($name)
       
   568     {
       
   569         if (!extension_loaded($name)) {
       
   570             $dlext = OS_WINDOWS ? '.dll' : '.so';
       
   571             @dl($name . $dlext);
       
   572             return extension_loaded($name);
       
   573         }
       
   574         return true;
       
   575     }
       
   576 }
   851 }
   577 
   852 
       
   853 // }}}
       
   854 // {{{ class DB_Error
       
   855 
   578 /**
   856 /**
   579  * DB_Error implements a class for reporting portable database error
   857  * DB_Error implements a class for reporting portable database error
   580  * messages.
   858  * messages
   581  *
   859  *
   582  * @package  DB
   860  * @category   Database
   583  * @author Stig Bakken <ssb@fast.no>
   861  * @package    DB
       
   862  * @author     Stig Bakken <ssb@php.net>
       
   863  * @copyright  1997-2005 The PHP Group
       
   864  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
       
   865  * @version    Release: @package_version@
       
   866  * @link       http://pear.php.net/package/DB
   584  */
   867  */
   585 class DB_Error extends PEAR_Error
   868 class DB_Error extends PEAR_Error
   586 {
   869 {
   587     /**
   870     // {{{ constructor
   588      * DB_Error constructor.
   871 
   589      *
   872     /**
   590      * @param mixed   $code   DB error code, or string with error message.
   873      * DB_Error constructor
   591      * @param integer $mode   what "error mode" to operate in
   874      *
   592      * @param integer $level  what error level to use for $mode & PEAR_ERROR_TRIGGER
   875      * @param mixed $code       DB error code, or string with error message
   593      * @param mixed   $debuginfo  additional debug info, such as the last query
   876      * @param int   $mode       what "error mode" to operate in
   594      *
   877      * @param int   $level      what error level to use for $mode &
   595      * @access public
   878      *                           PEAR_ERROR_TRIGGER
       
   879      * @param mixed $debuginfo  additional debug info, such as the last query
   596      *
   880      *
   597      * @see PEAR_Error
   881      * @see PEAR_Error
   598      */
   882      */
   599 
       
   600     function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
   883     function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
   601               $level = E_USER_NOTICE, $debuginfo = null)
   884                       $level = E_USER_NOTICE, $debuginfo = null)
   602     {
   885     {
   603         if (is_int($code)) {
   886         if (is_int($code)) {
   604             $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
   887             $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code,
       
   888                               $mode, $level, $debuginfo);
   605         } else {
   889         } else {
   606             $this->PEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo);
   890             $this->PEAR_Error("DB Error: $code", DB_ERROR,
   607         }
   891                               $mode, $level, $debuginfo);
   608     }
   892         }
       
   893     }
       
   894 
       
   895     // }}}
   609 }
   896 }
   610 
   897 
   611 /**
   898 // }}}
   612  * This class implements a wrapper for a DB result set.
   899 // {{{ class DB_result
       
   900 
       
   901 /**
       
   902  * This class implements a wrapper for a DB result set
       
   903  *
   613  * A new instance of this class will be returned by the DB implementation
   904  * A new instance of this class will be returned by the DB implementation
   614  * after processing a query that returns data.
   905  * after processing a query that returns data.
   615  *
   906  *
   616  * @package  DB
   907  * @category   Database
   617  * @author Stig Bakken <ssb@fast.no>
   908  * @package    DB
   618  */
   909  * @author     Stig Bakken <ssb@php.net>
   619 
   910  * @copyright  1997-2005 The PHP Group
       
   911  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
       
   912  * @version    Release: @package_version@
       
   913  * @link       http://pear.php.net/package/DB
       
   914  */
   620 class DB_result
   915 class DB_result
   621 {
   916 {
       
   917     // {{{ properties
       
   918 
       
   919     /**
       
   920      * Should results be freed automatically when there are no more rows?
       
   921      * @var boolean
       
   922      * @see DB_common::$options
       
   923      */
       
   924     var $autofree;
       
   925 
       
   926     /**
       
   927      * A reference to the DB_<driver> object
       
   928      * @var object
       
   929      */
   622     var $dbh;
   930     var $dbh;
       
   931 
       
   932     /**
       
   933      * The current default fetch mode
       
   934      * @var integer
       
   935      * @see DB_common::$fetchmode
       
   936      */
       
   937     var $fetchmode;
       
   938 
       
   939     /**
       
   940      * The name of the class into which results should be fetched when
       
   941      * DB_FETCHMODE_OBJECT is in effect
       
   942      *
       
   943      * @var string
       
   944      * @see DB_common::$fetchmode_object_class
       
   945      */
       
   946     var $fetchmode_object_class;
       
   947 
       
   948     /**
       
   949      * The number of rows to fetch from a limit query
       
   950      * @var integer
       
   951      */
       
   952     var $limit_count = null;
       
   953 
       
   954     /**
       
   955      * The row to start fetching from in limit queries
       
   956      * @var integer
       
   957      */
       
   958     var $limit_from = null;
       
   959 
       
   960     /**
       
   961      * The execute parameters that created this result
       
   962      * @var array
       
   963      * @since Property available since Release 1.7.0
       
   964      */
       
   965     var $parameters;
       
   966 
       
   967     /**
       
   968      * The query string that created this result
       
   969      *
       
   970      * Copied here incase it changes in $dbh, which is referenced
       
   971      *
       
   972      * @var string
       
   973      * @since Property available since Release 1.7.0
       
   974      */
       
   975     var $query;
       
   976 
       
   977     /**
       
   978      * The query result resource id created by PHP
       
   979      * @var resource
       
   980      */
   623     var $result;
   981     var $result;
       
   982 
       
   983     /**
       
   984      * The present row being dealt with
       
   985      * @var integer
       
   986      */
   624     var $row_counter = null;
   987     var $row_counter = null;
   625     /**
   988 
   626     * for limit queries, the row to start fetching
   989     /**
   627     * @var integer
   990      * The prepared statement resource id created by PHP in $dbh
   628     */
   991      *
   629     var $limit_from  = null;
   992      * This resource is only available when the result set was created using
   630 
   993      * a driver's native execute() method, not PEAR DB's emulated one.
   631     /**
   994      *
   632     * for limit queries, the number of rows to fetch
   995      * Copied here incase it changes in $dbh, which is referenced
   633     * @var integer
   996      *
   634     */
   997      * {@internal  Mainly here because the InterBase/Firebird API is only
   635     var $limit_count = null;
   998      * able to retrieve data from result sets if the statemnt handle is
   636 
   999      * still in scope.}}
   637     /**
  1000      *
   638      * DB_result constructor.
  1001      * @var resource
   639      * @param resource &$dbh   DB object reference
  1002      * @since Property available since Release 1.7.0
   640      * @param resource $result result resource id
  1003      */
   641      */
  1004     var $statement;
   642 
  1005 
       
  1006 
       
  1007     // }}}
       
  1008     // {{{ constructor
       
  1009 
       
  1010     /**
       
  1011      * This constructor sets the object's properties
       
  1012      *
       
  1013      * @param object   &$dbh     the DB object reference
       
  1014      * @param resource $result   the result resource id
       
  1015      * @param array    $options  an associative array with result options
       
  1016      *
       
  1017      * @return void
       
  1018      */
   643     function DB_result(&$dbh, $result, $options = array())
  1019     function DB_result(&$dbh, $result, $options = array())
   644     {
  1020     {
   645         $this->dbh = &$dbh;
       
   646         $this->result = $result;
       
   647         $this->limit_from  = isset($options['limit_from'])  ? $options['limit_from']  : null;
       
   648         $this->limit_count = isset($options['limit_count']) ? $options['limit_count'] : null;
       
   649         $this->limit_type  = $dbh->features['limit'];
       
   650         $this->autofree    = $dbh->options['autofree'];
  1021         $this->autofree    = $dbh->options['autofree'];
       
  1022         $this->dbh         = &$dbh;
   651         $this->fetchmode   = $dbh->fetchmode;
  1023         $this->fetchmode   = $dbh->fetchmode;
   652         $this->fetchmode_object_class = $dbh->fetchmode_object_class;
  1024         $this->fetchmode_object_class = $dbh->fetchmode_object_class;
   653     }
  1025         $this->parameters  = $dbh->last_parameters;
   654 
  1026         $this->query       = $dbh->last_query;
   655     /**
  1027         $this->result      = $result;
   656      * Fetch and return a row of data (it uses driver->fetchInto for that)
  1028         $this->statement   = empty($dbh->last_stmt) ? null : $dbh->last_stmt;
   657      * @param int $fetchmode format of fetched row
  1029         foreach ($options as $key => $value) {
   658      * @param int $rownum    the row number to fetch
  1030             $this->setOption($key, $value);
   659      *
  1031         }
   660      * @return  array a row of data, NULL on no more rows or PEAR_Error on error
  1032     }
   661      *
  1033 
   662      * @access public
  1034     /**
   663      */
  1035      * Set options for the DB_result object
   664     function fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
  1036      *
       
  1037      * @param string $key    the option to set
       
  1038      * @param mixed  $value  the value to set the option to
       
  1039      *
       
  1040      * @return void
       
  1041      */
       
  1042     function setOption($key, $value = null)
       
  1043     {
       
  1044         switch ($key) {
       
  1045             case 'limit_from':
       
  1046                 $this->limit_from = $value;
       
  1047                 break;
       
  1048             case 'limit_count':
       
  1049                 $this->limit_count = $value;
       
  1050         }
       
  1051     }
       
  1052 
       
  1053     // }}}
       
  1054     // {{{ fetchRow()
       
  1055 
       
  1056     /**
       
  1057      * Fetch a row of data and return it by reference into an array
       
  1058      *
       
  1059      * The type of array returned can be controlled either by setting this
       
  1060      * method's <var>$fetchmode</var> parameter or by changing the default
       
  1061      * fetch mode setFetchMode() before calling this method.
       
  1062      *
       
  1063      * There are two options for standardizing the information returned
       
  1064      * from databases, ensuring their values are consistent when changing
       
  1065      * DBMS's.  These portability options can be turned on when creating a
       
  1066      * new DB object or by using setOption().
       
  1067      *
       
  1068      *   + <var>DB_PORTABILITY_LOWERCASE</var>
       
  1069      *     convert names of fields to lower case
       
  1070      *
       
  1071      *   + <var>DB_PORTABILITY_RTRIM</var>
       
  1072      *     right trim the data
       
  1073      *
       
  1074      * @param int $fetchmode  the constant indicating how to format the data
       
  1075      * @param int $rownum     the row number to fetch (index starts at 0)
       
  1076      *
       
  1077      * @return mixed  an array or object containing the row's data,
       
  1078      *                 NULL when the end of the result set is reached
       
  1079      *                 or a DB_Error object on failure.
       
  1080      *
       
  1081      * @see DB_common::setOption(), DB_common::setFetchMode()
       
  1082      */
       
  1083     function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
   665     {
  1084     {
   666         if ($fetchmode === DB_FETCHMODE_DEFAULT) {
  1085         if ($fetchmode === DB_FETCHMODE_DEFAULT) {
   667             $fetchmode = $this->fetchmode;
  1086             $fetchmode = $this->fetchmode;
   668         }
  1087         }
   669         if ($fetchmode === DB_FETCHMODE_OBJECT) {
  1088         if ($fetchmode === DB_FETCHMODE_OBJECT) {
   672         }
  1091         }
   673         if ($this->limit_from !== null) {
  1092         if ($this->limit_from !== null) {
   674             if ($this->row_counter === null) {
  1093             if ($this->row_counter === null) {
   675                 $this->row_counter = $this->limit_from;
  1094                 $this->row_counter = $this->limit_from;
   676                 // Skip rows
  1095                 // Skip rows
   677                 if ($this->limit_type == false) {
  1096                 if ($this->dbh->features['limit'] === false) {
   678                     $i = 0;
  1097                     $i = 0;
   679                     while ($i++ < $this->limit_from) {
  1098                     while ($i++ < $this->limit_from) {
   680                         $this->dbh->fetchInto($this->result, $arr, $fetchmode);
  1099                         $this->dbh->fetchInto($this->result, $arr, $fetchmode);
   681                     }
  1100                     }
   682                 }
  1101                 }
   683             }
  1102             }
   684             if ($this->row_counter >= (
  1103             if ($this->row_counter >= ($this->limit_from + $this->limit_count))
   685                     $this->limit_from + $this->limit_count))
       
   686             {
  1104             {
   687                 return null;
  1105                 if ($this->autofree) {
   688             }
  1106                     $this->free();
   689             if ($this->limit_type == 'emulate') {
  1107                 }
       
  1108                 $tmp = null;
       
  1109                 return $tmp;
       
  1110             }
       
  1111             if ($this->dbh->features['limit'] === 'emulate') {
   690                 $rownum = $this->row_counter;
  1112                 $rownum = $this->row_counter;
   691             }
  1113             }
   692 
       
   693             $this->row_counter++;
  1114             $this->row_counter++;
   694         }
  1115         }
   695         $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
  1116         $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
   696         if ($res !== DB_OK) {
  1117         if ($res === DB_OK) {
   697             if ($res == null && $this->autofree) {
  1118             if (isset($object_class)) {
   698                 $this->free();
  1119                 // The default mode is specified in the
   699             }
  1120                 // DB_common::fetchmode_object_class property
   700             return $res;
  1121                 if ($object_class == 'stdClass') {
   701         }
  1122                     $arr = (object) $arr;
   702         if (isset($object_class)) {
  1123                 } else {
   703             // default mode specified in DB_common::fetchmode_object_class property
  1124                     $arr = &new $object_class($arr);
   704             if ($object_class == 'stdClass') {
  1125                 }
   705                 $ret = (object) $arr;
  1126             }
   706             } else {
  1127             return $arr;
   707                 $ret =& new $object_class($arr);
  1128         }
   708             }
  1129         if ($res == null && $this->autofree) {
   709             return $ret;
  1130             $this->free();
   710         }
  1131         }
   711         return $arr;
  1132         return $res;
   712     }
  1133     }
   713 
  1134 
   714     /**
  1135     // }}}
   715      * Fetch a row of data into an existing variable.
  1136     // {{{ fetchInto()
   716      *
  1137 
   717      * @param  mixed   &$arr     reference to data containing the row
  1138     /**
   718      * @param  integer $fetchmod format of fetched row
  1139      * Fetch a row of data into an array which is passed by reference
   719      * @param  integer $rownum   the row number to fetch
  1140      *
   720      *
  1141      * The type of array returned can be controlled either by setting this
   721      * @return  mixed  DB_OK on success, NULL on no more rows or
  1142      * method's <var>$fetchmode</var> parameter or by changing the default
   722      *                 a DB_Error object on error
  1143      * fetch mode setFetchMode() before calling this method.
   723      *
  1144      *
   724      * @access public
  1145      * There are two options for standardizing the information returned
   725      */
  1146      * from databases, ensuring their values are consistent when changing
   726     function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
  1147      * DBMS's.  These portability options can be turned on when creating a
       
  1148      * new DB object or by using setOption().
       
  1149      *
       
  1150      *   + <var>DB_PORTABILITY_LOWERCASE</var>
       
  1151      *     convert names of fields to lower case
       
  1152      *
       
  1153      *   + <var>DB_PORTABILITY_RTRIM</var>
       
  1154      *     right trim the data
       
  1155      *
       
  1156      * @param array &$arr       the variable where the data should be placed
       
  1157      * @param int   $fetchmode  the constant indicating how to format the data
       
  1158      * @param int   $rownum     the row number to fetch (index starts at 0)
       
  1159      *
       
  1160      * @return mixed  DB_OK if a row is processed, NULL when the end of the
       
  1161      *                 result set is reached or a DB_Error object on failure
       
  1162      *
       
  1163      * @see DB_common::setOption(), DB_common::setFetchMode()
       
  1164      */
       
  1165     function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
   727     {
  1166     {
   728         if ($fetchmode === DB_FETCHMODE_DEFAULT) {
  1167         if ($fetchmode === DB_FETCHMODE_DEFAULT) {
   729             $fetchmode = $this->fetchmode;
  1168             $fetchmode = $this->fetchmode;
   730         }
  1169         }
   731         if ($fetchmode === DB_FETCHMODE_OBJECT) {
  1170         if ($fetchmode === DB_FETCHMODE_OBJECT) {
   734         }
  1173         }
   735         if ($this->limit_from !== null) {
  1174         if ($this->limit_from !== null) {
   736             if ($this->row_counter === null) {
  1175             if ($this->row_counter === null) {
   737                 $this->row_counter = $this->limit_from;
  1176                 $this->row_counter = $this->limit_from;
   738                 // Skip rows
  1177                 // Skip rows
   739                 if ($this->limit_type == false) {
  1178                 if ($this->dbh->features['limit'] === false) {
   740                     $i = 0;
  1179                     $i = 0;
   741                     while ($i++ < $this->limit_from) {
  1180                     while ($i++ < $this->limit_from) {
   742                         $this->dbh->fetchInto($this->result, $arr, $fetchmode);
  1181                         $this->dbh->fetchInto($this->result, $arr, $fetchmode);
   743                     }
  1182                     }
   744                 }
  1183                 }
   745             }
  1184             }
   746             if ($this->row_counter >= (
  1185             if ($this->row_counter >= (
   747                     $this->limit_from + $this->limit_count))
  1186                     $this->limit_from + $this->limit_count))
   748             {
  1187             {
       
  1188                 if ($this->autofree) {
       
  1189                     $this->free();
       
  1190                 }
   749                 return null;
  1191                 return null;
   750             }
  1192             }
   751             if ($this->limit_type == 'emulate') {
  1193             if ($this->dbh->features['limit'] === 'emulate') {
   752                 $rownum = $this->row_counter;
  1194                 $rownum = $this->row_counter;
   753             }
  1195             }
   754 
  1196 
   755             $this->row_counter++;
  1197             $this->row_counter++;
   756         }
  1198         }
   757         $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
  1199         $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
   758         if (($res === DB_OK) && isset($object_class)) {
  1200         if ($res === DB_OK) {
   759             // default mode specified in DB_common::fetchmode_object_class property
  1201             if (isset($object_class)) {
   760             if ($object_class == 'stdClass') {
  1202                 // default mode specified in the
   761                 $arr = (object) $arr;
  1203                 // DB_common::fetchmode_object_class property
       
  1204                 if ($object_class == 'stdClass') {
       
  1205                     $arr = (object) $arr;
       
  1206                 } else {
       
  1207                     $arr = new $object_class($arr);
       
  1208                 }
       
  1209             }
       
  1210             return DB_OK;
       
  1211         }
       
  1212         if ($res == null && $this->autofree) {
       
  1213             $this->free();
       
  1214         }
       
  1215         return $res;
       
  1216     }
       
  1217 
       
  1218     // }}}
       
  1219     // {{{ numCols()
       
  1220 
       
  1221     /**
       
  1222      * Get the the number of columns in a result set
       
  1223      *
       
  1224      * @return int  the number of columns.  A DB_Error object on failure.
       
  1225      */
       
  1226     function numCols()
       
  1227     {
       
  1228         return $this->dbh->numCols($this->result);
       
  1229     }
       
  1230 
       
  1231     // }}}
       
  1232     // {{{ numRows()
       
  1233 
       
  1234     /**
       
  1235      * Get the number of rows in a result set
       
  1236      *
       
  1237      * @return int  the number of rows.  A DB_Error object on failure.
       
  1238      */
       
  1239     function numRows()
       
  1240     {
       
  1241         if ($this->dbh->features['numrows'] === 'emulate'
       
  1242             && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS)
       
  1243         {
       
  1244             if ($this->dbh->features['prepare']) {
       
  1245                 $res = $this->dbh->query($this->query, $this->parameters);
   762             } else {
  1246             } else {
   763                 $arr = new $object_class($arr);
  1247                 $res = $this->dbh->query($this->query);
   764             }
  1248             }
   765         } elseif ($res == null && $this->autofree) {
  1249             if (DB::isError($res)) {
   766             $this->free();
  1250                 return $res;
   767         }
  1251             }
   768         return $res;
  1252             $i = 0;
   769     }
  1253             while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) {
   770 
  1254                 $i++;
   771     /**
  1255             }
   772      * Get the the number of columns in a result set.
  1256             return $i;
   773      *
  1257         } else {
   774      * @return int the number of columns, or a DB error
  1258             return $this->dbh->numRows($this->result);
   775      *
  1259         }
   776      * @access public
  1260     }
   777      */
  1261 
   778     function numCols()
  1262     // }}}
   779     {
  1263     // {{{ nextResult()
   780         return $this->dbh->numCols($this->result);
  1264 
   781     }
  1265     /**
   782 
  1266      * Get the next result if a batch of queries was executed
   783     /**
  1267      *
   784      * Get the number of rows in a result set.
  1268      * @return bool  true if a new result is available or false if not
   785      *
       
   786      * @return int the number of rows, or a DB error
       
   787      *
       
   788      * @access public
       
   789      */
       
   790     function numRows()
       
   791     {
       
   792         return $this->dbh->numRows($this->result);
       
   793     }
       
   794 
       
   795     /**
       
   796      * Get the next result if a batch of queries was executed.
       
   797      *
       
   798      * @return bool true if a new result is available or false if not.
       
   799      *
       
   800      * @access public
       
   801      */
  1269      */
   802     function nextResult()
  1270     function nextResult()
   803     {
  1271     {
   804         return $this->dbh->nextResult($this->result);
  1272         return $this->dbh->nextResult($this->result);
   805     }
  1273     }
   806 
  1274 
   807     /**
  1275     // }}}
   808      * Frees the resources allocated for this result set.
  1276     // {{{ free()
   809      * @return  int error code
  1277 
   810      *
  1278     /**
   811      * @access public
  1279      * Frees the resources allocated for this result set
       
  1280      *
       
  1281      * @return bool  true on success.  A DB_Error object on failure.
   812      */
  1282      */
   813     function free()
  1283     function free()
   814     {
  1284     {
   815         $err = $this->dbh->freeResult($this->result);
  1285         $err = $this->dbh->freeResult($this->result);
   816         if(DB::isError($err)) {
  1286         if (DB::isError($err)) {
   817             return $err;
  1287             return $err;
   818         }
  1288         }
   819         $this->result = false;
  1289         $this->result = false;
       
  1290         $this->statement = false;
   820         return true;
  1291         return true;
   821     }
  1292     }
   822 
  1293 
   823     /**
  1294     // }}}
   824     * @deprecated
  1295     // {{{ tableInfo()
   825     */
  1296 
       
  1297     /**
       
  1298      * @see DB_common::tableInfo()
       
  1299      * @deprecated Method deprecated some time before Release 1.2
       
  1300      */
   826     function tableInfo($mode = null)
  1301     function tableInfo($mode = null)
   827     {
  1302     {
   828         return $this->dbh->tableInfo($this->result, $mode);
  1303         if (is_string($mode)) {
   829     }
  1304             return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA);
   830 
  1305         }
   831     /**
  1306         return $this->dbh->tableInfo($this, $mode);
   832     * returns the actual row number
  1307     }
   833     * @return integer
  1308 
   834     */
  1309     // }}}
       
  1310     // {{{ getQuery()
       
  1311 
       
  1312     /**
       
  1313      * Determine the query string that created this result
       
  1314      *
       
  1315      * @return string  the query string
       
  1316      *
       
  1317      * @since Method available since Release 1.7.0
       
  1318      */
       
  1319     function getQuery()
       
  1320     {
       
  1321         return $this->query;
       
  1322     }
       
  1323 
       
  1324     // }}}
       
  1325     // {{{ getRowCounter()
       
  1326 
       
  1327     /**
       
  1328      * Tells which row number is currently being processed
       
  1329      *
       
  1330      * @return integer  the current row being looked at.  Starts at 1.
       
  1331      */
   835     function getRowCounter()
  1332     function getRowCounter()
   836     {
  1333     {
   837         return $this->row_counter;
  1334         return $this->row_counter;
   838     }
  1335     }
       
  1336 
       
  1337     // }}}
   839 }
  1338 }
   840 
  1339 
   841 /**
  1340 // }}}
   842 * Pear DB Row Object
  1341 // {{{ class DB_row
   843 * @see DB_common::setFetchMode()
  1342 
   844 */
  1343 /**
       
  1344  * PEAR DB Row Object
       
  1345  *
       
  1346  * The object contains a row of data from a result set.  Each column's data
       
  1347  * is placed in a property named for the column.
       
  1348  *
       
  1349  * @category   Database
       
  1350  * @package    DB
       
  1351  * @author     Stig Bakken <ssb@php.net>
       
  1352  * @copyright  1997-2005 The PHP Group
       
  1353  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
       
  1354  * @version    Release: @package_version@
       
  1355  * @link       http://pear.php.net/package/DB
       
  1356  * @see        DB_common::setFetchMode()
       
  1357  */
   845 class DB_row
  1358 class DB_row
   846 {
  1359 {
   847     /**
  1360     // {{{ constructor
   848     * constructor
  1361 
   849     *
  1362     /**
   850     * @param resource row data as array
  1363      * The constructor places a row's data into properties of this object
   851     */
  1364      *
       
  1365      * @param array  the array containing the row's data
       
  1366      *
       
  1367      * @return void
       
  1368      */
   852     function DB_row(&$arr)
  1369     function DB_row(&$arr)
   853     {
  1370     {
   854         for (reset($arr); $key = key($arr); next($arr)) {
  1371         foreach ($arr as $key => $value) {
   855             $this->$key = &$arr[$key];
  1372             $this->$key = &$arr[$key];
   856         }
  1373         }
   857     }
  1374     }
       
  1375 
       
  1376     // }}}
   858 }
  1377 }
   859 
  1378 
       
  1379 // }}}
       
  1380 
       
  1381 /*
       
  1382  * Local variables:
       
  1383  * tab-width: 4
       
  1384  * c-basic-offset: 4
       
  1385  * End:
       
  1386  */
       
  1387 
   860 ?>
  1388 ?>