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 a 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 a 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($dsn, 0, $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($dsn, 0, $at);
  573. $dsn = substr($dsn, $at + 1);
  574. if (($pos = strpos($str, ':')) !== false) {
  575. $parsed['username'] = rawurldecode(substr($str, 0, $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[2] : false;
  588. $dsn = $match[3];
  589.  
  590. } else {
  591. // $dsn => protocol+hostspec/database (old format)
  592. if (strpos($dsn, '+') !== false) {
  593. list($proto, $dsn) = explode('+', $dsn, 2);
  594. }
  595. if (strpos($dsn, '/') !== false) {
  596. list($proto_opts, $dsn) = explode('/', $dsn, 2);
  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($dsn, 0, $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, $value) = explode('=', $opt);
  634. if (!isset($parsed[$key])) {
  635. // don't allow params overwrite
  636. $parsed[$key] = rawurldecode($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 received. expected $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($params) > 0) {
  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. ."$query, exceeding 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[$key] = rtrim($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 a 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 Thu, 04 May 2006 19:47:30 -0600 by phpDocumentor 1.3.0RC4