PHPonTraxTest
[ class tree: PHPonTraxTest ] [ index: PHPonTraxTest ] [ all elements ]

Source for file DB.php

Documentation is available at DB.php

  1. <?php
  2. /**
  3.  *  File for mock DB class
  4.  *
  5.  *  This file has the same name as the file holding the {@link }
  6.  *  http://pear.php.net/package/DB PEAR DB class}.
  7.  *  To use the mock DB, put this file in the PHP include path ahead of
  8.  *  the PEAR library, so that any class which requires DB.php will
  9.  *  load this version.
  10.  *
  11.  * (PHP 5)
  12.  *
  13.  * @package PHPonTraxTest
  14.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  15.  * @copyright (c) Walter O. Haas 2006
  16.  * @version $Id: DB.php 198 2006-04-20 16:20:30Z haas $
  17.  * @author Walt Haas <haas@xmission.com>
  18.  */
  19.  
  20. require_once 'PEAR.php';
  21. require_once 'PHPUnit2/Framework/Assert.php';
  22.  
  23. /**
  24.  * The code returned by many methods upon success
  25.  */
  26. define('DB_OK'1);
  27.  
  28. /**
  29.  * Unkown error
  30.  */
  31. define('DB_ERROR'-1);
  32.  
  33. /**
  34.  * Syntax error
  35.  */
  36. define('DB_ERROR_SYNTAX'-2);
  37.  
  38. /**
  39.  * Tried to insert a duplicate value into a primary or unique index
  40.  */
  41. define('DB_ERROR_CONSTRAINT'-3);
  42.  
  43. /**
  44.  * An identifier in the query refers to a non-existant object
  45.  */
  46. define('DB_ERROR_NOT_FOUND'-4);
  47.  
  48. /**
  49.  * Tried to create a duplicate object
  50.  */
  51. define('DB_ERROR_ALREADY_EXISTS'-5);
  52.  
  53. /**
  54.  * The current driver does not support the action you attempted
  55.  */
  56. define('DB_ERROR_UNSUPPORTED'-6);
  57.  
  58. /**
  59.  * The number of parameters does not match the number of placeholders
  60.  */
  61. define('DB_ERROR_MISMATCH'-7);
  62.  
  63. /**
  64.  * A literal submitted did not match the data type expected
  65.  */
  66. define('DB_ERROR_INVALID'-8);
  67.  
  68. /**
  69.  * The current DBMS does not support the action you attempted
  70.  */
  71. define('DB_ERROR_NOT_CAPABLE'-9);
  72.  
  73. /**
  74.  * A literal submitted was too long so the end of it was removed
  75.  */
  76. define('DB_ERROR_TRUNCATED'-10);
  77.  
  78. /**
  79.  * A literal number submitted did not match the data type expected
  80.  */
  81. define('DB_ERROR_INVALID_NUMBER'-11);
  82.  
  83. /**
  84.  * A literal date submitted did not match the data type expected
  85.  */
  86. define('DB_ERROR_INVALID_DATE'-12);
  87.  
  88. /**
  89.  * Attempt to divide something by zero
  90.  */
  91. define('DB_ERROR_DIVZERO'-13);
  92.  
  93. /**
  94.  * A database needs to be selected
  95.  */
  96. define('DB_ERROR_NODBSELECTED'-14);
  97.  
  98. /**
  99.  * Could not create the object requested
  100.  */
  101. define('DB_ERROR_CANNOT_CREATE'-15);
  102.  
  103. /**
  104.  * Could not drop the database requested because it does not exist
  105.  */
  106. define('DB_ERROR_CANNOT_DROP'-17);
  107.  
  108. /**
  109.  * An identifier in the query refers to a non-existant table
  110.  */
  111. define('DB_ERROR_NOSUCHTABLE'-18);
  112.  
  113. /**
  114.  * An identifier in the query refers to a non-existant column
  115.  */
  116. define('DB_ERROR_NOSUCHFIELD'-19);
  117.  
  118. /**
  119.  * The data submitted to the method was inappropriate
  120.  */
  121. define('DB_ERROR_NEED_MORE_DATA'-20);
  122.  
  123. /**
  124.  * The attempt to lock the table failed
  125.  */
  126. define('DB_ERROR_NOT_LOCKED'-21);
  127.  
  128. /**
  129.  * The number of columns doesn't match the number of values
  130.  */
  131. define('DB_ERROR_VALUE_COUNT_ON_ROW'-22);
  132.  
  133. /**
  134.  * The DSN submitted has problems
  135.  */
  136. define('DB_ERROR_INVALID_DSN'-23);
  137.  
  138. /**
  139.  * Could not connect to the database
  140.  */
  141. define('DB_ERROR_CONNECT_FAILED'-24);
  142.  
  143. /**
  144.  * The PHP extension needed for this DBMS could not be found
  145.  */
  146. define('DB_ERROR_EXTENSION_NOT_FOUND',-25);
  147.  
  148. /**
  149.  * The present user has inadequate permissions to perform the task requestd
  150.  */
  151. define('DB_ERROR_ACCESS_VIOLATION'-26);
  152.  
  153. /**
  154.  * The database requested does not exist
  155.  */
  156. define('DB_ERROR_NOSUCHDB'-27);
  157.  
  158. /**
  159.  * Tried to insert a null value into a column that doesn't allow nulls
  160.  */
  161. define('DB_ERROR_CONSTRAINT_NOT_NULL',-29);
  162.  
  163. /**
  164.  * Identifiers for the placeholders used in prepared statements.
  165.  * @see prepare()
  166.  */
  167.  
  168. /**
  169.  * Indicates a scalar (<kbd>?</kbd>) placeholder was used
  170.  *
  171.  * Quote and escape the value as necessary.
  172.  */
  173. define('DB_PARAM_SCALAR'1);
  174.  
  175. /**
  176.  * Indicates an opaque (<kbd>&</kbd>) placeholder was used
  177.  *
  178.  * The value presented is a file name.  Extract the contents of that file
  179.  * and place them in this column.
  180.  */
  181. define('DB_PARAM_OPAQUE'2);
  182.  
  183. /**
  184.  * Indicates a misc (<kbd>!</kbd>) placeholder was used
  185.  *
  186.  * The value should not be quoted or escaped.
  187.  */
  188. define('DB_PARAM_MISC',   3);
  189.  
  190. /**
  191.  * The different ways of returning binary data from queries.
  192.  */
  193.  
  194. /**
  195.  * Sends the fetched data straight through to output
  196.  */
  197. define('DB_BINMODE_PASSTHRU'1);
  198.  
  199. /**
  200.  * Lets you return data as usual
  201.  */
  202. define('DB_BINMODE_RETURN'2);
  203.  
  204. /**
  205.  * Converts the data to hex format before returning it
  206.  *
  207.  * For example the string "123" would become "313233".
  208.  */
  209. define('DB_BINMODE_CONVERT'3);
  210.  
  211. /**
  212.  * Fetchmode constants
  213.  */
  214. define('DB_FETCHMODE_DEFAULT'0);
  215. define('DB_FETCHMODE_ORDERED'1);
  216. define('DB_FETCHMODE_ASSOC'2);
  217. define('DB_FETCHMODE_OBJECT'3);
  218.  
  219. /**
  220.  * For multi-dimensional results, make the column name the first level
  221.  * of the array and put the row number in the second level of the array
  222.  *
  223.  * This is flipped from the normal behavior, which puts the row numbers
  224.  * in the first level of the array and the column names in the second level.
  225.  */
  226. define('DB_FETCHMODE_FLIPPED'4);
  227.  
  228. /**
  229.  * Old fetch modes.  Left here for compatibility.
  230.  */
  231. define('DB_GETMODE_ORDERED'DB_FETCHMODE_ORDERED);
  232. define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
  233. define('DB_GETMODE_FLIPPED'DB_FETCHMODE_FLIPPED);
  234.  
  235. /**
  236.  * The type of information to return from the tableInfo() method.
  237.  *
  238.  * Bitwised constants, so they can be combined using <kbd>|</kbd>
  239.  * and removed using <kbd>^</kbd>.
  240.  *
  241.  * @see tableInfo()
  242.  */
  243. define('DB_TABLEINFO_ORDER'1);
  244. define('DB_TABLEINFO_ORDERTABLE'2);
  245. define('DB_TABLEINFO_FULL'3);
  246.  
  247. /**
  248.  * The type of query to create with the automatic query building methods.
  249.  * @see autoPrepare(), autoExecute()
  250.  */
  251. define('DB_AUTOQUERY_INSERT'1);
  252. define('DB_AUTOQUERY_UPDATE'2);
  253.  
  254. /**
  255.  * Portability Modes.
  256.  *
  257.  * Bitwised constants, so they can be combined using <kbd>|</kbd>
  258.  * and removed using <kbd>^</kbd>.
  259.  *
  260.  * @see setOption()
  261.  */
  262.  
  263. /**
  264.  * Turn off all portability features
  265.  */
  266. define('DB_PORTABILITY_NONE'0);
  267.  
  268. /**
  269.  * Convert names of tables and fields to lower case
  270.  * when using the get*(), fetch*() and tableInfo() methods
  271.  */
  272. define('DB_PORTABILITY_LOWERCASE'1);
  273.  
  274. /**
  275.  * Right trim the data output by get*() and fetch*()
  276.  */
  277. define('DB_PORTABILITY_RTRIM'2);
  278.  
  279. /**
  280.  * Force reporting the number of rows deleted
  281.  */
  282. define('DB_PORTABILITY_DELETE_COUNT'4);
  283.  
  284. /**
  285.  * Enable hack that makes numRows() work in Oracle
  286.  */
  287. define('DB_PORTABILITY_NUMROWS'8);
  288.  
  289. /**
  290.  * Makes certain error messages in certain drivers compatible
  291.  * with those from other DBMS's
  292.  *
  293.  * + mysql, mysqli:  change unique/primary key constraints
  294.  *   DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
  295.  *
  296.  * + odbc(access):  MS's ODBC driver reports 'no such field' as code
  297.  *   07001, which means 'too few parameters.'  When this option is on
  298.  *   that code gets mapped to DB_ERROR_NOSUCHFIELD.
  299.  */
  300. define('DB_PORTABILITY_ERRORS'16);
  301.  
  302. /**
  303.  * Convert null values to empty strings in data output by
  304.  * get*() and fetch*()
  305.  */
  306. define('DB_PORTABILITY_NULL_TO_EMPTY'32);
  307.  
  308. /**
  309.  * Turn on all portability features
  310.  */
  311. define('DB_PORTABILITY_ALL'63);
  312.  
  313. /**
  314.  *  Mock DB class for testing
  315.  *
  316.  *  This class is a mock version of the
  317.  *  {@link http://pear.php.net/package/DB PEAR DB class}.  It is
  318.  *  intended to provide the same interface as the real DB class, plus
  319.  *  a small database sufficient to test software.
  320.  */
  321.  
  322. class DB {
  323.  
  324.     /**
  325.      * Create a new DB object for the specified database type but don't
  326.      * connect to the database
  327.      *
  328.      * @param string $type     the database type (eg "mysql")
  329.      * @param array  $options  an associative array of option names and values
  330.      * @return object  new DB object.  A DB_Error object on failure.
  331.      * @see DB_common::setOption()
  332.      *  @todo Implement mock DB::factory
  333.      */
  334.     public function &factory($type$options false)
  335.     {
  336. //        if (!is_array($options)) {
  337. //            $options = array('persistent' => $options);
  338. //        }
  339. //
  340. //        if (isset($options['debug']) && $options['debug'] >= 2) {
  341. //            // expose php errors with sufficient debug level
  342. //            include_once "DB/{$type}.php";
  343. //        } else {
  344. //            @include_once "DB/{$type}.php";
  345. //        }
  346. //
  347. //        $classname = "DB_${type}";
  348. //
  349. //        if (!class_exists($classname)) {
  350. //            $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
  351. //                                    "Unable to include the DB/{$type}.php"
  352. //                                    . " file for '$dsn'",
  353. //                                    'DB_Error', true);
  354. //            return $tmp;
  355. //        }
  356. //
  357. //        @$obj =& new $classname;
  358. //
  359. //        foreach ($options as $option => $value) {
  360. //            $test = $obj->setOption($option, $value);
  361. //            if (DB::isError($test)) {
  362. //                return $test;
  363. //            }
  364. //        }
  365. //
  366. //        return $obj;
  367.     }
  368.  
  369.     /**
  370.      * Create a new DB object including a connection to the specified database
  371.      *
  372.      * @param mixed $dsn      the string "data source name" or array in the
  373.      *                          format returned by DB::parseDSN()
  374.      * @param array $options  an associative array of option names and values
  375.      * @return object  new DB object.  A DB_Error object on failure.
  376.      * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
  377.      *  @todo Implement mock DB::connect
  378.      */
  379.     function &connect($dsn$options array())
  380.     {
  381.         $dsninfo DB::parseDSN($dsn);
  382.         $type $dsninfo['phptype'];
  383.  
  384.         // only support MySQL at the moment
  385.         PHPUnit2_Framework_Assert::assertEquals($type,'mysql');
  386.         @$obj =new DB_mysql;
  387.  
  388.         foreach ($options as $option => $value{
  389.             $test $obj->setOption($option$value);
  390.             if (DB::isError($test)) {
  391.                 return $test;
  392.             }
  393.         }
  394.  
  395. //        $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
  396. //        if (DB::isError($err)) {
  397. //            $err->addUserInfo($dsn);
  398. //            return $err;
  399. //        }
  400. //
  401.         return $obj;
  402.     }
  403.  
  404.     /**
  405.      * Return the DB API version
  406.      *
  407.      * @return string  the DB API version number
  408.      */
  409.     function apiVersion()
  410.     {
  411.         return '1.7.6';
  412.     }
  413.  
  414.     /**
  415.      * Determines if a variable is a DB_Error object
  416.      *
  417.      * @param mixed $value  the variable to check
  418.      * @return bool  whether $value is DB_Error object
  419.      */
  420.     function isError($value)
  421.     {
  422.         return is_a($value'DB_Error');
  423.     }
  424.  
  425.     /**
  426.      * Determines if a value is a DB_<driver> object
  427.      *
  428.      * @param mixed $value  the value to test
  429.      * @return bool  whether $value is a DB_<driver> object
  430.      *  @todo Implement mock DB::isConnection
  431.      */
  432.     function isConnection($value)
  433.     {
  434. //        return (is_object($value) &&
  435. //                is_subclass_of($value, 'db_common') &&
  436. //                method_exists($value, 'simpleQuery'));
  437.     }
  438.  
  439.     /**
  440.      * Tell whether a query is a data manipulation or data definition query
  441.      *
  442.      * @param string $query  the query
  443.      * @return boolean  whether $query is a data manipulation query
  444.      */
  445.     function isManip($query)
  446.     {
  447.         $manips 'INSERT|UPDATE|DELETE|REPLACE|'
  448.                 . 'CREATE|DROP|'
  449.                 . 'LOAD DATA|SELECT .* INTO|COPY|'
  450.                 . 'ALTER|GRANT|REVOKE|'
  451.                 . 'LOCK|UNLOCK';
  452.         if (preg_match('/^\s*"?(' $manips ')\s+/i'$query)) {
  453.             return true;
  454.         }
  455.         return false;
  456.     }
  457.  
  458.     /**
  459.      * Return a textual error message for a DB error code
  460.      *
  461.      * @param integer $value  the DB error code
  462.      * @return string  the error message or false if the error code was
  463.      *                   not recognized
  464.      *  @todo Implement mock DB::errorMessage
  465.      */
  466.     public function errorMessage($value)
  467.     {
  468.         static $errorMessages;
  469.         if (!isset($errorMessages)) {
  470.             $errorMessages array(
  471.                 DB_ERROR                    => 'unknown error',
  472.                 DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
  473.                 DB_ERROR_ALREADY_EXISTS     => 'already exists',
  474.                 DB_ERROR_CANNOT_CREATE      => 'can not create',
  475.                 DB_ERROR_CANNOT_DROP        => 'can not drop',
  476.                 DB_ERROR_CONNECT_FAILED     => 'connect failed',
  477.                 DB_ERROR_CONSTRAINT         => 'constraint violation',
  478.                 DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
  479.                 DB_ERROR_DIVZERO            => 'division by zero',
  480.                 DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
  481.                 DB_ERROR_INVALID            => 'invalid',
  482.                 DB_ERROR_INVALID_DATE       => 'invalid date or time',
  483.                 DB_ERROR_INVALID_DSN        => 'invalid DSN',
  484.                 DB_ERROR_INVALID_NUMBER     => 'invalid number',
  485.                 DB_ERROR_MISMATCH           => 'mismatch',
  486.                 DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
  487.                 DB_ERROR_NODBSELECTED       => 'no database selected',
  488.                 DB_ERROR_NOSUCHDB           => 'no such database',
  489.                 DB_ERROR_NOSUCHFIELD        => 'no such field',
  490.                 DB_ERROR_NOSUCHTABLE        => 'no such table',
  491.                 DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
  492.                 DB_ERROR_NOT_FOUND          => 'not found',
  493.                 DB_ERROR_NOT_LOCKED         => 'not locked',
  494.                 DB_ERROR_SYNTAX             => 'syntax error',
  495.                 DB_ERROR_UNSUPPORTED        => 'not supported',
  496.                 DB_ERROR_TRUNCATED          => 'truncated',
  497.                 DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
  498.                 DB_OK                       => 'no error',
  499.             );
  500.         }
  501.  
  502. //        if (DB::isError($value)) {
  503. //            $value = $value->getCode();
  504. //        }
  505. //
  506. //        return isset($errorMessages[$value]) ? $errorMessages[$value]
  507. //                     : $errorMessages[DB_ERROR];
  508.     }
  509.  
  510.     /**
  511.      * Parse a data source name
  512.      *
  513.      * @param string $dsn Data Source Name to be parsed
  514.      * @return array an associative array with the following keys:
  515.      *   + phptype:  Database backend used in PHP (mysql, odbc etc.)
  516.      *   + dbsyntax: Database used with regards to SQL syntax etc.
  517.      *   + protocol: Communication protocol to use (tcp, unix etc.)
  518.      *   + hostspec: Host specification (hostname[:port])
  519.      *   + database: Database to use on the DBMS server
  520.      *   + username: User name for login
  521.      *   + password: Password for login
  522.      *  @todo Implement mock DB::parseDSN
  523.      */
  524.     public function parseDSN($dsn)
  525.     {
  526.         $parsed array(
  527.             'phptype'  => false,
  528.             'dbsyntax' => false,
  529.             'username' => false,
  530.             'password' => false,
  531.             'protocol' => false,
  532.             'hostspec' => false,
  533.             'port'     => false,
  534.             'socket'   => false,
  535.             'database' => false,
  536.         );
  537.  
  538.         if (is_array($dsn)) {
  539.             $dsn array_merge($parsed$dsn);
  540.             if (!$dsn['dbsyntax']{
  541.                 $dsn['dbsyntax'$dsn['phptype'];
  542.             }
  543.             return $dsn;
  544.         }
  545.  
  546.         // Find phptype and dbsyntax
  547.         if (($pos strpos($dsn'://')) !== false{
  548.             $str substr($dsn0$pos);
  549.             $dsn substr($dsn$pos 3);
  550.         else {
  551.             $str $dsn;
  552.             $dsn null;
  553.         }
  554.  
  555.         // Get phptype and dbsyntax
  556.         // $str => phptype(dbsyntax)
  557.         if (preg_match('|^(.+?)\((.*?)\)$|'$str$arr)) {
  558.             $parsed['phptype']  $arr[1];
  559.             $parsed['dbsyntax'!$arr[2$arr[1$arr[2];
  560.         else {
  561.             $parsed['phptype']  $str;
  562.             $parsed['dbsyntax'$str;
  563.         }
  564.  
  565.         if (!count($dsn)) {
  566.             return $parsed;
  567.         }
  568.  
  569.         // Get (if found): username and password
  570.         // $dsn => username:password@protocol+hostspec/database
  571.         if (($at strrpos($dsn,'@')) !== false{
  572.             $str substr($dsn0$at);
  573.             $dsn substr($dsn$at 1);
  574.             if (($pos strpos($str':')) !== false{
  575.                 $parsed['username'rawurldecode(substr($str0$pos));
  576.                 $parsed['password'rawurldecode(substr($str$pos 1));
  577.             else {
  578.                 $parsed['username'rawurldecode($str);
  579.             }
  580.         }
  581.  
  582.         // Find protocol and hostspec
  583.  
  584.         if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|'$dsn$match)) {
  585.             // $dsn => proto(proto_opts)/database
  586.             $proto       $match[1];
  587.             $proto_opts  $match[2$match[2false;
  588.             $dsn         $match[3];
  589.  
  590.         else {
  591.             // $dsn => protocol+hostspec/database (old format)
  592.             if (strpos($dsn'+'!== false{
  593.                 list($proto$dsnexplode('+'$dsn2);
  594.             }
  595.             if (strpos($dsn'/'!== false{
  596.                 list($proto_opts$dsnexplode('/'$dsn2);
  597.             else {
  598.                 $proto_opts $dsn;
  599.                 $dsn null;
  600.             }
  601.         }
  602.  
  603.         // process the different protocol options
  604.         $parsed['protocol'(!empty($proto)) $proto 'tcp';
  605.         $proto_opts rawurldecode($proto_opts);
  606.         if ($parsed['protocol'== 'tcp'{
  607.             if (strpos($proto_opts':'!== false{
  608.                 list($parsed['hostspec'],
  609.                      $parsed['port']explode(':'$proto_opts);
  610.             else {
  611.                 $parsed['hostspec'$proto_opts;
  612.             }
  613.         elseif ($parsed['protocol'== 'unix'{
  614.             $parsed['socket'$proto_opts;
  615.         }
  616.  
  617.         // Get dabase if any
  618.         // $dsn => database
  619.         if ($dsn{
  620.             if (($pos strpos($dsn'?')) === false{
  621.                 // /database
  622.                 $parsed['database'rawurldecode($dsn);
  623.             else {
  624.                 // /database?param1=value1&param2=value2
  625.                 $parsed['database'rawurldecode(substr($dsn0$pos));
  626.                 $dsn substr($dsn$pos 1);
  627.                 if (strpos($dsn'&'!== false{
  628.                     $opts explode('&'$dsn);
  629.                 else // database?param1=value1
  630.                     $opts array($dsn);
  631.                 }
  632.                 foreach ($opts as $opt{
  633.                     list($key$valueexplode('='$opt);
  634.                     if (!isset($parsed[$key])) {
  635.                         // don't allow params overwrite
  636.                         $parsed[$keyrawurldecode($value);
  637.                     }
  638.                 }
  639.             }
  640.         }
  641.  
  642.         return $parsed;
  643.     }
  644. }
  645.  
  646. /**
  647.  *  Mock DB_common for testing
  648.  *  @todo Implement mock DB_common class
  649.  */
  650. class DB_common extends PEAR {
  651.  
  652.     /**
  653.      *  Mock Database
  654.      */
  655.     protected static $database =
  656.         //  Person names table
  657.         array('person_names' =>
  658.               //  Description
  659.               array('info' =>
  660.                     array(array('table' => 'person_names',
  661.                                 'name'  => 'id',
  662.                                 'type'  => 'int',
  663.                                 'len'   => '11',
  664.                                 'flags' => 'primary_key not_null'),
  665.                           array('table' => 'person_names',
  666.                                 'name'  => 'prefix',
  667.                                 'type'  => 'string',
  668.                                 'len'   => '20',
  669.                                 'flags' => ''),
  670.                           array('table' => 'person_names',
  671.                                 'name'  => 'first_name',
  672.                                 'type'  => 'string',
  673.                                 'len'   => '40',
  674.                                 'flags' => ''),
  675.                           array('table' => 'person_names',
  676.                                 'name'  => 'mi',
  677.                                 'type'  => 'string',
  678.                                 'len'   => '1',
  679.                                 'flags' => ''),
  680.                           array('table' => 'person_names',
  681.                                 'name'  => 'last_name',
  682.                                 'type'  => 'string',
  683.                                 'len'   => '40',
  684.                                 'flags' => ''),
  685.                           array('table' => 'person_names',
  686.                                 'name'  => 'suffix',
  687.                                 'type'  => 'string',
  688.                                 'len'   => '20',
  689.                                 'flags' => ''),
  690.                           ),
  691.                     'data' =>
  692.                     array()
  693.                     ),
  694.  
  695.               //  Data types table
  696.               'data_types' =>
  697.  
  698.               //  Description
  699.               array('info' =>
  700.                     array(array("table" => "data_types",
  701.                                 "name"  => "id",
  702.                                 "type"  => "int",
  703.                                 "len"   => '11',
  704.                                 "flags" => "not_null primary_key auto_increment"),
  705.                           array("table" => "data_types",
  706.                                 "name"  => "bit_type",
  707.                                 "type"  => "int",
  708.                                 "len"   => '1',
  709.                                 "flags" => ""),
  710.                           array("table" => "data_types",
  711.                                 "name"  => "tinyint_type",
  712.                                 "type"  => "int",
  713.                                 "len"   =>  '4',
  714.                                 "flags" =>  ""),
  715.                           array("table" =>  "data_types",
  716.                                 "name"  =>  "bool_type",
  717.                                 "type"  =>  "int",
  718.                                 "len"   =>  '1',
  719.                                 "flags" =>  ""),
  720.                           array("table" =>  "data_types",
  721.                                 "name"  =>  "boolean_type",
  722.                                 "type"  =>  "int",
  723.                                 "len"   =>  '1',
  724.                                 "flags" =>  ""),
  725.                           array("table" =>  "data_types",
  726.                                 "name"  =>  "smallint_type",
  727.                                 "type"  =>  "int",
  728.                                 "len"   =>  '6',
  729.                                 "flags" =>  ""),
  730.                           array("table" =>  "data_types",
  731.                                 "name"  =>  "mediumint_type",
  732.                                 "type"  =>  "int",
  733.                                 "len"   =>  '9',
  734.                                 "flags" =>  ""),
  735.                           array("table"   =>  "data_types",
  736.                                 "name"    =>  "int_type",
  737.                                 "type"    =>  "int",
  738.                                 "len"     =>  '11',
  739.                                 "flags"   =>  ""),
  740.                           array("table" =>  "data_types",
  741.                                 "name"  =>  "integer_type",
  742.                                 "type"  =>  "int",
  743.                                 "len"   =>  '11',
  744.                                 "flags" =>  ""),
  745.                           array("table" =>  "data_types",
  746.                                 "name"  =>  "bigint_type",
  747.                                 "type"  =>  "int",
  748.                                 "len"   =>  '20',
  749.                                 "flags" =>  ""),
  750.                           array("table" =>  "data_types",
  751.                                 "name"  =>  "float_type",
  752.                                 "type"  =>  "real",
  753.                                 "len"   =>  '12',
  754.                                 "flags" =>  ""),
  755.                           array("table" =>  "data_types",
  756.                                 "name"  =>  "double_type",
  757.                                 "type"  =>  "real",
  758.                                 "len"   =>  '22',
  759.                                 "flags" =>  ""),
  760.                           array("table" =>  "data_types",
  761.                                 "name"  =>  "double_precision_type",
  762.                                 "type"  =>  "real",
  763.                                 "len"   =>  '22',
  764.                                 "flags" =>  ""),
  765.                           array("table" =>  "data_types",
  766.                                 "name"  =>  "decimal_type",
  767.                                 "type"  =>  "real",
  768.                                 "len"   =>  '11',
  769.                                 "flags" =>  ""),
  770.                           array("table" =>  "data_types",
  771.                                 "name"  =>  "dec_type",
  772.                                 "type"  =>  "real",
  773.                                 "len"   =>  '11',
  774.                                 "flags" =>  ""),
  775.                           array("table" => "data_types",
  776.                                 "name"  => "numeric_type",
  777.                                 "type"  => "real",
  778.                                 "len"   => '11',
  779.                                 "flags" => ""),
  780.                           array("table" => "data_types",
  781.                                 "name"  => "fixed_type",
  782.                                 "type"  => "real",
  783.                                 "len"   => '11',
  784.                                 "flags" => ""),
  785.                           array("table" => "data_types",
  786.                                 "name"  => "date_type",
  787.                                 "type"  => "date",
  788.                                 "len"   => '10',
  789.                                 "flags" => "binary"),
  790.                           array("table" => "data_types",
  791.                                 "name"  => "datetime_type",
  792.                                 "type"  => "datetime",
  793.                                 "len"   => '19',
  794.                                 "flags" => "binary"),
  795.                           array("table" => "data_types",
  796.                                 "name"  => "timestamp_type",
  797.                                 "type"  => "timestamp",
  798.                                 "len"   => '19',
  799.                                 "flags" => "unsigned zerofill binary"),
  800.                           array("table" => "data_types",
  801.                                 "name"  => "time_type",
  802.                                 "type"  => "time",
  803.                                 "len"   => '8',
  804.                                 "flags" => "binary"),
  805.                           array("table" => "data_types",
  806.                                 "name"  => "year_type",
  807.                                 "type"  => "year",
  808.                                 "len"   => '4',
  809.                                 "flags" => "unsigned zerofill"),
  810.                           array("table" => "data_types",
  811.                                 "name"  => "char_type",
  812.                                 "type"  => "string",
  813.                                 "len"   => '20',
  814.                                 "flags" => ""),
  815.                           array("table" => "data_types",
  816.                                 "name"  => "varchar_type",
  817.                                 "type"  => "string",
  818.                                 "len"   => '20',
  819.                                 "flags" => ""),
  820.                           array("table" => "data_types",
  821.                                 "name"  => "nchar_type",
  822.                                 "type"  => "string",
  823.                                 "len"   => '20',
  824.                                 "flags" => ""),
  825.                           array("table" => "data_types",
  826.                                 "name"  => "binary_type",
  827.                                 "type"  => "string",
  828.                                 "len"   => '20',
  829.                                 "flags" => "binary"),
  830.                           array("table" => "data_types",
  831.                                 "name"  => "varbinary_type",
  832.                                 "type"  => "string",
  833.                                 "len"   => '20',
  834.                                 "flags" => "binary"),
  835.                           array("table" => "data_types",
  836.                                 "name"  => "tinyblob_type",
  837.                                 "type"  => "blob",
  838.                                 "len"   => '255',
  839.                                 "flags" => "blob binary"),
  840.                           array("table" => "data_types",
  841.                                 "name"  => "tinytext_type",
  842.                                 "type"  => "blob",
  843.                                 "len"   => '255',
  844.                                 "flags" => "blob"),
  845.                           array("table" => "data_types",
  846.                                 "name"  => "blob_type",
  847.                                 "type"  => "blob",
  848.                                 "len"   => '65535',
  849.                                 "flags" => "blob binary"),
  850.                           array("table" => "data_types",
  851.                                 "name"  => "text_type",
  852.                                 "type"  => "blob",
  853.                                 "len"   => '65535',
  854.                                 "flags" => "blob"),
  855.                           array("table" => "data_types",
  856.                                 "name"  => "mediumblob_type",
  857.                                 "type"  => "blob",
  858.                                 "len"   => '16777215',
  859.                                 "flags" => "blob binary"),
  860.                           array("table" => "data_types",
  861.                                 "name"  => "mediumtext_type",
  862.                                 "type"  => "blob",
  863.                                 "len"   => '16777215',
  864.                                 "flags" => "blob"),
  865.                           array("table" => "data_types",
  866.                                 "name"  => "longblob_type",
  867.                                 "type"  => "blob",
  868.                                 "len"   => '-1',
  869.                                 "flags" => "blob binary"),
  870.                           array("table" => "data_types",
  871.                                 "name"  => "longtext_type",
  872.                                 "type"  => "blob",
  873.                                 "len"   => '-1',
  874.                                 "flags" => "blob"),
  875.                           array("table" => "data_types",
  876.                                 "name"  => "enum_type",
  877.                                 "type"  => "string",
  878.                                 "len"   => '3',
  879.                                 "flags" => "enum"),
  880.                           array("table" => "data_types",
  881.                                 "name"  => "set_type",
  882.                                 "type"  => "string",
  883.                                 "len"   => '7',
  884.                                 "flags" => "set"),
  885.                           ),
  886.                     'data' =>
  887.                     array()
  888.                     ),
  889.               );
  890.  
  891.     /**
  892.      * Run-time configuration options
  893.      *
  894.      * @var array 
  895.      * @see DB_common::setOption()
  896.      */
  897.     var $options = array(
  898.         'result_buffering' => 500,
  899.         'persistent' => false,
  900.         'ssl' => false,
  901.         'debug' => 0,
  902.         'seqname_format' => '%s_seq',
  903.         'autofree' => false,
  904.         'portability' => DB_PORTABILITY_NONE,
  905.         'optimize' => 'performance',  // Deprecated.  Use 'portability'.
  906.     );
  907.  
  908.     /**
  909.      *  List of expected queries and returns
  910.      */
  911.     private $expected_list = null;
  912.  
  913.     /**
  914.      *  Cursor in list of expected queries and returns
  915.      */
  916.     private $expected_list_cursor = null;
  917.  
  918.     /**
  919.      *  Expected query
  920.      *  @var string 
  921.      */
  922.     private $expected_query = null;
  923.  
  924.     /**
  925.      *  Result to be returned from expected query
  926.      *  @var string 
  927.      */
  928.     private $expected_result = null;
  929.  
  930.     /**
  931.      * This constructor calls <kbd>$this->PEAR('DB_Error')</kbd>
  932.      *
  933.      * @return void 
  934.      */
  935.     function DB_common()
  936.     {
  937.         $this->PEAR('DB_Error');
  938.     }
  939.  
  940.     /**
  941.      * Automatically indicates which properties should be saved
  942.      * when PHP's serialize() function is called
  943.      *
  944.      * @return array  the array of properties names that should be saved
  945.      *  @todo Implement mock DB_common::__sleep
  946.      */
  947.     function __sleep()
  948.     {
  949. //        if ($this->connection) {
  950. //            // Don't disconnect(), people use serialize() for many reasons
  951. //            $this->was_connected = true;
  952. //        } else {
  953. //            $this->was_connected = false;
  954. //        }
  955. //        if (isset($this->autocommit)) {
  956. //            return array('autocommit',
  957. //                         'dbsyntax',
  958. //                         'dsn',
  959. //                         'features',
  960. //                         'fetchmode',
  961. //                         'fetchmode_object_class',
  962. //                         'options',
  963. //                         'was_connected',
  964. //                   );
  965. //        } else {
  966. //            return array('dbsyntax',
  967. //                         'dsn',
  968. //                         'features',
  969. //                         'fetchmode',
  970. //                         'fetchmode_object_class',
  971. //                         'options',
  972. //                         'was_connected',
  973. //                   );
  974. //        }
  975.     }
  976.  
  977.     /**
  978.      * Automatically reconnects to the database when PHP's unserialize()
  979.      * function is called
  980.      *
  981.      * @return void 
  982.      *  @todo Implement mock DB_common::__wakeup
  983.      */
  984.     function __wakeup()
  985.     {
  986. //        if ($this->was_connected) {
  987. //            $this->connect($this->dsn, $this->options);
  988. //        }
  989.     }
  990.  
  991.     /**
  992.      * Automatic string conversion for PHP 5
  993.      *
  994.      * @return string  a string describing the current PEAR DB object
  995.      *  @todo Implement mock DB_common::__toString
  996.      */
  997.     public function __toString()
  998.     {
  999. //        $info = strtolower(get_class($this));
  1000. //        $info .=  ': (phptype=' . $this->phptype .
  1001. //                  ', dbsyntax=' . $this->dbsyntax .
  1002. //                  ')';
  1003. //        if ($this->connection) {
  1004. //            $info .= ' [connected]';
  1005. //        }
  1006. //        return $info;
  1007.     }
  1008.  
  1009.     /**
  1010.      * Quotes a string so it can be safely used as a table or column name
  1011.      *
  1012.      * @param string $str  the identifier name to be quoted
  1013.      * @return string  the quoted identifier
  1014.      */
  1015.     public function quoteIdentifier($str)
  1016.     {
  1017.         return '"' str_replace('"''""'$str'"';
  1018.     }
  1019.  
  1020.     /**
  1021.      * Formats input so it can be safely used in a query
  1022.      *
  1023.      * @see DB_common::escapeSimple()
  1024.      *  @todo Implement mock DB_common::quoteSmart
  1025.      */
  1026.     public function quoteSmart($in)
  1027.     {
  1028. //        if (is_int($in) || is_double($in)) {
  1029. //            return $in;
  1030. //        } elseif (is_bool($in)) {
  1031. //            return $in ? 1 : 0;
  1032. //        } elseif (is_null($in)) {
  1033. //            return 'NULL';
  1034. //        } else {
  1035. //            return "'" . $this->escapeSimple($in) . "'";
  1036. //        }
  1037.     }
  1038.  
  1039.     /**
  1040.      * Escapes a string according to the current DBMS's standards
  1041.      *
  1042.      * @param string $str  the string to be escaped
  1043.      * @return string  the escaped string
  1044.      * @see DB_common::quoteSmart()
  1045.      *  @todo Implement mock DB_common::escapeSimple
  1046.      */
  1047.     public function escapeSimple($str)
  1048.     {
  1049. //        return str_replace("'", "''", $str);
  1050.     }
  1051.  
  1052.     /**
  1053.      * Tells whether the present driver supports a given feature
  1054.      *
  1055.      * @param string $feature  the feature you're curious about
  1056.      * @return bool  whether this driver supports $feature
  1057.      *  @todo Implement mock DB_common::provides
  1058.      */
  1059.     public function provides($feature)
  1060.     {
  1061. //        return $this->features[$feature];
  1062.     }
  1063.  
  1064.     /**
  1065.      * Sets the fetch mode that should be used by default for query results
  1066.      *
  1067.      * @param integer $fetchmode    DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC
  1068.      *                                or DB_FETCHMODE_OBJECT
  1069.      * @param string $object_class  the class name of the object to be returned
  1070.      *                                by the fetch methods when the
  1071.      *                                DB_FETCHMODE_OBJECT mode is selected.
  1072.      *                                If no class is specified by default a cast
  1073.      *                                to object from the assoc array row will be
  1074.      *                                done.  There is also the posibility to use
  1075.      *                                and extend the 'DB_row' class.
  1076.      *
  1077.      * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT
  1078.      *  @todo Implement mock DB_common::setFetchMode
  1079.      */
  1080.     public function setFetchMode($fetchmode$object_class 'stdClass')
  1081.     {
  1082. //        switch ($fetchmode) {
  1083. //            case DB_FETCHMODE_OBJECT:
  1084. //                $this->fetchmode_object_class = $object_class;
  1085. //            case DB_FETCHMODE_ORDERED:
  1086. //            case DB_FETCHMODE_ASSOC:
  1087. //                $this->fetchmode = $fetchmode;
  1088. //                break;
  1089. //            default:
  1090. //                return $this->raiseError('invalid fetchmode mode');
  1091. //        }
  1092.     }
  1093.  
  1094.     /**
  1095.      * Sets run-time configuration options for PEAR DB
  1096.      *
  1097.      * @param string $option option name
  1098.      * @param mixed  $value value for the option
  1099.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1100.      * @see DB_common::$options
  1101.      *  @todo Implement mock DB_common::setOption
  1102.      */
  1103.     public function setOption($option$value)
  1104.     {
  1105.         if (isset($this->options[$option])) {
  1106.             $this->options[$option$value;
  1107.             return DB_OK;
  1108.         }
  1109.         PHPUnit2_Framework_Assert::fail("DB_common::setOption called"
  1110.                                         ." with unknown option $option");
  1111.     }
  1112.  
  1113.     /**
  1114.      * Returns the value of an option
  1115.      *
  1116.      * @param string $option  the option name you're curious about
  1117.      * @return mixed  the option's value
  1118.      *  @todo Implement mock DB_common::getOption
  1119.      */
  1120.     public function getOption($option)
  1121.     {
  1122. //        if (isset($this->options[$option])) {
  1123. //            return $this->options[$option];
  1124. //        }
  1125. //        return $this->raiseError("unknown option $option");
  1126.     }
  1127.  
  1128.     /**
  1129.      * Prepares a query for multiple execution with execute()
  1130.      *
  1131.      * @param string $query  the query to be prepared
  1132.      * @return mixed  DB statement resource on success. A DB_Error object
  1133.      *                  on failure.
  1134.      * @see DB_common::execute()
  1135.      *  @todo Implement mock DB_common::prepare
  1136.      */
  1137.     public function prepare($query)
  1138.     {
  1139.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1140.                                         . " multiple execution");
  1141. //        $tokens   = preg_split('/((?<!\\\)[&?!])/', $query, -1,
  1142. //                               PREG_SPLIT_DELIM_CAPTURE);
  1143. //        $token     = 0;
  1144. //        $types     = array();
  1145. //        $newtokens = array();
  1146. //
  1147. //        foreach ($tokens as $val) {
  1148. //            switch ($val) {
  1149. //                case '?':
  1150. //                    $types[$token++] = DB_PARAM_SCALAR;
  1151. //                    break;
  1152. //                case '&':
  1153. //                    $types[$token++] = DB_PARAM_OPAQUE;
  1154. //                    break;
  1155. //                case '!':
  1156. //                    $types[$token++] = DB_PARAM_MISC;
  1157. //                    break;
  1158. //                default:
  1159. //                    $newtokens[] = preg_replace('/\\\([&?!])/', "\\1", $val);
  1160. //            }
  1161. //        }
  1162. //
  1163. //        $this->prepare_tokens[] = &$newtokens;
  1164. //        end($this->prepare_tokens);
  1165. //
  1166. //        $k = key($this->prepare_tokens);
  1167. //        $this->prepare_types[$k] = $types;
  1168. //        $this->prepared_queries[$k] = implode(' ', $newtokens);
  1169. //
  1170. //        return $k;
  1171.     }
  1172.  
  1173.  
  1174.     /**
  1175.      * Automaticaly generates an insert or update query and pass it to
  1176.      * prepare()
  1177.      *
  1178.      * @param string $table         the table name
  1179.      * @param array  $table_fields  the array of field names
  1180.      * @param int    $mode          a type of query to make:
  1181.      *                                DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  1182.      * @param string $where         for update queries: the WHERE clause to
  1183.      *                                append to the SQL statement.  Don't
  1184.      *                                include the "WHERE" keyword.
  1185.      *
  1186.      * @return resource  the query handle
  1187.      * @uses DB_common::prepare(), DB_common::buildManipSQL()
  1188.      *  @todo Implement mock DB_common::autoPrepare
  1189.      */
  1190.     public function autoPrepare($table$table_fields$mode DB_AUTOQUERY_INSERT,
  1191.                          $where false)
  1192.     {
  1193. //        $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
  1194. //        if (DB::isError($query)) {
  1195. //            return $query;
  1196. //        }
  1197. //        return $this->prepare($query);
  1198.     }
  1199.  
  1200.     /**
  1201.      * Automaticaly generates an insert or update query and call prepare()
  1202.      * and execute() with it
  1203.      *
  1204.      * @param string $table         the table name
  1205.      * @param array  $fields_values the associative array where $key is a
  1206.      *                                field name and $value its value
  1207.      * @param int    $mode          a type of query to make:
  1208.      *                                DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  1209.      * @param string $where         for update queries: the WHERE clause to
  1210.      *                                append to the SQL statement.  Don't
  1211.      *                                include the "WHERE" keyword.
  1212.      *
  1213.      * @return mixed  a new DB_result object for successful SELECT queries
  1214.      *                  or DB_OK for successul data manipulation queries.
  1215.      *                  A DB_Error object on failure.
  1216.      *
  1217.      * @uses DB_common::autoPrepare(), DB_common::execute()
  1218.      *  @todo Implement mock DB_common::autoExecute
  1219.      */
  1220.     public function autoExecute($table$fields_values$mode DB_AUTOQUERY_INSERT,
  1221.                          $where false)
  1222.     {
  1223.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1224.                                         . " multiple execution");
  1225. //        $sth = $this->autoPrepare($table, array_keys($fields_values), $mode,
  1226. //                                  $where);
  1227. //        if (DB::isError($sth)) {
  1228. //            return $sth;
  1229. //        }
  1230. //        $ret =& $this->execute($sth, array_values($fields_values));
  1231. //        $this->freePrepared($sth);
  1232. //        return $ret;
  1233.     }
  1234.  
  1235.     /**
  1236.      * Produces an SQL query string for autoPrepare()
  1237.      *
  1238.      * @param string $table         the table name
  1239.      * @param array  $table_fields  the array of field names
  1240.      * @param int    $mode          a type of query to make:
  1241.      *                                DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
  1242.      * @param string $where         for update queries: the WHERE clause to
  1243.      *                                append to the SQL statement.  Don't
  1244.      *                                include the "WHERE" keyword.
  1245.      *
  1246.      * @return string  the sql query for autoPrepare()
  1247.      *  @todo Implement mock DB_common::buildManipSQL
  1248.      */
  1249.     public function buildManipSQL($table$table_fields$mode$where false)
  1250.     {
  1251. //        if (count($table_fields) == 0) {
  1252. //            return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
  1253. //        }
  1254. //        $first = true;
  1255. //        switch ($mode) {
  1256. //            case DB_AUTOQUERY_INSERT:
  1257. //                $values = '';
  1258. //                $names = '';
  1259. //                foreach ($table_fields as $value) {
  1260. //                    if ($first) {
  1261. //                        $first = false;
  1262. //                    } else {
  1263. //                        $names .= ',';
  1264. //                        $values .= ',';
  1265. //                    }
  1266. //                    $names .= $value;
  1267. //                    $values .= '?';
  1268. //                }
  1269. //                return "INSERT INTO $table ($names) VALUES ($values)";
  1270. //            case DB_AUTOQUERY_UPDATE:
  1271. //                $set = '';
  1272. //                foreach ($table_fields as $value) {
  1273. //                    if ($first) {
  1274. //                        $first = false;
  1275. //                    } else {
  1276. //                        $set .= ',';
  1277. //                    }
  1278. //                    $set .= "$value = ?";
  1279. //                }
  1280. //                $sql = "UPDATE $table SET $set";
  1281. //                if ($where) {
  1282. //                    $sql .= " WHERE $where";
  1283. //                }
  1284. //                return $sql;
  1285. //            default:
  1286. //                return $this->raiseError(DB_ERROR_SYNTAX);
  1287. //        }
  1288.     }
  1289.  
  1290.     /**
  1291.      * Executes a DB statement prepared with prepare()
  1292.      *
  1293.      * @param resource $stmt  a DB statement resource returned from prepare()
  1294.      * @param mixed    $data  array, string or numeric data to be used in
  1295.      *                          execution of the statement.  Quantity of items
  1296.      *                          passed must match quantity of placeholders in
  1297.      *                          query:  meaning 1 placeholder for non-array
  1298.      *                          parameters or 1 placeholder per array element.
  1299.      *
  1300.      * @return mixed  a new DB_result object for successful SELECT queries
  1301.      *                  or DB_OK for successul data manipulation queries.
  1302.      *                  A DB_Error object on failure.
  1303.      *
  1304.      * @see DB_common::prepare()
  1305.      *  @todo Implement mock DB_common::execute
  1306.      */
  1307.     public function &execute($stmt$data array())
  1308.     {
  1309.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1310.                                         . " multiple execution");
  1311. //        $realquery = $this->executeEmulateQuery($stmt, $data);
  1312. //        if (DB::isError($realquery)) {
  1313. //            return $realquery;
  1314. //        }
  1315. //        $result = $this->simpleQuery($realquery);
  1316. //
  1317. //        if ($result === DB_OK || DB::isError($result)) {
  1318. //            return $result;
  1319. //        } else {
  1320. //            $tmp =& new DB_result($this, $result);
  1321. //            return $tmp;
  1322. //        }
  1323.     }
  1324.  
  1325.     /**
  1326.      * Emulates executing prepared statements if the DBMS not support them
  1327.      *
  1328.      * @param resource $stmt  a DB statement resource returned from execute()
  1329.      * @param mixed    $data  array, string or numeric data to be used in
  1330.      *                          execution of the statement.  Quantity of items
  1331.      *                          passed must match quantity of placeholders in
  1332.      *                          query:  meaning 1 placeholder for non-array
  1333.      *                          parameters or 1 placeholder per array element.
  1334.      *
  1335.      * @return mixed  a string containing the real query run when emulating
  1336.      *                  prepare/execute.  A DB_Error object on failure.
  1337.      *
  1338.      * @see DB_common::execute()
  1339.      *  @todo Implement mock DB_common::executeEmulateQuery
  1340.      */
  1341.     protected function executeEmulateQuery($stmt$data array())
  1342.     {
  1343.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1344.                                         . " multiple execution");
  1345. //        $stmt = (int)$stmt;
  1346. //        $data = (array)$data;
  1347. //        $this->last_parameters = $data;
  1348. //
  1349. //        if (count($this->prepare_types[$stmt]) != count($data)) {
  1350. //            $this->last_query = $this->prepared_queries[$stmt];
  1351. //            return $this->raiseError(DB_ERROR_MISMATCH);
  1352. //        }
  1353. //
  1354. //        $realquery = $this->prepare_tokens[$stmt][0];
  1355. //
  1356. //        $i = 0;
  1357. //        foreach ($data as $value) {
  1358. //            if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) {
  1359. //                $realquery .= $this->quoteSmart($value);
  1360. //            } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) {
  1361. //                $fp = @fopen($value, 'rb');
  1362. //                if (!$fp) {
  1363. //                    return $this->raiseError(DB_ERROR_ACCESS_VIOLATION);
  1364. //                }
  1365. //                $realquery .= $this->quoteSmart(fread($fp, filesize($value)));
  1366. //                fclose($fp);
  1367. //            } else {
  1368. //                $realquery .= $value;
  1369. //            }
  1370. //
  1371. //            $realquery .= $this->prepare_tokens[$stmt][++$i];
  1372. //        }
  1373. //
  1374. //        return $realquery;
  1375.     }
  1376.  
  1377.     /**
  1378.      * Performs several execute() calls on the same statement handle
  1379.      *
  1380.      * @param resource $stmt  query handle from prepare()
  1381.      * @param array    $data  numeric array containing the
  1382.      *                          data to insert into the query
  1383.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1384.      * @see DB_common::prepare(), DB_common::execute()
  1385.      *  @todo Implement mock DB_common::executeMultiple
  1386.      */
  1387.     function executeMultiple($stmt$data)
  1388.     {
  1389.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1390.                                         . " multiple execution");
  1391. //        foreach ($data as $value) {
  1392. //            $res =& $this->execute($stmt, $value);
  1393. //            if (DB::isError($res)) {
  1394. //                return $res;
  1395. //            }
  1396. //        }
  1397. //        return DB_OK;
  1398.     }
  1399.  
  1400.     /**
  1401.      * Frees the internal resources associated with a prepared query
  1402.      *
  1403.      * @param resource $stmt           the prepared statement's PHP resource
  1404.      * @param bool     $free_resource  should the PHP resource be freed too?
  1405.      *                                   Use false if you need to get data
  1406.      *                                   from the result set later.
  1407.      * @return bool  TRUE on success, FALSE if $result is invalid
  1408.      * @see DB_common::prepare()
  1409.      *  @todo Implement mock DB_common::freePrepared
  1410.      */
  1411.     function freePrepared($stmt$free_resource true)
  1412.     {
  1413.         PHPUnit2_Framework_Assert::fail("DB does not support"
  1414.                                         . " multiple execution");
  1415. //        $stmt = (int)$stmt;
  1416. //        if (isset($this->prepare_tokens[$stmt])) {
  1417. //            unset($this->prepare_tokens[$stmt]);
  1418. //            unset($this->prepare_types[$stmt]);
  1419. //            unset($this->prepared_queries[$stmt]);
  1420. //            return true;
  1421. //        }
  1422. //        return false;
  1423.     }
  1424.  
  1425.     /**
  1426.      * Changes a query string for various DBMS specific reasons
  1427.      *
  1428.      * @param string $query  the query string to modify
  1429.      * @return string  the modified query string
  1430.      * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(),
  1431.      *       DB_sqlite::modifyQuery()
  1432.      *  @todo Implement mock DB_common::modifyQuery
  1433.      */
  1434.     protected function modifyQuery($query)
  1435.     {
  1436. //        return $query;
  1437.     }
  1438.  
  1439.     /**
  1440.      * Adds LIMIT clauses to a query string according to current DBMS standards
  1441.      *
  1442.      * @param string $query   the query to modify
  1443.      * @param int    $from    the row to start to fetching (0 = the first row)
  1444.      * @param int    $count   the numbers of rows to fetch
  1445.      * @param mixed  $params  array, string or numeric data to be used in
  1446.      *                          execution of the statement.  Quantity of items
  1447.      *                          passed must match quantity of placeholders in
  1448.      *                          query:  meaning 1 placeholder for non-array
  1449.      *                          parameters or 1 placeholder per array element.
  1450.      *
  1451.      * @return string  the query string with LIMIT clauses added
  1452.      *  @todo Implement mock DB_common::modifyLimitQuery
  1453.      */
  1454.     protected function modifyLimitQuery($query$from$count$params array())
  1455.     {
  1456. //        return $query;
  1457.     }
  1458.  
  1459.     /**
  1460.      *  Set expected query and return
  1461.      *
  1462.      *  This is a test routine that does not exist in the PEAR DB package.
  1463.      *  @param string $expected Expected query
  1464.      *  @param string $result Result to be returned when expected
  1465.      *   query is received.
  1466.      */
  1467.     public function expect_query($expected$result{
  1468.         $this->expected_query = $expected;
  1469.         $this->expected_result = $result;
  1470.     }
  1471.  
  1472.     /**
  1473.      *  Set list of expected queries and returns
  1474.      *
  1475.      *  This is a test routine that does not exist in the PEAR DB package.
  1476.      *  @param string $list Expected queries and returns
  1477.      */
  1478.     public function expect_queries($list{
  1479.         $this->expected_list = $list;
  1480.         $this->expected_list_cursor = 0;
  1481.         $this->expect_query($this->expected_list[0]['query'],
  1482.                             $this->expected_list[0]['result']);
  1483.     }
  1484.  
  1485.     /**
  1486.      *  Verify that all expected queries have been received
  1487.      *
  1488.      *  This is a test routine that does not exist in the PEAR DB package.
  1489.      */
  1490.     public function tally_queries({
  1491.         if ($this->expected_list_cursor < count($this->expected_list)) {
  1492.             PHPUnit2_Framework_Assert::fail("DB_mysql::expected query was"
  1493.                           ." not receivedexpected $this->expected_query");
  1494.         }
  1495.     }
  1496.  
  1497.     /**
  1498.      * Sends a query to the database server
  1499.      *
  1500.      * @param string $query   the SQL query or the statement to prepare
  1501.      * @param mixed  $params  array, string or numeric data to be used in
  1502.      *                          execution of the statement.  Quantity of items
  1503.      *                          passed must match quantity of placeholders in
  1504.      *                          query:  meaning 1 placeholder for non-array
  1505.      *                          parameters or 1 placeholder per array element.
  1506.      *
  1507.      * @return mixed  a new DB_result object for successful SELECT queries
  1508.      *                  or DB_OK for successul data manipulation queries.
  1509.      *                  A DB_Error object on failure.
  1510.      *
  1511.      * @see DB_result, DB_common::prepare(), DB_common::execute()
  1512.      *  @todo Implement mock DB_common::query
  1513.      */
  1514.     public function &query($query$params array())
  1515.     {
  1516.         $params = (array)$params;
  1517.         if (sizeof($params0{
  1518.             PHPUnit2_Framework_Assert::fail("DB does not support"
  1519.                                             . " multiple execution");
  1520.         }
  1521.         if (!is_null($this->expected_list)) {
  1522.             //  We are working through a list of queries.  If the
  1523.             //  number of queries received is greater than the number
  1524.             //  on the list, that's an error
  1525.             if ($this->expected_list_cursor >= count($this->expected_list)) {
  1526.                 PHPUnit2_Framework_Assert::fail(
  1527.                               "DB_mysql::query called with"
  1528.                              ."$queryexceeding number of queries expected");
  1529.                 }            
  1530.         }
  1531.         if ($query != $this->expected_query{
  1532.             PHPUnit2_Framework_Assert::fail('DB_mysql::query() called with'
  1533.                  .' "'.$query.'", expected "'.$this->expected_query.'"');
  1534.         }
  1535.         $result $this->expected_result;
  1536.         if (!is_null($this->expected_list)) {
  1537.             //  More queries are expected.  Advance the cursor
  1538.             $this->expected_list_cursor++;
  1539.             $this->expect_query(
  1540.               $this->expected_list[$this->expected_list_cursor]['query'],
  1541.               $this->expected_list[$this->expected_list_cursor]['result']);
  1542.         }
  1543.         return $result;
  1544. //        if (sizeof($params) > 0) {
  1545. //            $sth = $this->prepare($query);
  1546. //            if (DB::isError($sth)) {
  1547. //                return $sth;
  1548. //            }
  1549. //            $ret =& $this->execute($sth, $params);
  1550. //            $this->freePrepared($sth, false);
  1551. //            return $ret;
  1552. //        } else {
  1553. //            $this->last_parameters = array();
  1554. //            $result = $this->simpleQuery($query);
  1555. //            if ($result === DB_OK || DB::isError($result)) {
  1556. //                return $result;
  1557. //            } else {
  1558. //                $tmp =& new DB_result($this, $result);
  1559. //                return $tmp;
  1560. //            }
  1561. //        }
  1562.     }
  1563.  
  1564.     /**
  1565.      * Generates and executes a LIMIT query
  1566.      *
  1567.      * @param string $query   the query
  1568.      * @param intr   $from    the row to start to fetching (0 = the first row)
  1569.      * @param int    $count   the numbers of rows to fetch
  1570.      * @param mixed  $params  array, string or numeric data to be used in
  1571.      *                          execution of the statement.  Quantity of items
  1572.      *                          passed must match quantity of placeholders in
  1573.      *                          query:  meaning 1 placeholder for non-array
  1574.      *                          parameters or 1 placeholder per array element.
  1575.      *
  1576.      * @return mixed  a new DB_result object for successful SELECT queries
  1577.      *                  or DB_OK for successul data manipulation queries.
  1578.      *                  A DB_Error object on failure.
  1579.      *  @todo Implement mock DB_common::limitQuery
  1580.      */
  1581.     public function &limitQuery($query$from$count$params array())
  1582.     {
  1583. //        $query = $this->modifyLimitQuery($query, $from, $count, $params);
  1584. //        if (DB::isError($query)){
  1585. //            return $query;
  1586. //        }
  1587. //        $result =& $this->query($query, $params);
  1588. //        if (is_a($result, 'DB_result')) {
  1589. //            $result->setOption('limit_from', $from);
  1590. //            $result->setOption('limit_count', $count);
  1591. //        }
  1592. //        return $result;
  1593.     }
  1594.  
  1595.     /**
  1596.      * Fetches the first column of the first row from a query result
  1597.      *
  1598.      * @param string $query   the SQL query
  1599.      * @param mixed  $params  array, string or numeric data to be used in
  1600.      *                          execution of the statement.  Quantity of items
  1601.      *                          passed must match quantity of placeholders in
  1602.      *                          query:  meaning 1 placeholder for non-array
  1603.      *                          parameters or 1 placeholder per array element.
  1604.      *
  1605.      * @return mixed  the returned value of the query.
  1606.      *                  A DB_Error object on failure.
  1607.      *  @todo Implement mock DB_common::getOne
  1608.      */
  1609.     function &getOne($query$params array())
  1610.     {
  1611.         return $this->query($query,$params);
  1612.  
  1613. //            $sth = $this->prepare($query);
  1614. //            if (DB::isError($sth)) {
  1615. //                return $sth;
  1616. //            }
  1617. //            $res =& $this->execute($sth, $params);
  1618. //            $this->freePrepared($sth);
  1619. //        } else {
  1620. //            $res =& $this->query($query);
  1621. //        }
  1622. //
  1623. //        if (DB::isError($res)) {
  1624. //            return $res;
  1625. //        }
  1626. //
  1627. //        $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED);
  1628. //        $res->free();
  1629. //
  1630. //        if ($err !== DB_OK) {
  1631. //            return $err;
  1632. //        }
  1633. //
  1634. //        return $row[0];
  1635.     }
  1636.  
  1637.     /**
  1638.      * Fetches the first row of data returned from a query result
  1639.      *
  1640.      * @param string $query   the SQL query
  1641.      * @param mixed  $params  array, string or numeric data to be used in
  1642.      *                          execution of the statement.  Quantity of items
  1643.      *                          passed must match quantity of placeholders in
  1644.      *                          query:  meaning 1 placeholder for non-array
  1645.      *                          parameters or 1 placeholder per array element.
  1646.      * @param int $fetchmode  the fetch mode to use
  1647.      *
  1648.      * @return array  the first row of results as an array.
  1649.      *                  A DB_Error object on failure.
  1650.      *  @todo Implement mock DB_common::getRow
  1651.      */
  1652.     public function &getRow($query$params array(),
  1653.                      $fetchmode DB_FETCHMODE_DEFAULT)
  1654.     {
  1655. //        // compat check, the params and fetchmode parameters used to
  1656. //        // have the opposite order
  1657. //        if (!is_array($params)) {
  1658. //            if (is_array($fetchmode)) {
  1659. //                if ($params === null) {
  1660. //                    $tmp = DB_FETCHMODE_DEFAULT;
  1661. //                } else {
  1662. //                    $tmp = $params;
  1663. //                }
  1664. //                $params = $fetchmode;
  1665. //                $fetchmode = $tmp;
  1666. //            } elseif ($params !== null) {
  1667. //                $fetchmode = $params;
  1668. //                $params = array();
  1669. //            }
  1670. //        }
  1671. //        // modifyLimitQuery() would be nice here, but it causes BC issues
  1672. //        if (sizeof($params) > 0) {
  1673. //            $sth = $this->prepare($query);
  1674. //            if (DB::isError($sth)) {
  1675. //                return $sth;
  1676. //            }
  1677. //            $res =& $this->execute($sth, $params);
  1678. //            $this->freePrepared($sth);
  1679. //        } else {
  1680. //            $res =& $this->query($query);
  1681. //        }
  1682. //
  1683. //        if (DB::isError($res)) {
  1684. //            return $res;
  1685. //        }
  1686. //
  1687. //        $err = $res->fetchInto($row, $fetchmode);
  1688. //
  1689. //        $res->free();
  1690. //
  1691. //        if ($err !== DB_OK) {
  1692. //            return $err;
  1693. //        }
  1694. //
  1695. //        return $row;
  1696.     }
  1697.  
  1698.     /**
  1699.      * Fetches a single column from a query result and returns it as an
  1700.      * indexed array
  1701.      *
  1702.      * @param string $query   the SQL query
  1703.      * @param mixed  $col     which column to return (integer [column number,
  1704.      *                          starting at 0] or string [column name])
  1705.      * @param mixed  $params  array, string or numeric data to be used in
  1706.      *                          execution of the statement.  Quantity of items
  1707.      *                          passed must match quantity of placeholders in
  1708.      *                          query:  meaning 1 placeholder for non-array
  1709.      *                          parameters or 1 placeholder per array element.
  1710.      *
  1711.      * @return array  the results as an array.  A DB_Error object on failure.
  1712.      *
  1713.      * @see DB_common::query()
  1714.      *  @todo Implement mock DB_common::getCol
  1715.      */
  1716.     public function &getCol($query$col 0$params array())
  1717.     {
  1718. //        $params = (array)$params;
  1719. //        if (sizeof($params) > 0) {
  1720. //            $sth = $this->prepare($query);
  1721. //
  1722. //            if (DB::isError($sth)) {
  1723. //                return $sth;
  1724. //            }
  1725. //
  1726. //            $res =& $this->execute($sth, $params);
  1727. //            $this->freePrepared($sth);
  1728. //        } else {
  1729. //            $res =& $this->query($query);
  1730. //        }
  1731. //
  1732. //        if (DB::isError($res)) {
  1733. //            return $res;
  1734. //        }
  1735. //
  1736. //        $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC;
  1737. //
  1738. //        if (!is_array($row = $res->fetchRow($fetchmode))) {
  1739. //            $ret = array();
  1740. //        } else {
  1741. //            if (!array_key_exists($col, $row)) {
  1742. //                $ret =& $this->raiseError(DB_ERROR_NOSUCHFIELD);
  1743. //            } else {
  1744. //                $ret = array($row[$col]);
  1745. //                while (is_array($row = $res->fetchRow($fetchmode))) {
  1746. //                    $ret[] = $row[$col];
  1747. //                }
  1748. //            }
  1749. //        }
  1750. //
  1751. //        $res->free();
  1752. //
  1753. //        if (DB::isError($row)) {
  1754. //            $ret = $row;
  1755. //        }
  1756. //
  1757. //        return $ret;
  1758.     }
  1759.  
  1760.     /**
  1761.      * Fetches an entire query result and returns it as an
  1762.      * associative array using the first column as the key
  1763.      *
  1764.      * @param string $query        the SQL query
  1765.      * @param bool   $force_array  used only when the query returns
  1766.      *                               exactly two columns.  If true, the values
  1767.      *                               of the returned array will be one-element
  1768.      *                               arrays instead of scalars.
  1769.      * @param mixed  $params       array, string or numeric data to be used in
  1770.      *                               execution of the statement.  Quantity of
  1771.      *                               items passed must match quantity of
  1772.      *                               placeholders in query:  meaning 1
  1773.      *                               placeholder for non-array parameters or
  1774.      *                               1 placeholder per array element.
  1775.      * @param int   $fetchmode     the fetch mode to use
  1776.      * @param bool  $group         if true, the values of the returned array
  1777.      *                               is wrapped in another array.  If the same
  1778.      *                               key value (in the first column) repeats
  1779.      *                               itself, the values will be appended to
  1780.      *                               this array instead of overwriting the
  1781.      *                               existing values.
  1782.      *
  1783.      * @return array  the associative array containing the query results.
  1784.      *                 A DB_Error object on failure.
  1785.      *  @todo Implement mock DB_common::getAssoc
  1786.      */
  1787.     public function &getAssoc($query$force_array false$params array(),
  1788.                        $fetchmode DB_FETCHMODE_DEFAULT$group false)
  1789.     {
  1790. //        $params = (array)$params;
  1791. //        if (sizeof($params) > 0) {
  1792. //            $sth = $this->prepare($query);
  1793. //
  1794. //            if (DB::isError($sth)) {
  1795. //                return $sth;
  1796. //            }
  1797. //
  1798. //            $res =& $this->execute($sth, $params);
  1799. //            $this->freePrepared($sth);
  1800. //        } else {
  1801. //            $res =& $this->query($query);
  1802. //        }
  1803. //
  1804. //        if (DB::isError($res)) {
  1805. //            return $res;
  1806. //        }
  1807. //        if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  1808. //            $fetchmode = $this->fetchmode;
  1809. //        }
  1810. //        $cols = $res->numCols();
  1811. //
  1812. //        if ($cols < 2) {
  1813. //            $tmp =& $this->raiseError(DB_ERROR_TRUNCATED);
  1814. //            return $tmp;
  1815. //        }
  1816. //
  1817. //        $results = array();
  1818. //
  1819. //        if ($cols > 2 || $force_array) {
  1820. //            // return array values
  1821. //            // XXX this part can be optimized
  1822. //            if ($fetchmode == DB_FETCHMODE_ASSOC) {
  1823. //                while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) {
  1824. //                    reset($row);
  1825. //                    $key = current($row);
  1826. //                    unset($row[key($row)]);
  1827. //                    if ($group) {
  1828. //                        $results[$key][] = $row;
  1829. //                    } else {
  1830. //                        $results[$key] = $row;
  1831. //                    }
  1832. //                }
  1833. //            } elseif ($fetchmode == DB_FETCHMODE_OBJECT) {
  1834. //                while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) {
  1835. //                    $arr = get_object_vars($row);
  1836. //                    $key = current($arr);
  1837. //                    if ($group) {
  1838. //                        $results[$key][] = $row;
  1839. //                    } else {
  1840. //                        $results[$key] = $row;
  1841. //                    }
  1842. //                }
  1843. //            } else {
  1844. //                while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1845. //                    // we shift away the first element to get
  1846. //                    // indices running from 0 again
  1847. //                    $key = array_shift($row);
  1848. //                    if ($group) {
  1849. //                        $results[$key][] = $row;
  1850. //                    } else {
  1851. //                        $results[$key] = $row;
  1852. //                    }
  1853. //                }
  1854. //            }
  1855. //            if (DB::isError($row)) {
  1856. //                $results = $row;
  1857. //            }
  1858. //        } else {
  1859. //            // return scalar values
  1860. //            while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) {
  1861. //                if ($group) {
  1862. //                    $results[$row[0]][] = $row[1];
  1863. //                } else {
  1864. //                    $results[$row[0]] = $row[1];
  1865. //                }
  1866. //            }
  1867. //            if (DB::isError($row)) {
  1868. //                $results = $row;
  1869. //            }
  1870. //        }
  1871. //
  1872. //        $res->free();
  1873. //
  1874. //        return $results;
  1875.     }
  1876.  
  1877.     /**
  1878.      * Fetches all of the rows from a query result
  1879.      *
  1880.      * @param string $query      the SQL query
  1881.      * @param mixed  $params     array, string or numeric data to be used in
  1882.      *                             execution of the statement.  Quantity of
  1883.      *                             items passed must match quantity of
  1884.      *                             placeholders in query:  meaning 1
  1885.      *                             placeholder for non-array parameters or
  1886.      *                             1 placeholder per array element.
  1887.      * @param int    $fetchmode  the fetch mode to use:
  1888.      *                             + DB_FETCHMODE_ORDERED
  1889.      *                             + DB_FETCHMODE_ASSOC
  1890.      *                             + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED
  1891.      *                             + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED
  1892.      *
  1893.      * @return array  the nested array.  A DB_Error object on failure.
  1894.      *  @todo Implement mock DB_common::getAll
  1895.      */
  1896.     public function &getAll($query$params array(),
  1897.                      $fetchmode DB_FETCHMODE_DEFAULT)
  1898.     {
  1899. //        // compat check, the params and fetchmode parameters used to
  1900. //        // have the opposite order
  1901. //        if (!is_array($params)) {
  1902. //            if (is_array($fetchmode)) {
  1903. //                if ($params === null) {
  1904. //                    $tmp = DB_FETCHMODE_DEFAULT;
  1905. //                } else {
  1906. //                    $tmp = $params;
  1907. //                }
  1908. //                $params = $fetchmode;
  1909. //                $fetchmode = $tmp;
  1910. //            } elseif ($params !== null) {
  1911. //                $fetchmode = $params;
  1912. //                $params = array();
  1913. //            }
  1914. //        }
  1915. //
  1916. //        if (sizeof($params) > 0) {
  1917. //            $sth = $this->prepare($query);
  1918. //
  1919. //            if (DB::isError($sth)) {
  1920. //                return $sth;
  1921. //            }
  1922. //
  1923. //            $res =& $this->execute($sth, $params);
  1924. //            $this->freePrepared($sth);
  1925. //        } else {
  1926. //            $res =& $this->query($query);
  1927. //        }
  1928. //
  1929. //        if ($res === DB_OK || DB::isError($res)) {
  1930. //            return $res;
  1931. //        }
  1932. //
  1933. //        $results = array();
  1934. //        while (DB_OK === $res->fetchInto($row, $fetchmode)) {
  1935. //            if ($fetchmode & DB_FETCHMODE_FLIPPED) {
  1936. //                foreach ($row as $key => $val) {
  1937. //                    $results[$key][] = $val;
  1938. //                }
  1939. //            } else {
  1940. //                $results[] = $row;
  1941. //            }
  1942. //        }
  1943. //
  1944. //        $res->free();
  1945. //
  1946. //        if (DB::isError($row)) {
  1947. //            $tmp =& $this->raiseError($row);
  1948. //            return $tmp;
  1949. //        }
  1950. //        return $results;
  1951.     }
  1952.  
  1953.     /**
  1954.      * Enables or disables automatic commits
  1955.      *
  1956.      * @param bool $onoff  true turns it on, false turns it off
  1957.      * @return int  DB_OK on success.  A DB_Error object if the driver
  1958.      *                doesn't support auto-committing transactions.
  1959.      *  @todo Implement mock DB_common::autoCommit
  1960.      */
  1961.     public function autoCommit($onoff false)
  1962.     {
  1963. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1964.     }
  1965.  
  1966.     /**
  1967.      * Commits the current transaction
  1968.      *
  1969.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1970.      *  @todo Implement mock DB_common::commit
  1971.      */
  1972.     public function commit()
  1973.     {
  1974. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1975.     }
  1976.  
  1977.     /**
  1978.      * Reverts the current transaction
  1979.      *
  1980.      * @return int  DB_OK on success.  A DB_Error object on failure.
  1981.      *  @todo Implement mock DB_common::rollback
  1982.      */
  1983.     public function rollback()
  1984.     {
  1985. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1986.     }
  1987.  
  1988.     /**
  1989.      * Determines the number of rows in a query result
  1990.      *
  1991.      * @param resource $result  the query result idenifier produced by PHP
  1992.      * @return int  the number of rows.  A DB_Error object on failure.
  1993.      *  @todo Implement mock DB_common::numRows
  1994.      */
  1995.     public function numRows($result)
  1996.     {
  1997. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  1998.     }
  1999.  
  2000.     /**
  2001.      * Determines the number of rows affected by a data maniuplation query
  2002.      *
  2003.      * 0 is returned for queries that don't manipulate data.
  2004.      *
  2005.      * @return int  the number of rows.  A DB_Error object on failure.
  2006.      *  @todo Implement mock DB_common::affectedRows
  2007.      */
  2008.     public function affectedRows()
  2009.     {
  2010. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2011.     }
  2012.  
  2013.     /**
  2014.      * Generates the name used inside the database for a sequence
  2015.      *
  2016.      * @param string $sqn  the sequence's public name
  2017.      * @return string  the sequence's name in the backend
  2018.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  2019.      *       DB_common::nextID(), DB_common::setOption()
  2020.      *  @todo Implement mock DB_common::getSequenceName
  2021.      */
  2022.     protected function getSequenceName($sqn)
  2023.     {
  2024. //        return sprintf($this->getOption('seqname_format'),
  2025. //                       preg_replace('/[^a-z0-9_.]/i', '_', $sqn));
  2026.     }
  2027.  
  2028.     /**
  2029.      * Returns the next free id in a sequence
  2030.      *
  2031.      * @param string  $seq_name  name of the sequence
  2032.      * @param boolean $ondemand  when true, the seqence is automatically
  2033.      *                             created if it does not exist
  2034.      *
  2035.      * @return int  the next id number in the sequence.
  2036.      *                A DB_Error object on failure.
  2037.      *
  2038.      * @see DB_common::createSequence(), DB_common::dropSequence(),
  2039.      *       DB_common::getSequenceName()
  2040.      *  @todo Implement mock DB_common::nextID
  2041.      */
  2042.     public function nextId($seq_name$ondemand true)
  2043.     {
  2044. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2045.     }
  2046.  
  2047.     /**
  2048.      * Creates a new sequence
  2049.      *
  2050.      * @param string $seq_name  name of the new sequence
  2051.      * @return int  DB_OK on success.  A DB_Error object on failure.
  2052.      * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  2053.      *       DB_common::nextID()
  2054.      *  @todo Implement mock DB_common::createSequence
  2055.      */
  2056.     public function createSequence($seq_name)
  2057.     {
  2058. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2059.     }
  2060.  
  2061.     /**
  2062.      * Deletes a sequence
  2063.      *
  2064.      * @param string $seq_name  name of the sequence to be deleted
  2065.      * @return int  DB_OK on success.  A DB_Error object on failure.
  2066.      * @see DB_common::createSequence(), DB_common::getSequenceName(),
  2067.      *       DB_common::nextID()
  2068.      *  @todo Implement mock DB_common::dropSequence
  2069.      */
  2070.     public function dropSequence($seq_name)
  2071.     {
  2072. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2073.     }
  2074.  
  2075.     /**
  2076.      * Communicates an error and invoke error callbacks, etc
  2077.      *
  2078.      * Basically a wrapper for PEAR::raiseError without the message string.
  2079.      *
  2080.      * @param mixed   integer error code, or a PEAR error object (all
  2081.      *                  other parameters are ignored if this parameter is
  2082.      *                  an object
  2083.      * @param int     error mode, see PEAR_Error docs
  2084.      * @param mixed   if error mode is PEAR_ERROR_TRIGGER, this is the
  2085.      *                  error level (E_USER_NOTICE etc).  If error mode is
  2086.      *                  PEAR_ERROR_CALLBACK, this is the callback function,
  2087.      *                  either as a function name, or as an array of an
  2088.      *                  object and method name.  For other error modes this
  2089.      *                  parameter is ignored.
  2090.      * @param string  extra debug information.  Defaults to the last
  2091.      *                  query and native error code.
  2092.      * @param mixed   native error code, integer or string depending the
  2093.      *                  backend
  2094.      *
  2095.      * @return object  the PEAR_Error object
  2096.      * @see PEAR_Error
  2097.      *  @todo Implement mock DB_common::raiseError
  2098.      */
  2099.     public function &raiseError($code DB_ERROR$mode null$options null,
  2100.                          $userinfo null$nativecode null)
  2101.     {
  2102. //        // The error is yet a DB error object
  2103. //        if (is_object($code)) {
  2104. //            // because we the static PEAR::raiseError, our global
  2105. //            // handler should be used if it is set
  2106. //            if ($mode === null && !empty($this->_default_error_mode)) {
  2107. //                $mode    = $this->_default_error_mode;
  2108. //                $options = $this->_default_error_options;
  2109. //            }
  2110. //            $tmp = PEAR::raiseError($code, null, $mode, $options,
  2111. //                                    null, null, true);
  2112. //            return $tmp;
  2113. //        }
  2114. //
  2115. //        if ($userinfo === null) {
  2116. //            $userinfo = $this->last_query;
  2117. //        }
  2118. //
  2119. //        if ($nativecode) {
  2120. //            $userinfo .= ' [nativecode=' . trim($nativecode) . ']';
  2121. //        } else {
  2122. //            $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']';
  2123. //        }
  2124. //
  2125. //        $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo,
  2126. //                                'DB_Error', true);
  2127. //        return $tmp;
  2128.     }
  2129.  
  2130.     /**
  2131.      * Gets the DBMS' native error code produced by the last query
  2132.      *
  2133.      * @return mixed  the DBMS' error code.  A DB_Error object on failure.
  2134.      *  @todo Implement mock DB_common::errorNative
  2135.      */
  2136.     public function errorNative()
  2137.     {
  2138. //        return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2139.     }
  2140.  
  2141.     /**
  2142.      * Maps native error codes to DB's portable ones
  2143.      *
  2144.      * Uses the <var>$errorcode_map</var> property defined in each driver.
  2145.      *
  2146.      * @param string|int$nativecode  the error code returned by the DBMS
  2147.      *
  2148.      * @return int  the portable DB error code.  Return DB_ERROR if the
  2149.      *                current driver doesn't have a mapping for the
  2150.      *                $nativecode submitted.
  2151.      *  @todo Implement mock DB_common::errorCode
  2152.      */
  2153.     public function errorCode($nativecode)
  2154.     {
  2155. //        if (isset($this->errorcode_map[$nativecode])) {
  2156. //            return $this->errorcode_map[$nativecode];
  2157. //        }
  2158.         // Fall back to DB_ERROR if there was no mapping.
  2159.         return DB_ERROR;
  2160.     }
  2161.  
  2162.     /**
  2163.      * Maps a DB error code to a textual message
  2164.      *
  2165.      * @param integer $dbcode  the DB error code
  2166.      * @return string  the error message corresponding to the error code
  2167.      *                   submitted.  FALSE if the error code is unknown.
  2168.      * @see DB::errorMessage()
  2169.      *  @todo Implement mock DB_common::errorMessage
  2170.      */
  2171.     public function errorMessage($dbcode)
  2172.     {
  2173. //        return DB::errorMessage($this->errorcode_map[$dbcode]);
  2174.     }
  2175.  
  2176.     /**
  2177.      * Returns information about a table or a result set
  2178.      *
  2179.      * @param object|string $result  DB_result object from a query or a
  2180.      *                                 string containing the name of a table.
  2181.      *                                 While this also accepts a query result
  2182.      *                                 resource identifier, this behavior is
  2183.      *                                 deprecated.
  2184.      * @param int  $mode   either unused or one of the tableInfo modes:
  2185.      *                      <kbd>DB_TABLEINFO_ORDERTABLE</kbd>,
  2186.      *                      <kbd>DB_TABLEINFO_ORDER</kbd> or
  2187.      *                      <kbd>DB_TABLEINFO_FULL</kbd> (which does both).
  2188.      *                      These are bitwise, so the first two can be
  2189.      *                      combined using <kbd>|</kbd>.
  2190.      *
  2191.      * @return array  an associative array with the information requested.
  2192.      *                  A DB_Error object on failure.
  2193.      *
  2194.      * @see DB_common::setOption()
  2195.      *  @todo Implement mock DB_common::tableInfo
  2196.      */
  2197.     public function tableInfo($result$mode null)
  2198.     {
  2199.         /*
  2200.          * If the DB_<driver> class has a tableInfo() method, that one
  2201.          * overrides this one.  But, if the driver doesn't have one,
  2202.          * this method runs and tells users about that fact.
  2203.          */
  2204.         return $this->raiseError(DB_ERROR_NOT_CAPABLE);
  2205.     }
  2206.  
  2207.     /**
  2208.      * Lists internal database information
  2209.      *
  2210.      * @param string $type  type of information being sought.
  2211.      *                        Common items being sought are:
  2212.      *                        tables, databases, users, views, functions
  2213.      *                        Each DBMS's has its own capabilities.
  2214.      *
  2215.      * @return array  an array listing the items sought.
  2216.      *                  A DB DB_Error object on failure.
  2217.      *  @todo Implement mock DB_common::getListOf
  2218.      */
  2219.     public function getListOf($type)
  2220.     {
  2221. //        $sql = $this->getSpecialQuery($type);
  2222. //        if ($sql === null) {
  2223. //            $this->last_query = '';
  2224. //            return $this->raiseError(DB_ERROR_UNSUPPORTED);
  2225. //        } elseif (is_int($sql) || DB::isError($sql)) {
  2226. //            // Previous error
  2227. //            return $this->raiseError($sql);
  2228. //        } elseif (is_array($sql)) {
  2229. //            // Already the result
  2230. //            return $sql;
  2231. //        }
  2232. //        // Launch this query
  2233. //        return $this->getCol($sql);
  2234.     }
  2235.  
  2236.     /**
  2237.      * Obtains the query string needed for listing a given type of objects
  2238.      *
  2239.      * @param string $type  the kind of objects you want to retrieve
  2240.      * @return string  the SQL query string or null if the driver doesn't
  2241.      *                   support the object type requested
  2242.      * @see DB_common::getListOf()
  2243.      *  @todo Implement mock DB_common::getSpecialQuery
  2244.      */
  2245.     protected function getSpecialQuery($type)
  2246.     {
  2247. //        return $this->raiseError(DB_ERROR_UNSUPPORTED);
  2248.     }
  2249.  
  2250.     /**
  2251.      * Right-trims all strings in an array
  2252.      *
  2253.      * @param array $array  the array to be trimmed (passed by reference)
  2254.      * @return void 
  2255.      */
  2256.     protected function _rtrimArrayValues(&$array)
  2257.     {
  2258.         foreach ($array as $key => $value{
  2259.             if (is_string($value)) {
  2260.                 $array[$keyrtrim($value);
  2261.             }
  2262.         }
  2263.     }
  2264.  
  2265.     /**
  2266.      * Converts all null values in an array to empty strings
  2267.      *
  2268.      * @param array  $array  the array to be de-nullified (passed by reference)
  2269.      * @return void 
  2270.      */
  2271.     protected function _convertNullArrayValuesToEmpty(&$array)
  2272.     {
  2273.         foreach ($array as $key => $value{
  2274.             if (is_null($value)) {
  2275.                 $array[$key'';
  2276.             }
  2277.         }
  2278.     }
  2279. }
  2280.  
  2281. /**
  2282.  *  Mock DB_Error
  2283.  *  @todo Implement mock DB_Error class
  2284.  */
  2285. class DB_Error extends PEAR_Error
  2286. {
  2287.     /**
  2288.      * DB_Error constructor
  2289.      *
  2290.      * @param mixed $code       DB error code, or string with error message
  2291.      * @param int   $mode       what "error mode" to operate in
  2292.      * @param int   $level      what error level to use for $mode &
  2293.      *                            PEAR_ERROR_TRIGGER
  2294.      * @param mixed $debuginfo  additional debug info, such as the last query
  2295.      * @see PEAR_Error
  2296.      *  @todo Implement DB_Error::constructor
  2297.      */
  2298.     function DB_Error($code DB_ERROR$mode PEAR_ERROR_RETURN,
  2299.                       $level E_USER_NOTICE$debuginfo null)
  2300.     {
  2301. //        if (is_int($code)) {
  2302. //            $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code,
  2303. //                              $mode, $level, $debuginfo);
  2304. //        } else {
  2305. //            $this->PEAR_Error("DB Error: $code", DB_ERROR,
  2306. //                              $mode, $level, $debuginfo);
  2307. //        }
  2308.     }
  2309. }
  2310.  
  2311. /**
  2312.  *  Mock DB_result
  2313.  *  @todo Implement mock DB_result
  2314.  */
  2315. class DB_result
  2316. {
  2317.  
  2318.     /**
  2319.      * This constructor sets the object's properties
  2320.      *
  2321.      * @param object   &$dbh     the DB object reference
  2322.      * @param resource $result   the result resource id
  2323.      * @param array    $options  an associative array with result options
  2324.      * @return void 
  2325.      *  @todo Implement mock DB_result::constructor
  2326.      */
  2327.     function DB_result(&$dbh$result$options array())
  2328.     {
  2329.     }
  2330.  
  2331.     /**
  2332.      * Set options for the DB_result object
  2333.      *
  2334.      * @param string $key    the option to set
  2335.      * @param mixed  $value  the value to set the option to
  2336.      * @return void 
  2337.      *  @todo Implement mock DB_result::setOption()
  2338.      */
  2339.     function setOption($key$value null)
  2340.     {
  2341.         switch ($key{
  2342.             case 'limit_from':
  2343. //                $this->limit_from = $value;
  2344.                 break;
  2345.             case 'limit_count':
  2346. //                $this->limit_count = $value;
  2347.         }
  2348.     }
  2349.  
  2350.     /**
  2351.      * Fetch a row of data and return it by reference into an array
  2352.      *
  2353.      * @param int $fetchmode  the constant indicating how to format the data
  2354.      * @param int $rownum     the row number to fetch (index starts at 0)
  2355.      *
  2356.      * @return mixed  an array or object containing the row's data,
  2357.      *                  NULL when the end of the result set is reached
  2358.      *                  or a DB_Error object on failure.
  2359.      *
  2360.      * @see DB_common::setOption(), DB_common::setFetchMode()
  2361.      *  @todo Implement mock DB_result::fetchRow()
  2362.      */
  2363.     function &fetchRow($fetchmode DB_FETCHMODE_DEFAULT$rownum null)
  2364.     {
  2365. //        if ($fetchmode === DB_FETCHMODE_DEFAULT) {
  2366. //            $fetchmode = $this->fetchmode;
  2367. //        }
  2368. //        if ($fetchmode === DB_FETCHMODE_OBJECT) {
  2369. //            $fetchmode = DB_FETCHMODE_ASSOC;
  2370. //            $object_class = $this->fetchmode_object_class;
  2371. //        }
  2372. //        if ($this->limit_from !== null) {
  2373. //            if ($this->row_counter === null) {
  2374. //                $this->row_counter = $this->limit_from;
  2375. //                // Skip rows
  2376. //                if ($this->dbh->features['limit'] === false) {
  2377. //                    $i = 0;
  2378. //                    while ($i++ < $this->limit_from) {
  2379. //                        $this->dbh->fetchInto($this->result, $arr, $fetchmode);
  2380. //                    }
  2381. //                }
  2382. //            }
  2383. //            if ($this->row_counter >= ($this->limit_from + $this->limit_count))
  2384. //            {
  2385. //                if ($this->autofree) {
  2386. //                    $this->free();
  2387. //                }
  2388. //                $tmp = null;
  2389. //                return $tmp;
  2390. //            }
  2391. //            if ($this->dbh->features['limit'] === 'emulate') {
  2392. //                $rownum = $this->row_counter;
  2393. //            }
  2394. //            $this->row_counter++;
  2395. //        }
  2396. //        $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
  2397. //        if ($res === DB_OK) {
  2398. //            if (isset($object_class)) {
  2399. //                // The default mode is specified in the
  2400. //                // DB_common::fetchmode_object_class property
  2401. //                if ($object_class == 'stdClass') {
  2402. //                    $arr = (object) $arr;
  2403. //                } else {
  2404. //                    $arr = &new $object_class($arr);
  2405. //                }
  2406. //            }
  2407. //            return $arr;
  2408. //        }
  2409. //        if ($res == null && $this->autofree) {
  2410. //            $this->free();
  2411. //        }
  2412. //        return $res;
  2413.     }
  2414.  
  2415.     /**
  2416.      * Fetch a row of data into an array which is passed by reference
  2417.      *
  2418.      * @param array &$arr       the variable where the data should be placed
  2419.      * @param int   $fetchmode  the constant indicating how to format the data
  2420.      * @param int   $rownum     the row number to fetch (index starts at 0)
  2421.      * @return mixed  DB_OK if a row is processed, NULL when the end of the
  2422.      *                  result set is reached or a DB_Error object on failure
  2423.      *
  2424.      * @see DB_common::setOption(), DB_common::setFetchMode()
  2425.      *  @todo Implement mock DB_result::fetchInto()
  2426.      */
  2427.     function fetchInto(&$arr$fetchmode DB_FETCHMODE_DEFAULT$rownum null)
  2428.     {
  2429. //        if ($fetchmode === DB_FETCHMODE_DEFAULT) {
  2430. //            $fetchmode = $this->fetchmode;
  2431. //        }
  2432. //        if ($fetchmode === DB_FETCHMODE_OBJECT) {
  2433. //            $fetchmode = DB_FETCHMODE_ASSOC;
  2434. //            $object_class = $this->fetchmode_object_class;
  2435. //        }
  2436. //        if ($this->limit_from !== null) {
  2437. //            if ($this->row_counter === null) {
  2438. //                $this->row_counter = $this->limit_from;
  2439. //                // Skip rows
  2440. //                if ($this->dbh->features['limit'] === false) {
  2441. //                    $i = 0;
  2442. //                    while ($i++ < $this->limit_from) {
  2443. //                        $this->dbh->fetchInto($this->result, $arr, $fetchmode);
  2444. //                    }
  2445. //                }
  2446. //            }
  2447. //            if ($this->row_counter >= (
  2448. //                    $this->limit_from + $this->limit_count))
  2449. //            {
  2450. //                if ($this->autofree) {
  2451. //                    $this->free();
  2452. //                }
  2453. //                return null;
  2454. //            }
  2455. //            if ($this->dbh->features['limit'] === 'emulate') {
  2456. //                $rownum = $this->row_counter;
  2457. //            }
  2458. //
  2459. //            $this->row_counter++;
  2460. //        }
  2461. //        $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
  2462. //        if ($res === DB_OK) {
  2463. //            if (isset($object_class)) {
  2464. //                // default mode specified in the
  2465. //                // DB_common::fetchmode_object_class property
  2466. //                if ($object_class == 'stdClass') {
  2467. //                    $arr = (object) $arr;
  2468. //                } else {
  2469. //                    $arr = new $object_class($arr);
  2470. //                }
  2471. //            }
  2472. //            return DB_OK;
  2473. //        }
  2474. //        if ($res == null && $this->autofree) {
  2475. //            $this->free();
  2476. //        }
  2477. //        return $res;
  2478.     }
  2479.  
  2480.     /**
  2481.      * Get the the number of columns in a result set
  2482.      *
  2483.      * @return int  the number of columns.  A DB_Error object on failure.
  2484.      *  @todo Implement mock DB_result::numCols()
  2485.      */
  2486.     function numCols()
  2487.     {
  2488. //        return $this->dbh->numCols($this->result);
  2489.     }
  2490.  
  2491.     /**
  2492.      * Get the number of rows in a result set
  2493.      *
  2494.      * @return int  the number of rows.  A DB_Error object on failure.
  2495.      *  @todo Implement mock DB_result::numRows()
  2496.      */
  2497.     function numRows()
  2498.     {
  2499. //        if ($this->dbh->features['numrows'] === 'emulate'
  2500. //            && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS)
  2501. //        {
  2502. //            if ($this->dbh->features['prepare']) {
  2503. //                $res = $this->dbh->query($this->query, $this->parameters);
  2504. //            } else {
  2505. //                $res = $this->dbh->query($this->query);
  2506. //            }
  2507. //            if (DB::isError($res)) {
  2508. //                return $res;
  2509. //            }
  2510. //            $i = 0;
  2511. //            while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) {
  2512. //                $i++;
  2513. //            }
  2514. //            return $i;
  2515. //        } else {
  2516. //            return $this->dbh->numRows($this->result);
  2517. //        }
  2518.     }
  2519.  
  2520.     /**
  2521.      * Get the next result if a batch of queries was executed
  2522.      *
  2523.      * @return bool  true if a new result is available or false if not
  2524.      *  @todo Implement mock DB_result::nextResult()
  2525.      */
  2526.     function nextResult()
  2527.     {
  2528. //        return $this->dbh->nextResult($this->result);
  2529.     }
  2530.  
  2531.     /**
  2532.      * Frees the resources allocated for this result set
  2533.      *
  2534.      * @return bool  true on success.  A DB_Error object on failure.
  2535.      *  @todo Implement mock DB_result::free()
  2536.      */
  2537.     function free()
  2538.     {
  2539. //        $err = $this->dbh->freeResult($this->result);
  2540. //        if (DB::isError($err)) {
  2541. //            return $err;
  2542. //        }
  2543. //        $this->result = false;
  2544. //        $this->statement = false;
  2545. //        return true;
  2546.     }
  2547.  
  2548.     /**
  2549.      * Determine the query string that created this result
  2550.      *
  2551.      * @return string  the query string
  2552.      *  @todo Implement mock DB_result::getQuery()
  2553.      */
  2554.     function getQuery()
  2555.     {
  2556. //        return $this->query;
  2557.     }
  2558.  
  2559.     /**
  2560.      * Tells which row number is currently being processed
  2561.      *
  2562.      * @return integer  the current row being looked at.  Starts at 1.
  2563.      *  @todo Implement mock DB_result::getRowCounter()
  2564.      */
  2565.     function getRowCounter()
  2566.     {
  2567. //        return $this->row_counter;
  2568.     }
  2569. }
  2570.  
  2571. /**
  2572.  *  Mock DB_row
  2573.  *  @todo Implement mock DB_row
  2574.  */
  2575. class DB_row
  2576. {
  2577.  
  2578.     /**
  2579.      * The constructor places a row's data into properties of this object
  2580.      *
  2581.      * @param array  the array containing the row's data
  2582.      * @return void 
  2583.      *  @todo Implement mock DB_row constructor
  2584.      */
  2585.     function DB_row(&$arr)
  2586.     {
  2587. //        foreach ($arr as $key => $value) {
  2588. //            $this->$key = &$arr[$key];
  2589. //      }
  2590.     }
  2591. }
  2592.  
  2593. /**
  2594.  *  Mock DB_mysql class
  2595.  */
  2596. class DB_mysql extends DB_common
  2597. {
  2598.  
  2599.     /**
  2600.      * This constructor calls <kbd>$this->DB_common()</kbd>
  2601.      *
  2602.      * @return void 
  2603.      */
  2604.     function DB_mysql()
  2605.     {
  2606.         $this->DB_common();
  2607.     }
  2608.  
  2609.     /**
  2610.      * Connect to the database server, log in and open the database
  2611.      *
  2612.      * @param array $dsn         the data source name
  2613.      * @param bool  $persistent  should the connection be persistent?
  2614.      * @return int  DB_OK on success. A DB_Error object on failure.
  2615.      *  @todo Implement mock DB_mysql::connect()
  2616.      */
  2617.     function connect($dsn$persistent false)
  2618.     {
  2619. //        if (!PEAR::loadExtension('mysql')) {
  2620. //            return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  2621. //        }
  2622. //
  2623. //        $this->dsn = $dsn;
  2624. //        if ($dsn['dbsyntax']) {
  2625. //            $this->dbsyntax = $dsn['dbsyntax'];
  2626. //        }
  2627. //
  2628. //        $params = array();
  2629. //        if ($dsn['protocol'] && $dsn['protocol'] == 'unix') {
  2630. //            $params[0] = ':' . $dsn['socket'];
  2631. //        } else {
  2632. //            $params[0] = $dsn['hostspec'] ? $dsn['hostspec']
  2633. //                         : 'localhost';
  2634. //            if ($dsn['port']) {
  2635. //                $params[0] .= ':' . $dsn['port'];
  2636. //            }
  2637. //        }
  2638. //        $params[] = $dsn['username'] ? $dsn['username'] : null;
  2639. //        $params[] = $dsn['password'] ? $dsn['password'] : null;
  2640. //
  2641. //        if (!$persistent) {
  2642. //            if (isset($dsn['new_link'])
  2643. //                && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true))
  2644. //            {
  2645. //                $params[] = true;
  2646. //            } else {
  2647. //                $params[] = false;
  2648. //            }
  2649. //        }
  2650. //        if (version_compare(phpversion(), '4.3.0', '>=')) {
  2651. //            $params[] = isset($dsn['client_flags'])
  2652. //                        ? $dsn['client_flags'] : null;
  2653. //        }
  2654. //
  2655. //        $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
  2656. //
  2657. //        $ini = ini_get('track_errors');
  2658. //        $php_errormsg = '';
  2659. //        if ($ini) {
  2660. //            $this->connection = @call_user_func_array($connect_function,
  2661. //                                                      $params);
  2662. //        } else {
  2663. //            ini_set('track_errors', 1);
  2664. //            $this->connection = @call_user_func_array($connect_function,
  2665. //                                                      $params);
  2666. //            ini_set('track_errors', $ini);
  2667. //        }
  2668. //
  2669. //        if (!$this->connection) {
  2670. //            if (($err = @mysql_error()) != '') {
  2671. //                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  2672. //                                         null, null, null, 
  2673. //                                         $err);
  2674. //            } else {
  2675. //                return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  2676. //                                         null, null, null,
  2677. //                                         $php_errormsg);
  2678. //            }
  2679. //        }
  2680. //
  2681. //        if ($dsn['database']) {
  2682. //            if (!@mysql_select_db($dsn['database'], $this->connection)) {
  2683. //                return $this->mysqlRaiseError();
  2684. //            }
  2685. //            $this->_db = $dsn['database'];
  2686. //        }
  2687. //
  2688. //        return DB_OK;
  2689.     }
  2690.  
  2691.     /**
  2692.      * Disconnects from the database server
  2693.      *
  2694.      * @return bool  TRUE on success, FALSE on failure
  2695.      *  @todo Implement mock DB_mysql::disconnect()
  2696.      */
  2697.     function disconnect()
  2698.     {
  2699. //        $ret = @mysql_close($this->connection);
  2700. //        $this->connection = null;
  2701. //        return $ret;
  2702.     }
  2703.  
  2704.     /**
  2705.      * Sends a query to the database server
  2706.      *
  2707.      * Generally uses mysql_query().  If you want to use
  2708.      * mysql_unbuffered_query() set the "result_buffering" option to 0 using
  2709.      * setOptions().  This option was added in Release 1.7.0.
  2710.      *
  2711.      * @param string  the SQL query string
  2712.      *
  2713.      * @return mixed  + a PHP result resrouce for successful SELECT queries
  2714.      *                 + the DB_OK constant for other successful queries
  2715.      *                 + a DB_Error object on failure
  2716.      *  @todo Implement mock DB_mysql::simpleQuery()
  2717.      */
  2718.     function simpleQuery($query)
  2719.     {
  2720. //        $ismanip = DB::isManip($query);
  2721. //        $this->last_query = $query;
  2722. //        $query = $this->modifyQuery($query);
  2723. //        if ($this->_db) {
  2724. //            if (!@mysql_select_db($this->_db, $this->connection)) {
  2725. //                return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  2726. //            }
  2727. //        }
  2728. //        if (!$this->autocommit && $ismanip) {
  2729. //            if ($this->transaction_opcount == 0) {
  2730. //                $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
  2731. //                $result = @mysql_query('BEGIN', $this->connection);
  2732. //                if (!$result) {
  2733. //                    return $this->mysqlRaiseError();
  2734. //                }
  2735. //            }
  2736. //            $this->transaction_opcount++;
  2737. //        }
  2738. //        if (!$this->options['result_buffering']) {
  2739. //            $result = @mysql_unbuffered_query($query, $this->connection);
  2740. //        } else {
  2741. //            $result = @mysql_query($query, $this->connection);
  2742. //        }
  2743. //        if (!$result) {
  2744. //            return $this->mysqlRaiseError();
  2745. //        }
  2746. //        if (is_resource($result)) {
  2747. //            return $result;
  2748. //        }
  2749.         return DB_OK;
  2750.     }
  2751.  
  2752.     /**
  2753.      * Move the internal mysql result pointer to the next available result
  2754.      *
  2755.      * This method has not been implemented yet.
  2756.      *
  2757.      * @param valid sql result resource
  2758.      *
  2759.      * @return false 
  2760.      */
  2761.     function nextResult($result)
  2762.     {
  2763.         return false;
  2764.     }
  2765.  
  2766.     /**
  2767.      * Places a row from the result set into the given array
  2768.      *
  2769.      * @param resource $result    the query result resource
  2770.      * @param array    $arr       the referenced array to put the data in
  2771.      * @param int      $fetchmode how the resulting array should be indexed
  2772.      * @param int      $rownum    the row number to fetch (0 = first row)
  2773.      * @return mixed  DB_OK on success, NULL when the end of a result set is
  2774.      *                  reached or on failure
  2775.      *
  2776.      * @see DB_result::fetchInto()
  2777.      *  @todo Implement mock DB_mysql::fetchInto()
  2778.      */
  2779.     function fetchInto($result&$arr$fetchmode$rownum null)
  2780.     {
  2781. //        if ($rownum !== null) {
  2782. //            if (!@mysql_data_seek($result, $rownum)) {
  2783. //                return null;
  2784. //            }
  2785. //        }
  2786. //        if ($fetchmode & DB_FETCHMODE_ASSOC) {
  2787. //            $arr = @mysql_fetch_array($result, MYSQL_ASSOC);
  2788. //            if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
  2789. //                $arr = array_change_key_case($arr, CASE_LOWER);
  2790. //            }
  2791. //        } else {
  2792. //            $arr = @mysql_fetch_row($result);
  2793. //        }
  2794. //        if (!$arr) {
  2795. //            return null;
  2796. //        }
  2797. //        if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
  2798. //            /*
  2799. //             * Even though this DBMS already trims output, we do this because
  2800. //             * a field might have intentional whitespace at the end that
  2801. //             * gets removed by DB_PORTABILITY_RTRIM under another driver.
  2802. //             */
  2803. //            $this->_rtrimArrayValues($arr);
  2804. //        }
  2805. //        if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
  2806. //            $this->_convertNullArrayValuesToEmpty($arr);
  2807. //        }
  2808.         return DB_OK;
  2809.     }
  2810.  
  2811.     /**
  2812.      * Deletes the result set and frees the memory occupied by the result set
  2813.      *
  2814.      * This method is not meant to be called directly.  Use
  2815.      * DB_result::free() instead.  It can't be declared "protected"
  2816.      * because DB_result is a separate object.
  2817.      *
  2818.      * @param resource $result  PHP's query result resource
  2819.      *
  2820.      * @return bool  TRUE on success, FALSE if $result is invalid
  2821.      *
  2822.      * @see DB_result::free()
  2823.      *  @todo Implement mock DB_mysql::freeResult()
  2824.      */
  2825.     function freeResult($result)
  2826.     {
  2827. //        return @mysql_free_result($result);
  2828.     }
  2829.  
  2830.  
  2831.     /**
  2832.      * Gets the number of columns in a result set
  2833.      *
  2834.      * This method is not meant to be called directly.  Use
  2835.      * DB_result::numCols() instead.  It can't be declared "protected"
  2836.      * because DB_result is a separate object.
  2837.      *
  2838.      * @param resource $result  PHP's query result resource
  2839.      *
  2840.      * @return int  the number of columns.  A DB_Error object on failure.
  2841.      *
  2842.      * @see DB_result::numCols()
  2843.      *  @todo Implement mock DB_mysql::numCols()
  2844.      */
  2845.     function numCols($result)
  2846.     {
  2847. //        $cols = @mysql_num_fields($result);
  2848. //        if (!$cols) {
  2849. //            return $this->mysqlRaiseError();
  2850. //        }
  2851. //        return $cols;
  2852.     }
  2853.  
  2854.     /**
  2855.      * Gets the number of rows in a result set
  2856.      *
  2857.      * This method is not meant to be called directly.  Use
  2858.      * DB_result::numRows() instead.  It can't be declared "protected"
  2859.      * because DB_result is a separate object.
  2860.      *
  2861.      * @param resource $result  PHP's query result resource
  2862.      *
  2863.      * @return int  the number of rows.  A DB_Error object on failure.
  2864.      *
  2865.      * @see DB_result::numRows()
  2866.      *  @todo Implement mock DB_mysql::numRows()
  2867.      */
  2868.     function numRows($result)
  2869.     {
  2870. //        $rows = @mysql_num_rows($result);
  2871. //        if ($rows === null) {
  2872. //            return $this->mysqlRaiseError();
  2873. //        }
  2874. //        return $rows;
  2875.     }
  2876.  
  2877.     /**
  2878.      * Enables or disables automatic commits
  2879.      *
  2880.      * @param bool $onoff  true turns it on, false turns it off
  2881.      *
  2882.      * @return int  DB_OK on success.  A DB_Error object if the driver
  2883.      *                doesn't support auto-committing transactions.
  2884.      *  @todo Implement mock DB_mysql::autoCommit()
  2885.      */
  2886.     function autoCommit($onoff false)
  2887.     {
  2888. //        // XXX if $this->transaction_opcount > 0, we should probably
  2889. //        // issue a warning here.
  2890. //        $this->autocommit = $onoff ? true : false;
  2891.         return DB_OK;
  2892.     }
  2893.  
  2894.     /**
  2895.      * Commits the current transaction
  2896.      *
  2897.      * @return int  DB_OK on success.  A DB_Error object on failure.
  2898.      *  @todo Implement mock DB_mysql::committ()
  2899.      */
  2900.     function commit()
  2901.     {
  2902. //        if ($this->transaction_opcount > 0) {
  2903. //            if ($this->_db) {
  2904. //                if (!@mysql_select_db($this->_db, $this->connection)) {
  2905. //                    return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  2906. //                }
  2907. //            }
  2908. //            $result = @mysql_query('COMMIT', $this->connection);
  2909. //            $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
  2910. //            $this->transaction_opcount = 0;
  2911. //            if (!$result) {
  2912. //                return $this->mysqlRaiseError();
  2913. //            }
  2914. //        }
  2915.         return DB_OK;
  2916.     }
  2917.  
  2918.     /**
  2919.      * Reverts the current transaction
  2920.      *
  2921.      * @return int  DB_OK on success.  A DB_Error object on failure.
  2922.      *  @todo Implement mock DB_mysql::rollback()
  2923.      */
  2924.     function rollback()
  2925.     {
  2926. //        if ($this->transaction_opcount > 0) {
  2927. //            if ($this->_db) {
  2928. //                if (!@mysql_select_db($this->_db, $this->connection)) {
  2929. //                    return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
  2930. //                }
  2931. //            }
  2932. //            $result = @mysql_query('ROLLBACK', $this->connection);
  2933. //            $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
  2934. //            $this->transaction_opcount = 0;
  2935. //            if (!$result) {
  2936. //                return $this->mysqlRaiseError();
  2937. //            }
  2938. //        }
  2939.         return DB_OK;
  2940.     }
  2941.  
  2942.     /**
  2943.      * Determines the number of rows affected by a data maniuplation query
  2944.      *
  2945.      * 0 is returned for queries that don't manipulate data.
  2946.      *
  2947.      * @return int  the number of rows.  A DB_Error object on failure.
  2948.      *  @todo Implement mock DB_mysql::affectedRows()
  2949.      */
  2950.     function affectedRows()
  2951.     {
  2952. //        if (DB::isManip($this->last_query)) {
  2953. //            return @mysql_affected_rows($this->connection);
  2954. //        } else {
  2955. //            return 0;
  2956. //        }
  2957.      }
  2958.  
  2959.     /**
  2960.      * Returns the next free id in a sequence
  2961.      *
  2962.      * @param string  $seq_name  name of the sequence
  2963.      * @param boolean $ondemand  when true, the seqence is automatically
  2964.      *                             created if it does not exist
  2965.      *
  2966.      * @return int  the next id number in the sequence.
  2967.      *                A DB_Error object on failure.
  2968.      *
  2969.      * @see DB_common::nextID(), DB_common::getSequenceName(),
  2970.      *       DB_mysql::createSequence(), DB_mysql::dropSequence()
  2971.      *  @todo Implement mock DB_mysql::nextId()
  2972.      */
  2973.     function nextId($seq_name$ondemand true)
  2974.     {
  2975. //        $seqname = $this->getSequenceName($seq_name);
  2976. //        do {
  2977. //            $repeat = 0;
  2978. //            $this->pushErrorHandling(PEAR_ERROR_RETURN);
  2979. //            $result = $this->query("UPDATE ${seqname} ".
  2980. //                                   'SET id=LAST_INSERT_ID(id+1)');
  2981. //            $this->popErrorHandling();
  2982. //            if ($result === DB_OK) {
  2983. //                // COMMON CASE
  2984. //                $id = @mysql_insert_id($this->connection);
  2985. //                if ($id != 0) {
  2986. //                    return $id;
  2987. //                }
  2988. //                // EMPTY SEQ TABLE
  2989. //                // Sequence table must be empty for some reason, so fill
  2990. //                // it and return 1 and obtain a user-level lock
  2991. //                $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
  2992. //                if (DB::isError($result)) {
  2993. //                    return $this->raiseError($result);
  2994. //                }
  2995. //                if ($result == 0) {
  2996. //                    // Failed to get the lock
  2997. //                    return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
  2998. //                }
  2999. //
  3000. //                // add the default value
  3001. //                $result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)");
  3002. //                if (DB::isError($result)) {
  3003. //                    return $this->raiseError($result);
  3004. //                }
  3005. //
  3006. //                // Release the lock
  3007. //                $result = $this->getOne('SELECT RELEASE_LOCK('
  3008. //                                        . "'${seqname}_lock')");
  3009. //                if (DB::isError($result)) {
  3010. //                    return $this->raiseError($result);
  3011. //                }
  3012. //                // We know what the result will be, so no need to try again
  3013. //                return 1;
  3014. //
  3015. //            } elseif ($ondemand && DB::isError($result) &&
  3016. //                $result->getCode() == DB_ERROR_NOSUCHTABLE)
  3017. //            {
  3018. //                // ONDEMAND TABLE CREATION
  3019. //                $result = $this->createSequence($seq_name);
  3020. //                if (DB::isError($result)) {
  3021. //                    return $this->raiseError($result);
  3022. //                } else {
  3023. //                    $repeat = 1;
  3024. //                }
  3025. //
  3026. //            } elseif (DB::isError($result) &&
  3027. //                      $result->getCode() == DB_ERROR_ALREADY_EXISTS)
  3028. //            {
  3029. //                // BACKWARDS COMPAT
  3030. //                // see _BCsequence() comment
  3031. //                $result = $this->_BCsequence($seqname);
  3032. //                if (DB::isError($result)) {
  3033. //                    return $this->raiseError($result);
  3034. //                }
  3035. //                $repeat = 1;
  3036. //            }
  3037. //        } while ($repeat);
  3038. //
  3039. //        return $this->raiseError($result);
  3040.     }
  3041.  
  3042.     /**
  3043.      * Creates a new sequence
  3044.      *
  3045.      * @param string $seq_name  name of the new sequence
  3046.      *
  3047.      * @return int  DB_OK on success.  A DB_Error object on failure.
  3048.      *
  3049.      * @see DB_common::createSequence(), DB_common::getSequenceName(),
  3050.      *       DB_mysql::nextID(), DB_mysql::dropSequence()
  3051.      *  @todo Implement mock DB_mysql::createSequence()
  3052.      */
  3053.     function createSequence($seq_name)
  3054.     {
  3055. //        $seqname = $this->getSequenceName($seq_name);
  3056. //        $res = $this->query('CREATE TABLE ' . $seqname
  3057. //                            . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'
  3058. //                            . ' PRIMARY KEY(id))');
  3059. //        if (DB::isError($res)) {
  3060. //            return $res;
  3061. //        }
  3062. //        // insert yields value 1, nextId call will generate ID 2
  3063. //        $res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)");
  3064. //        if (DB::isError($res)) {
  3065. //            return $res;
  3066. //        }
  3067. //        // so reset to zero
  3068. //        return $this->query("UPDATE ${seqname} SET id = 0");
  3069.     }
  3070.  
  3071.     /**
  3072.      * Deletes a sequence
  3073.      *
  3074.      * @param string $seq_name  name of the sequence to be deleted
  3075.      *
  3076.      * @return int  DB_OK on success.  A DB_Error object on failure.
  3077.      *
  3078.      * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  3079.      *       DB_mysql::nextID(), DB_mysql::createSequence()
  3080.      *  @todo Implement mock DB_mysql::dropSequence()
  3081.      */
  3082.     function dropSequence($seq_name)
  3083.     {
  3084. //        return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
  3085.     }
  3086.  
  3087.     /**
  3088.      * Backwards compatibility with old sequence emulation implementation
  3089.      * (clean up the dupes)
  3090.      *
  3091.      * @param string $seqname  the sequence name to clean up
  3092.      *
  3093.      * @return bool  true on success.  A DB_Error object on failure.
  3094.      *  @todo Implement mock DB_mysql::_BCsequence()
  3095.      */
  3096.     private function _BCsequence($seqname)
  3097.     {
  3098. //        // Obtain a user-level lock... this will release any previous
  3099. //        // application locks, but unlike LOCK TABLES, it does not abort
  3100. //        // the current transaction and is much less frequently used.
  3101. //        $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
  3102. //        if (DB::isError($result)) {
  3103. //            return $result;
  3104. //        }
  3105. //        if ($result == 0) {
  3106. //            // Failed to get the lock, can't do the conversion, bail
  3107. //            // with a DB_ERROR_NOT_LOCKED error
  3108. //            return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
  3109. //        }
  3110. //
  3111. //        $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
  3112. //        if (DB::isError($highest_id)) {
  3113. //            return $highest_id;
  3114. //        }
  3115. //        // This should kill all rows except the highest
  3116. //        // We should probably do something if $highest_id isn't
  3117. //        // numeric, but I'm at a loss as how to handle that...
  3118. //        $result = $this->query('DELETE FROM ' . $seqname
  3119. //                               . " WHERE id <> $highest_id");
  3120. //        if (DB::isError($result)) {
  3121. //            return $result;
  3122. //        }
  3123. //
  3124. //        // If another thread has been waiting for this lock,
  3125. //        // it will go thru the above procedure, but will have no
  3126. //        // real effect
  3127. //        $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
  3128. //        if (DB::isError($result)) {
  3129. //            return $result;
  3130. //        }
  3131.         return true;
  3132.     }
  3133.  
  3134.     /**
  3135.      * Quotes a string so it can be safely used as a table or column name
  3136.      *
  3137.      * MySQL can't handle the backtick character (<kbd>`</kbd>) in
  3138.      * table or column names.
  3139.      *
  3140.      * @param string $str  identifier name to be quoted
  3141.      * @return string  quoted identifier string
  3142.      * @see DB_common::quoteIdentifier()
  3143.      * @access private
  3144.      */
  3145.     function quoteIdentifier($str)
  3146.     {
  3147.         return '`' $str '`';
  3148.     }
  3149.  
  3150.     /**
  3151.      * Escapes a string according to the current DBMS's standards
  3152.      *
  3153.      * @param string $str  the string to be escaped
  3154.      * @return string  the escaped string
  3155.      * @see DB_common::quoteSmart()
  3156.      *  @todo Implement mock DB_mysql::escapeSimple()
  3157.      */
  3158.     function escapeSimple($str)
  3159.     {
  3160. //        if (function_exists('mysql_real_escape_string')) {
  3161. //            return @mysql_real_escape_string($str, $this->connection);
  3162. //        } else {
  3163. //            return @mysql_escape_string($str);
  3164. //        }
  3165.     }
  3166.  
  3167.     /**
  3168.      * Changes a query string for various DBMS specific reasons
  3169.      *
  3170.      * This little hack lets you know how many rows were deleted
  3171.      * when running a "DELETE FROM table" query.  Only implemented
  3172.      * if the DB_PORTABILITY_DELETE_COUNT portability option is on.
  3173.      *
  3174.      * @param string $query  the query string to modify
  3175.      * @return string  the modified query string
  3176.      * @see DB_common::setOption()
  3177.      *  @todo Implement mock DB_mysql::modifyQuery()
  3178.      */
  3179.     protected function modifyQuery($query)
  3180.     {
  3181. //        if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
  3182. //            // "DELETE FROM table" gives 0 affected rows in MySQL.
  3183. //            // This little hack lets you know how many rows were deleted.
  3184. //            if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
  3185. //                $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
  3186. //                                      'DELETE FROM \1 WHERE 1=1', $query);
  3187. //            }
  3188. //        }
  3189. //        return $query;
  3190.     }
  3191.  
  3192.     /**
  3193.      * Adds LIMIT clauses to a query string according to current DBMS standards
  3194.      *
  3195.      * @param string $query   the query to modify
  3196.      * @param int    $from    the row to start to fetching (0 = the first row)
  3197.      * @param int    $count   the numbers of rows to fetch
  3198.      * @param mixed  $params  array, string or numeric data to be used in
  3199.      *                          execution of the statement.  Quantity of items
  3200.      *                          passed must match quantity of placeholders in
  3201.      *                          query:  meaning 1 placeholder for non-array
  3202.      *                          parameters or 1 placeholder per array element.
  3203.      * @return string  the query string with LIMIT clauses added
  3204.      *  @todo Implement mock DB_mysql::modifyLimitQuery()
  3205.      */
  3206.     protected function modifyLimitQuery($query$from$count$params array())
  3207.     {
  3208. //        if (DB::isManip($query)) {
  3209. //            return $query . " LIMIT $count";
  3210. //        } else {
  3211. //            return $query . " LIMIT $from, $count";
  3212. //        }
  3213.     }
  3214.  
  3215.     /**
  3216.      * Produces a DB_Error object regarding the current problem
  3217.      *
  3218.      * @param int $errno  if the error is being manually raised pass a
  3219.      *                      DB_ERROR* constant here.  If this isn't passed
  3220.      *                      the error information gathered from the DBMS.
  3221.      *
  3222.      * @return object  the DB_Error object
  3223.      * @see DB_common::raiseError(),
  3224.      *       DB_mysql::errorNative(), DB_common::errorCode()
  3225.      *  @todo Implement mock DB_mysql::mysqlRaiseError()
  3226.      */
  3227.     function mysqlRaiseError($errno null)
  3228.     {
  3229. //        if ($errno === null) {
  3230. //            if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
  3231. //                $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT;
  3232. //                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL;
  3233. //                $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT;
  3234. //            } else {
  3235. //                // Doing this in case mode changes during runtime.
  3236. //                $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS;
  3237. //                $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT;
  3238. //                $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS;
  3239. //            }
  3240. //            $errno = $this->errorCode(mysql_errno($this->connection));
  3241. //        }
  3242. //        return $this->raiseError($errno, null, null, null,
  3243. //                                 @mysql_errno($this->connection) . ' ** ' .
  3244. //                                 @mysql_error($this->connection));
  3245.     }
  3246.  
  3247.     /**
  3248.      * Gets the DBMS' native error code produced by the last query
  3249.      *
  3250.      * @return int  the DBMS' error code
  3251.      *  @todo Implement mock DB_mysql::errorNative()
  3252.      */
  3253.     function errorNative()
  3254.     {
  3255. //        return @mysql_errno($this->connection);
  3256.     }
  3257.  
  3258.     /**
  3259.      * Returns information about a table or a result set
  3260.      *
  3261.      * @param object|string $result  DB_result object from a query or a
  3262.      *                                  string containing the name of a table.
  3263.      *                                  While this also accepts a query result
  3264.      *                                  resource identifier, this behavior is
  3265.      *                                  deprecated.
  3266.      * @param int            $mode    a valid tableInfo mode
  3267.      *
  3268.      * @return array  an associative array with the information requested.
  3269.      *                  A DB_Error object on failure.
  3270.      *
  3271.      * @see DB_common::tableInfo()
  3272.      *  @todo Implement mock DB_mysql::tableInfo()
  3273.      */
  3274.     function tableInfo($result$mode null)
  3275.     {
  3276.         // We only support the default mode
  3277.         PHPUnit2_Framework_Assert::assertNull($mode);
  3278.  
  3279.         // We only support table name as first argument
  3280.         PHPUnit2_Framework_Assert::assertTrue(is_string($result));
  3281.  
  3282.         // Look up table name in the mock database
  3283.         foreach(self::$database as $table => $value{
  3284.             if ($result == $table{
  3285.                 return $value['info'];
  3286.             }
  3287.         }
  3288.         PHPUnit2_Framework_Assert::fail("DB_mysql::tableInfo called"
  3289.                                         ." with unknown table $result");
  3290.     }
  3291.  
  3292.     /**
  3293.      * Obtains the query string needed for listing a given type of objects
  3294.      *
  3295.      * @param string $type  the kind of objects you want to retrieve
  3296.      *
  3297.      * @return string  the SQL query string or null if the driver doesn't
  3298.      *                   support the object type requested
  3299.      *
  3300.      * @see DB_common::getListOf()
  3301.      */
  3302.     protected function getSpecialQuery($type)
  3303.     {
  3304.         switch ($type{
  3305.             case 'tables':
  3306.                 return 'SHOW TABLES';
  3307.             case 'users':
  3308.                 return 'SELECT DISTINCT User FROM mysql.user';
  3309.             case 'databases':
  3310.                 return 'SHOW DATABASES';
  3311.             default:
  3312.                 return null;
  3313.         }
  3314.     }
  3315. }
  3316.  
  3317. // -- set Emacs parameters --
  3318. // Local variables:
  3319. // tab-width: 4
  3320. // c-basic-offset: 4
  3321. // c-hanging-comment-ender-p: nil
  3322. // indent-tabs-mode: nil
  3323. // End:
  3324. ?>

Documentation generated on Mon, 21 May 2007 22:28:26 -0600 by phpDocumentor 1.3.2