PageRenderTime 75ms CodeModel.GetById 27ms RepoModel.GetById 2ms app.codeStats 1ms

/common/libraries/plugin/pear/MDB2.php

https://bitbucket.org/renaatdemuynck/chamilo
PHP | 4734 lines | 2095 code | 530 blank | 2109 comment | 293 complexity | 1ee6e7244bd4a5801ab352545f868f0f MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP versions 4 and 5 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
  7. // | Stig. S. Bakken, Lukas Smith |
  8. // | All rights reserved. |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
  11. // | API as well as database abstraction for PHP applications. |
  12. // | This LICENSE is in the BSD license style. |
  13. // | |
  14. // | Redistribution and use in source and binary forms, with or without |
  15. // | modification, are permitted provided that the following conditions |
  16. // | are met: |
  17. // | |
  18. // | Redistributions of source code must retain the above copyright |
  19. // | notice, this list of conditions and the following disclaimer. |
  20. // | |
  21. // | Redistributions in binary form must reproduce the above copyright |
  22. // | notice, this list of conditions and the following disclaimer in the |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // | |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission. |
  29. // | |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
  41. // | POSSIBILITY OF SUCH DAMAGE. |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Lukas Smith <smith@pooteeweet.org> |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id: MDB2.php 137 2009-11-09 13:24:37Z vanpouckesven $
  47. //
  48. /**
  49. * @package MDB2
  50. * @category Database
  51. * @author Lukas Smith <smith@pooteeweet.org>
  52. */
  53. require_once 'PEAR.php';
  54. // {{{ Error constants
  55. /**
  56. * The method mapErrorCode in each MDB2_dbtype implementation maps
  57. * native error codes to one of these.
  58. *
  59. * If you add an error code here, make sure you also add a textual
  60. * version of it in MDB2::errorMessage().
  61. */
  62. define('MDB2_OK', true);
  63. define('MDB2_ERROR', - 1);
  64. define('MDB2_ERROR_SYNTAX', - 2);
  65. define('MDB2_ERROR_CONSTRAINT', - 3);
  66. define('MDB2_ERROR_NOT_FOUND', - 4);
  67. define('MDB2_ERROR_ALREADY_EXISTS', - 5);
  68. define('MDB2_ERROR_UNSUPPORTED', - 6);
  69. define('MDB2_ERROR_MISMATCH', - 7);
  70. define('MDB2_ERROR_INVALID', - 8);
  71. define('MDB2_ERROR_NOT_CAPABLE', - 9);
  72. define('MDB2_ERROR_TRUNCATED', - 10);
  73. define('MDB2_ERROR_INVALID_NUMBER', - 11);
  74. define('MDB2_ERROR_INVALID_DATE', - 12);
  75. define('MDB2_ERROR_DIVZERO', - 13);
  76. define('MDB2_ERROR_NODBSELECTED', - 14);
  77. define('MDB2_ERROR_CANNOT_CREATE', - 15);
  78. define('MDB2_ERROR_CANNOT_DELETE', - 16);
  79. define('MDB2_ERROR_CANNOT_DROP', - 17);
  80. define('MDB2_ERROR_NOSUCHTABLE', - 18);
  81. define('MDB2_ERROR_NOSUCHFIELD', - 19);
  82. define('MDB2_ERROR_NEED_MORE_DATA', - 20);
  83. define('MDB2_ERROR_NOT_LOCKED', - 21);
  84. define('MDB2_ERROR_VALUE_COUNT_ON_ROW', - 22);
  85. define('MDB2_ERROR_INVALID_DSN', - 23);
  86. define('MDB2_ERROR_CONNECT_FAILED', - 24);
  87. define('MDB2_ERROR_EXTENSION_NOT_FOUND', - 25);
  88. define('MDB2_ERROR_NOSUCHDB', - 26);
  89. define('MDB2_ERROR_ACCESS_VIOLATION', - 27);
  90. define('MDB2_ERROR_CANNOT_REPLACE', - 28);
  91. define('MDB2_ERROR_CONSTRAINT_NOT_NULL', - 29);
  92. define('MDB2_ERROR_DEADLOCK', - 30);
  93. define('MDB2_ERROR_CANNOT_ALTER', - 31);
  94. define('MDB2_ERROR_MANAGER', - 32);
  95. define('MDB2_ERROR_MANAGER_PARSE', - 33);
  96. define('MDB2_ERROR_LOADMODULE', - 34);
  97. define('MDB2_ERROR_INSUFFICIENT_DATA', - 35);
  98. define('MDB2_ERROR_NO_PERMISSION', - 36);
  99. define('MDB2_ERROR_DISCONNECT_FAILED', - 37);
  100. // }}}
  101. // {{{ Verbose constants
  102. /**
  103. * These are just helper constants to more verbosely express parameters to prepare()
  104. */
  105. define('MDB2_PREPARE_MANIP', false);
  106. define('MDB2_PREPARE_RESULT', null);
  107. // }}}
  108. // {{{ Fetchmode constants
  109. /**
  110. * This is a special constant that tells MDB2 the user hasn't specified
  111. * any particular get mode, so the default should be used.
  112. */
  113. define('MDB2_FETCHMODE_DEFAULT', 0);
  114. /**
  115. * Column data indexed by numbers, ordered from 0 and up
  116. */
  117. define('MDB2_FETCHMODE_ORDERED', 1);
  118. /**
  119. * Column data indexed by column names
  120. */
  121. define('MDB2_FETCHMODE_ASSOC', 2);
  122. /**
  123. * Column data as object properties
  124. */
  125. define('MDB2_FETCHMODE_OBJECT', 3);
  126. /**
  127. * For multi-dimensional results: normally the first level of arrays
  128. * is the row number, and the second level indexed by column number or name.
  129. * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
  130. * is the column name, and the second level the row number.
  131. */
  132. define('MDB2_FETCHMODE_FLIPPED', 4);
  133. // }}}
  134. // {{{ Portability mode constants
  135. /**
  136. * Portability: turn off all portability features.
  137. * @see MDB2_Driver_Common::setOption()
  138. */
  139. define('MDB2_PORTABILITY_NONE', 0);
  140. /**
  141. * Portability: convert names of tables and fields to case defined in the
  142. * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
  143. * @see MDB2_Driver_Common::setOption()
  144. */
  145. define('MDB2_PORTABILITY_FIX_CASE', 1);
  146. /**
  147. * Portability: right trim the data output by query*() and fetch*().
  148. * @see MDB2_Driver_Common::setOption()
  149. */
  150. define('MDB2_PORTABILITY_RTRIM', 2);
  151. /**
  152. * Portability: force reporting the number of rows deleted.
  153. * @see MDB2_Driver_Common::setOption()
  154. */
  155. define('MDB2_PORTABILITY_DELETE_COUNT', 4);
  156. /**
  157. * Portability: not needed in MDB2 (just left here for compatibility to DB)
  158. * @see MDB2_Driver_Common::setOption()
  159. */
  160. define('MDB2_PORTABILITY_NUMROWS', 8);
  161. /**
  162. * Portability: makes certain error messages in certain drivers compatible
  163. * with those from other DBMS's.
  164. *
  165. * + mysql, mysqli: change unique/primary key constraints
  166. * MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT
  167. *
  168. * + odbc(access): MS's ODBC driver reports 'no such field' as code
  169. * 07001, which means 'too few parameters.' When this option is on
  170. * that code gets mapped to MDB2_ERROR_NOSUCHFIELD.
  171. *
  172. * @see MDB2_Driver_Common::setOption()
  173. */
  174. define('MDB2_PORTABILITY_ERRORS', 16);
  175. /**
  176. * Portability: convert empty values to null strings in data output by
  177. * query*() and fetch*().
  178. * @see MDB2_Driver_Common::setOption()
  179. */
  180. define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
  181. /**
  182. * Portability: removes database/table qualifiers from associative indexes
  183. * @see MDB2_Driver_Common::setOption()
  184. */
  185. define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
  186. /**
  187. * Portability: turn on all portability features.
  188. * @see MDB2_Driver_Common::setOption()
  189. */
  190. define('MDB2_PORTABILITY_ALL', 127);
  191. // }}}
  192. // {{{ Globals for class instance tracking
  193. /**
  194. * These are global variables that are used to track the various class instances
  195. */
  196. $GLOBALS['_MDB2_databases'] = array();
  197. $GLOBALS['_MDB2_dsninfo_default'] = array('phptype' => false, 'dbsyntax' => false, 'username' => false,
  198. 'password' => false, 'protocol' => false, 'hostspec' => false, 'port' => false, 'socket' => false,
  199. 'database' => false, 'mode' => false);
  200. // }}}
  201. // {{{ class MDB2
  202. /**
  203. * The main 'MDB2' class is simply a container class with some static
  204. * methods for creating DB objects as well as some utility functions
  205. * common to all parts of DB.
  206. *
  207. * The object model of MDB2 is as follows (indentation means inheritance):
  208. *
  209. * MDB2 The main MDB2 class. This is simply a utility class
  210. * with some 'static' methods for creating MDB2 objects as
  211. * well as common utility functions for other MDB2 classes.
  212. *
  213. * MDB2_Driver_Common The base for each MDB2 implementation. Provides default
  214. * | implementations (in OO lingo virtual methods) for
  215. * | the actual DB implementations as well as a bunch of
  216. * | query utility functions.
  217. * |
  218. * +-MDB2_Driver_mysql The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
  219. * When calling MDB2::factory or MDB2::connect for MySQL
  220. * connections, the object returned is an instance of this
  221. * class.
  222. * +-MDB2_Driver_pgsql The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
  223. * When calling MDB2::factory or MDB2::connect for PostGreSQL
  224. * connections, the object returned is an instance of this
  225. * class.
  226. *
  227. * @package MDB2
  228. * @category Database
  229. * @author Lukas Smith <smith@pooteeweet.org>
  230. */
  231. class MDB2
  232. {
  233. // {{{ function setOptions(&$db, $options)
  234. /**
  235. * set option array in an exiting database object
  236. *
  237. * @param MDB2_Driver_Common MDB2 object
  238. * @param array An associative array of option names and their values.
  239. *
  240. * @return mixed MDB2_OK or a PEAR Error object
  241. *
  242. * @access public
  243. */
  244. function setOptions(&$db, $options)
  245. {
  246. if (is_array($options))
  247. {
  248. foreach ($options as $option => $value)
  249. {
  250. $test = $db->setOption($option, $value);
  251. if (PEAR :: isError($test))
  252. {
  253. return $test;
  254. }
  255. }
  256. }
  257. return MDB2_OK;
  258. }
  259. // }}}
  260. // {{{ function classExists($classname)
  261. /**
  262. * Checks if a class exists without triggering __autoload
  263. *
  264. * @param string classname
  265. *
  266. * @return bool true success and false on error
  267. * @static
  268. * @access public
  269. */
  270. function classExists($classname)
  271. {
  272. if (version_compare(phpversion(), "5.0", ">="))
  273. {
  274. return class_exists($classname, false);
  275. }
  276. return class_exists($classname);
  277. }
  278. // }}}
  279. // {{{ function loadClass($class_name, $debug)
  280. /**
  281. * Loads a PEAR class.
  282. *
  283. * @param string classname to load
  284. * @param bool if errors should be suppressed
  285. *
  286. * @return mixed true success or PEAR_Error on failure
  287. *
  288. * @access public
  289. */
  290. function loadClass($class_name, $debug)
  291. {
  292. if (! MDB2 :: classExists($class_name))
  293. {
  294. $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name) . '.php';
  295. if ($debug)
  296. {
  297. $include = include_once ($file_name);
  298. }
  299. else
  300. {
  301. $include = @include_once ($file_name);
  302. }
  303. if (! $include)
  304. {
  305. if (! MDB2 :: fileExists($file_name))
  306. {
  307. $msg = "unable to find package '$class_name' file '$file_name'";
  308. }
  309. else
  310. {
  311. $msg = "unable to load class '$class_name' from file '$file_name'";
  312. }
  313. $err = & MDB2 :: raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
  314. return $err;
  315. }
  316. }
  317. return MDB2_OK;
  318. }
  319. // }}}
  320. // {{{ function &factory($dsn, $options = false)
  321. /**
  322. * Create a new MDB2 object for the specified database type
  323. *
  324. * IMPORTANT: In order for MDB2 to work properly it is necessary that
  325. * you make sure that you work with a reference of the original
  326. * object instead of a copy (this is a PHP4 quirk).
  327. *
  328. * For example:
  329. * $db =& MDB2::factory($dsn);
  330. * ^^
  331. * And not:
  332. * $db = MDB2::factory($dsn);
  333. *
  334. * @param mixed 'data source name', see the MDB2::parseDSN
  335. * method for a description of the dsn format.
  336. * Can also be specified as an array of the
  337. * format returned by MDB2::parseDSN.
  338. * @param array An associative array of option names and
  339. * their values.
  340. *
  341. * @return mixed a newly created MDB2 object, or false on error
  342. *
  343. * @access public
  344. */
  345. function &factory($dsn, $options = false)
  346. {
  347. $dsninfo = MDB2 :: parseDSN($dsn);
  348. if (empty($dsninfo['phptype']))
  349. {
  350. $err = & MDB2 :: raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'no RDBMS driver specified');
  351. return $err;
  352. }
  353. $class_name = 'MDB2_Driver_' . $dsninfo['phptype'];
  354. $debug = (! empty($options['debug']));
  355. $err = MDB2 :: loadClass($class_name, $debug);
  356. if (PEAR :: isError($err))
  357. {
  358. return $err;
  359. }
  360. $db = new $class_name();
  361. $db->setDSN($dsninfo);
  362. $err = MDB2 :: setOptions($db, $options);
  363. if (PEAR :: isError($err))
  364. {
  365. return $err;
  366. }
  367. return $db;
  368. }
  369. // }}}
  370. // {{{ function &connect($dsn, $options = false)
  371. /**
  372. * Create a new MDB2_Driver_* connection object and connect to the specified
  373. * database
  374. *
  375. * IMPORTANT: In order for MDB2 to work properly it is necessary that
  376. * you make sure that you work with a reference of the original
  377. * object instead of a copy (this is a PHP4 quirk).
  378. *
  379. * For example:
  380. * $db =& MDB2::connect($dsn);
  381. * ^^
  382. * And not:
  383. * $db = MDB2::connect($dsn);
  384. * ^^
  385. *
  386. * @param mixed $dsn 'data source name', see the MDB2::parseDSN
  387. * method for a description of the dsn format.
  388. * Can also be specified as an array of the
  389. * format returned by MDB2::parseDSN.
  390. * @param array $options An associative array of option names and
  391. * their values.
  392. *
  393. * @return mixed a newly created MDB2 connection object, or a MDB2
  394. * error object on error
  395. *
  396. * @access public
  397. * @see MDB2::parseDSN
  398. */
  399. function &connect($dsn, $options = false)
  400. {
  401. $db = & MDB2 :: factory($dsn, $options);
  402. if (PEAR :: isError($db))
  403. {
  404. return $db;
  405. }
  406. $err = $db->connect();
  407. if (PEAR :: isError($err))
  408. {
  409. $dsn = $db->getDSN('string', 'xxx');
  410. $db->disconnect();
  411. $err->addUserInfo($dsn);
  412. return $err;
  413. }
  414. return $db;
  415. }
  416. // }}}
  417. // {{{ function &singleton($dsn = null, $options = false)
  418. /**
  419. * Returns a MDB2 connection with the requested DSN.
  420. * A new MDB2 connection object is only created if no object with the
  421. * requested DSN exists yet.
  422. *
  423. * IMPORTANT: In order for MDB2 to work properly it is necessary that
  424. * you make sure that you work with a reference of the original
  425. * object instead of a copy (this is a PHP4 quirk).
  426. *
  427. * For example:
  428. * $db =& MDB2::singleton($dsn);
  429. * ^^
  430. * And not:
  431. * $db = MDB2::singleton($dsn);
  432. * ^^
  433. *
  434. * @param mixed 'data source name', see the MDB2::parseDSN
  435. * method for a description of the dsn format.
  436. * Can also be specified as an array of the
  437. * format returned by MDB2::parseDSN.
  438. * @param array An associative array of option names and
  439. * their values.
  440. *
  441. * @return mixed a newly created MDB2 connection object, or a MDB2
  442. * error object on error
  443. *
  444. * @access public
  445. * @see MDB2::parseDSN
  446. */
  447. function &singleton($dsn = null, $options = false)
  448. {
  449. if ($dsn)
  450. {
  451. $dsninfo = MDB2 :: parseDSN($dsn);
  452. $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
  453. $keys = array_keys($GLOBALS['_MDB2_databases']);
  454. for($i = 0, $j = count($keys); $i < $j; ++ $i)
  455. {
  456. if (isset($GLOBALS['_MDB2_databases'][$keys[$i]]))
  457. {
  458. $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
  459. if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0)
  460. {
  461. MDB2 :: setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
  462. return $GLOBALS['_MDB2_databases'][$keys[$i]];
  463. }
  464. }
  465. }
  466. }
  467. elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases']))
  468. {
  469. $db = & $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
  470. return $db;
  471. }
  472. $db = & MDB2 :: factory($dsn, $options);
  473. return $db;
  474. }
  475. // }}}
  476. // {{{ function areEquals()
  477. /**
  478. * It looks like there's a memory leak in array_diff() in PHP 5.1.x,
  479. * so use this method instead.
  480. * @see http://pear.php.net/bugs/bug.php?id=11790
  481. *
  482. * @param array $arr1
  483. * @param array $arr2
  484. * @return boolean
  485. */
  486. function areEquals($arr1, $arr2)
  487. {
  488. if (count($arr1) != count($arr2))
  489. {
  490. return false;
  491. }
  492. foreach (array_keys($arr1) as $k)
  493. {
  494. if (! array_key_exists($k, $arr2) || $arr1[$k] != $arr2[$k])
  495. {
  496. return false;
  497. }
  498. }
  499. return true;
  500. }
  501. // }}}
  502. // {{{ function loadFile($file)
  503. /**
  504. * load a file (like 'Date')
  505. *
  506. * @param string name of the file in the MDB2 directory (without '.php')
  507. *
  508. * @return string name of the file that was included
  509. *
  510. * @access public
  511. */
  512. function loadFile($file)
  513. {
  514. $file_name = 'MDB2' . DIRECTORY_SEPARATOR . $file . '.php';
  515. if (! MDB2 :: fileExists($file_name))
  516. {
  517. return MDB2 :: raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'unable to find: ' . $file_name);
  518. }
  519. if (! include_once ($file_name))
  520. {
  521. return MDB2 :: raiseError(MDB2_ERROR_NOT_FOUND, null, null, 'unable to load driver class: ' . $file_name);
  522. }
  523. return $file_name;
  524. }
  525. // }}}
  526. // {{{ function apiVersion()
  527. /**
  528. * Return the MDB2 API version
  529. *
  530. * @return string the MDB2 API version number
  531. *
  532. * @access public
  533. */
  534. function apiVersion()
  535. {
  536. return '2.5.0b2';
  537. }
  538. // }}}
  539. // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
  540. /**
  541. * This method is used to communicate an error and invoke error
  542. * callbacks etc. Basically a wrapper for PEAR::raiseError
  543. * without the message string.
  544. *
  545. * @param mixed int error code
  546. *
  547. * @param int error mode, see PEAR_Error docs
  548. *
  549. * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the
  550. * error level (E_USER_NOTICE etc). If error mode is
  551. * PEAR_ERROR_CALLBACK, this is the callback function,
  552. * either as a function name, or as an array of an
  553. * object and method name. For other error modes this
  554. * parameter is ignored.
  555. *
  556. * @param string Extra debug information. Defaults to the last
  557. * query and native error code.
  558. *
  559. * @return PEAR_Error instance of a PEAR Error object
  560. *
  561. * @access private
  562. * @see PEAR_Error
  563. */
  564. function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $dummy1 = null, $dummy2 = null, $dummy3 = false)
  565. {
  566. $err = & PEAR :: raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
  567. return $err;
  568. }
  569. // }}}
  570. // {{{ function isError($data, $code = null)
  571. /**
  572. * Tell whether a value is a MDB2 error.
  573. *
  574. * @param mixed the value to test
  575. * @param int if is an error object, return true
  576. * only if $code is a string and
  577. * $db->getMessage() == $code or
  578. * $code is an integer and $db->getCode() == $code
  579. *
  580. * @return bool true if parameter is an error
  581. *
  582. * @access public
  583. */
  584. function isError($data, $code = null)
  585. {
  586. if (is_a($data, 'MDB2_Error'))
  587. {
  588. if (is_null($code))
  589. {
  590. return true;
  591. }
  592. elseif (is_string($code))
  593. {
  594. return $data->getMessage() === $code;
  595. }
  596. else
  597. {
  598. $code = (array) $code;
  599. return in_array($data->getCode(), $code);
  600. }
  601. }
  602. return false;
  603. }
  604. // }}}
  605. // {{{ function isConnection($value)
  606. /**
  607. * Tell whether a value is a MDB2 connection
  608. *
  609. * @param mixed value to test
  610. *
  611. * @return bool whether $value is a MDB2 connection
  612. *
  613. * @access public
  614. */
  615. function isConnection($value)
  616. {
  617. return is_a($value, 'MDB2_Driver_Common');
  618. }
  619. // }}}
  620. // {{{ function isResult($value)
  621. /**
  622. * Tell whether a value is a MDB2 result
  623. *
  624. * @param mixed value to test
  625. *
  626. * @return bool whether $value is a MDB2 result
  627. *
  628. * @access public
  629. */
  630. function isResult($value)
  631. {
  632. return is_a($value, 'MDB2_Result');
  633. }
  634. // }}}
  635. // {{{ function isResultCommon($value)
  636. /**
  637. * Tell whether a value is a MDB2 result implementing the common interface
  638. *
  639. * @param mixed value to test
  640. *
  641. * @return bool whether $value is a MDB2 result implementing the common interface
  642. *
  643. * @access public
  644. */
  645. function isResultCommon($value)
  646. {
  647. return is_a($value, 'MDB2_Result_Common');
  648. }
  649. // }}}
  650. // {{{ function isStatement($value)
  651. /**
  652. * Tell whether a value is a MDB2 statement interface
  653. *
  654. * @param mixed value to test
  655. *
  656. * @return bool whether $value is a MDB2 statement interface
  657. *
  658. * @access public
  659. */
  660. function isStatement($value)
  661. {
  662. return is_a($value, 'MDB2_Statement_Common');
  663. }
  664. // }}}
  665. // {{{ function errorMessage($value = null)
  666. /**
  667. * Return a textual error message for a MDB2 error code
  668. *
  669. * @param int|array integer error code,
  670. null to get the current error code-message map,
  671. or an array with a new error code-message map
  672. *
  673. * @return string error message, or false if the error code was
  674. * not recognized
  675. *
  676. * @access public
  677. */
  678. function errorMessage($value = null)
  679. {
  680. static $errorMessages;
  681. if (is_array($value))
  682. {
  683. $errorMessages = $value;
  684. return MDB2_OK;
  685. }
  686. if (! isset($errorMessages))
  687. {
  688. $errorMessages = array(MDB2_OK => 'no error', MDB2_ERROR => 'unknown error',
  689. MDB2_ERROR_ALREADY_EXISTS => 'already exists', MDB2_ERROR_CANNOT_CREATE => 'can not create',
  690. MDB2_ERROR_CANNOT_ALTER => 'can not alter', MDB2_ERROR_CANNOT_REPLACE => 'can not replace',
  691. MDB2_ERROR_CANNOT_DELETE => 'can not delete', MDB2_ERROR_CANNOT_DROP => 'can not drop',
  692. MDB2_ERROR_CONSTRAINT => 'constraint violation',
  693. MDB2_ERROR_CONSTRAINT_NOT_NULL => 'null value violates not-null constraint',
  694. MDB2_ERROR_DIVZERO => 'division by zero', MDB2_ERROR_INVALID => 'invalid',
  695. MDB2_ERROR_INVALID_DATE => 'invalid date or time', MDB2_ERROR_INVALID_NUMBER => 'invalid number',
  696. MDB2_ERROR_MISMATCH => 'mismatch', MDB2_ERROR_NODBSELECTED => 'no database selected',
  697. MDB2_ERROR_NOSUCHFIELD => 'no such field', MDB2_ERROR_NOSUCHTABLE => 'no such table',
  698. MDB2_ERROR_NOT_CAPABLE => 'MDB2 backend not capable', MDB2_ERROR_NOT_FOUND => 'not found',
  699. MDB2_ERROR_NOT_LOCKED => 'not locked', MDB2_ERROR_SYNTAX => 'syntax error',
  700. MDB2_ERROR_UNSUPPORTED => 'not supported', MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
  701. MDB2_ERROR_INVALID_DSN => 'invalid DSN', MDB2_ERROR_CONNECT_FAILED => 'connect failed',
  702. MDB2_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
  703. MDB2_ERROR_EXTENSION_NOT_FOUND => 'extension not found',
  704. MDB2_ERROR_NOSUCHDB => 'no such database',
  705. MDB2_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
  706. MDB2_ERROR_LOADMODULE => 'error while including on demand module',
  707. MDB2_ERROR_TRUNCATED => 'truncated', MDB2_ERROR_DEADLOCK => 'deadlock detected',
  708. MDB2_ERROR_NO_PERMISSION => 'no permission', MDB2_ERROR_DISCONNECT_FAILED => 'disconnect failed');
  709. }
  710. if (is_null($value))
  711. {
  712. return $errorMessages;
  713. }
  714. if (PEAR :: isError($value))
  715. {
  716. $value = $value->getCode();
  717. }
  718. return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[MDB2_ERROR];
  719. }
  720. // }}}
  721. // {{{ function parseDSN($dsn)
  722. /**
  723. * Parse a data source name.
  724. *
  725. * Additional keys can be added by appending a URI query string to the
  726. * end of the DSN.
  727. *
  728. * The format of the supplied DSN is in its fullest form:
  729. * <code>
  730. * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
  731. * </code>
  732. *
  733. * Most variations are allowed:
  734. * <code>
  735. * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
  736. * phptype://username:password@hostspec/database_name
  737. * phptype://username:password@hostspec
  738. * phptype://username@hostspec
  739. * phptype://hostspec/database
  740. * phptype://hostspec
  741. * phptype(dbsyntax)
  742. * phptype
  743. * </code>
  744. *
  745. * @param string Data Source Name to be parsed
  746. *
  747. * @return array an associative array with the following keys:
  748. * + phptype: Database backend used in PHP (mysql, odbc etc.)
  749. * + dbsyntax: Database used with regards to SQL syntax etc.
  750. * + protocol: Communication protocol to use (tcp, unix etc.)
  751. * + hostspec: Host specification (hostname[:port])
  752. * + database: Database to use on the DBMS server
  753. * + username: User name for login
  754. * + password: Password for login
  755. *
  756. * @access public
  757. * @author Tomas V.V.Cox <cox@idecnet.com>
  758. */
  759. function parseDSN($dsn)
  760. {
  761. $parsed = $GLOBALS['_MDB2_dsninfo_default'];
  762. if (is_array($dsn))
  763. {
  764. $dsn = array_merge($parsed, $dsn);
  765. if (! $dsn['dbsyntax'])
  766. {
  767. $dsn['dbsyntax'] = $dsn['phptype'];
  768. }
  769. return $dsn;
  770. }
  771. // Find phptype and dbsyntax
  772. if (($pos = strpos($dsn, '://')) !== false)
  773. {
  774. $str = substr($dsn, 0, $pos);
  775. $dsn = substr($dsn, $pos + 3);
  776. }
  777. else
  778. {
  779. $str = $dsn;
  780. $dsn = null;
  781. }
  782. // Get phptype and dbsyntax
  783. // $str => phptype(dbsyntax)
  784. if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr))
  785. {
  786. $parsed['phptype'] = $arr[1];
  787. $parsed['dbsyntax'] = ! $arr[2] ? $arr[1] : $arr[2];
  788. }
  789. else
  790. {
  791. $parsed['phptype'] = $str;
  792. $parsed['dbsyntax'] = $str;
  793. }
  794. if (! count($dsn))
  795. {
  796. return $parsed;
  797. }
  798. // Get (if found): username and password
  799. // $dsn => username:password@protocol+hostspec/database
  800. if (($at = strrpos($dsn, '@')) !== false)
  801. {
  802. $str = substr($dsn, 0, $at);
  803. $dsn = substr($dsn, $at + 1);
  804. if (($pos = strpos($str, ':')) !== false)
  805. {
  806. $parsed['username'] = rawurldecode(substr($str, 0, $pos));
  807. $parsed['password'] = rawurldecode(substr($str, $pos + 1));
  808. }
  809. else
  810. {
  811. $parsed['username'] = rawurldecode($str);
  812. }
  813. }
  814. // Find protocol and hostspec
  815. // $dsn => proto(proto_opts)/database
  816. if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match))
  817. {
  818. $proto = $match[1];
  819. $proto_opts = $match[2] ? $match[2] : false;
  820. $dsn = $match[3];
  821. // $dsn => protocol+hostspec/database (old format)
  822. }
  823. else
  824. {
  825. if (strpos($dsn, '+') !== false)
  826. {
  827. list($proto, $dsn) = explode('+', $dsn, 2);
  828. }
  829. if (strpos($dsn, '//') === 0 && strpos($dsn, '/', 2) !== false && $parsed['phptype'] == 'oci8')
  830. {
  831. //oracle's "Easy Connect" syntax:
  832. //"username/password@[//]host[:port][/service_name]"
  833. //e.g. "scott/tiger@//mymachine:1521/oracle"
  834. $proto_opts = $dsn;
  835. $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1);
  836. }
  837. elseif (strpos($dsn, '/') !== false)
  838. {
  839. list($proto_opts, $dsn) = explode('/', $dsn, 2);
  840. }
  841. else
  842. {
  843. $proto_opts = $dsn;
  844. $dsn = null;
  845. }
  846. }
  847. // process the different protocol options
  848. $parsed['protocol'] = (! empty($proto)) ? $proto : 'tcp';
  849. $proto_opts = rawurldecode($proto_opts);
  850. if (strpos($proto_opts, ':') !== false)
  851. {
  852. list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
  853. }
  854. if ($parsed['protocol'] == 'tcp')
  855. {
  856. $parsed['hostspec'] = $proto_opts;
  857. }
  858. elseif ($parsed['protocol'] == 'unix')
  859. {
  860. $parsed['socket'] = $proto_opts;
  861. }
  862. // Get dabase if any
  863. // $dsn => database
  864. if ($dsn)
  865. {
  866. // /database
  867. if (($pos = strpos($dsn, '?')) === false)
  868. {
  869. $parsed['database'] = $dsn;
  870. // /database?param1=value1&param2=value2
  871. }
  872. else
  873. {
  874. $parsed['database'] = substr($dsn, 0, $pos);
  875. $dsn = substr($dsn, $pos + 1);
  876. if (strpos($dsn, '&') !== false)
  877. {
  878. $opts = explode('&', $dsn);
  879. }
  880. else
  881. { // database?param1=value1
  882. $opts = array($dsn);
  883. }
  884. foreach ($opts as $opt)
  885. {
  886. list($key, $value) = explode('=', $opt);
  887. if (! isset($parsed[$key]))
  888. {
  889. // don't allow params overwrite
  890. $parsed[$key] = rawurldecode($value);
  891. }
  892. }
  893. }
  894. }
  895. return $parsed;
  896. }
  897. // }}}
  898. // {{{ function fileExists($file)
  899. /**
  900. * Checks if a file exists in the include path
  901. *
  902. * @param string filename
  903. *
  904. * @return bool true success and false on error
  905. *
  906. * @access public
  907. */
  908. function fileExists($file)
  909. {
  910. // safe_mode does notwork with is_readable()
  911. if (! @ini_get('safe_mode'))
  912. {
  913. $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
  914. foreach ($dirs as $dir)
  915. {
  916. if (is_readable($dir . DIRECTORY_SEPARATOR . $file))
  917. {
  918. return true;
  919. }
  920. }
  921. }
  922. else
  923. {
  924. $fp = @fopen($file, 'r', true);
  925. if (is_resource($fp))
  926. {
  927. @fclose($fp);
  928. return true;
  929. }
  930. }
  931. return false;
  932. }
  933. // }}}
  934. }
  935. // }}}
  936. // {{{ class MDB2_Error extends PEAR_Error
  937. /**
  938. * MDB2_Error implements a class for reporting portable database error
  939. * messages.
  940. *
  941. * @package MDB2
  942. * @category Database
  943. * @author Stig Bakken <ssb@fast.no>
  944. */
  945. class MDB2_Error extends PEAR_Error
  946. {
  947. // {{{ constructor: function __construct($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
  948. /**
  949. * MDB2_Error constructor.
  950. *
  951. * @param mixed MDB2 error code, or string with error message.
  952. * @param int what 'error mode' to operate in
  953. * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER
  954. * @param mixed additional debug info, such as the last query
  955. */
  956. function __construct($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null, $dummy = null)
  957. {
  958. if (is_null($code))
  959. {
  960. $code = MDB2_ERROR;
  961. }
  962. parent :: __construct('MDB2 Error: ' . MDB2 :: errorMessage($code), $code, $mode, $level, $debuginfo);
  963. }
  964. // }}}
  965. }
  966. // }}}
  967. // {{{ class MDB2_Driver_Common extends PEAR
  968. /**
  969. * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
  970. *
  971. * @package MDB2
  972. * @category Database
  973. * @author Lukas Smith <smith@pooteeweet.org>
  974. */
  975. class MDB2_Driver_Common extends PEAR
  976. {
  977. // {{{ Variables (Properties)
  978. /**
  979. * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
  980. * @var int
  981. * @access public
  982. */
  983. var $db_index = 0;
  984. /**
  985. * DSN used for the next query
  986. * @var array
  987. * @access protected
  988. */
  989. var $dsn = array();
  990. /**
  991. * DSN that was used to create the current connection
  992. * @var array
  993. * @access protected
  994. */
  995. var $connected_dsn = array();
  996. /**
  997. * connection resource
  998. * @var mixed
  999. * @access protected
  1000. */
  1001. var $connection = 0;
  1002. /**
  1003. * if the current opened connection is a persistent connection
  1004. * @var bool
  1005. * @access protected
  1006. */
  1007. var $opened_persistent;
  1008. /**
  1009. * the name of the database for the next query
  1010. * @var string
  1011. * @access protected
  1012. */
  1013. var $database_name = '';
  1014. /**
  1015. * the name of the database currently selected
  1016. * @var string
  1017. * @access protected
  1018. */
  1019. var $connected_database_name = '';
  1020. /**
  1021. * server version information
  1022. * @var string
  1023. * @access protected
  1024. */
  1025. var $connected_server_info = '';
  1026. /**
  1027. * list of all supported features of the given driver
  1028. * @var array
  1029. * @access public
  1030. */
  1031. var $supported = array('sequences' => false, 'indexes' => false, 'affected_rows' => false,
  1032. 'summary_functions' => false, 'order_by_text' => false, 'transactions' => false, 'savepoints' => false,
  1033. 'current_id' => false, 'limit_queries' => false, 'LOBs' => false, 'replace' => false, 'sub_selects' => false,
  1034. 'triggers' => false, 'auto_increment' => false, 'primary_key' => false, 'result_introspection' => false,
  1035. 'prepared_statements' => false, 'identifier_quoting' => false, 'pattern_escaping' => false,
  1036. 'new_link' => false);
  1037. /**
  1038. * Array of supported options that can be passed to the MDB2 instance.
  1039. *
  1040. * The options can be set during object creation, using
  1041. * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can
  1042. * also be set after the object is created, using MDB2::setOptions() or
  1043. * MDB2_Driver_Common::setOption().
  1044. * The list of available option includes:
  1045. * <ul>
  1046. * <li>$options['ssl'] -> boolean: determines if ssl should be used for connections</li>
  1047. * <li>$options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names</li>
  1048. * <li>$options['disable_query'] -> boolean: determines if queries should be executed</li>
  1049. * <li>$options['result_class'] -> string: class used for result sets</li>
  1050. * <li>$options['buffered_result_class'] -> string: class used for buffered result sets</li>
  1051. * <li>$options['result_wrap_class'] -> string: class used to wrap result sets into</li>
  1052. * <li>$options['result_buffering'] -> boolean should results be buffered or not?</li>
  1053. * <li>$options['fetch_class'] -> string: class to use when fetch mode object is used</li>
  1054. * <li>$options['persistent'] -> boolean: persistent connection?</li>
  1055. * <li>$options['debug'] -> integer: numeric debug level</li>
  1056. * <li>$options['debug_handler'] -> string: function/method that captures debug messages</li>
  1057. * <li>$options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler</li>
  1058. * <li>$options['default_text_field_length'] -> integer: default text field length to use</li>
  1059. * <li>$options['lob_buffer_length'] -> integer: LOB buffer length</li>
  1060. * <li>$options['log_line_break'] -> string: line-break format</li>
  1061. * <li>$options['idxname_format'] -> string: pattern for index name</li>
  1062. * <li>$options['seqname_format'] -> string: pattern for sequence name</li>
  1063. * <li>$options['savepoint_format'] -> string: pattern for auto generated savepoint names</li>
  1064. * <li>$options['statement_format'] -> string: pattern for prepared statement names</li>
  1065. * <li>$options['seqcol_name'] -> string: sequence column name</li>
  1066. * <li>$options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used</li>
  1067. * <li>$options['use_transactions'] -> boolean: if transaction use should be enabled</li>
  1068. * <li>$options['decimal_places'] -> integer: number of decimal places to handle</li>
  1069. * <li>$options['portability'] -> integer: portability constant</li>
  1070. * <li>$options['modules'] -> array: short to long module name mapping for __call()</li>
  1071. * <li>$options['emulate_prepared'] -> boolean: force prepared statements to be emulated</li>
  1072. * <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li>
  1073. * <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li>
  1074. * <li>$options['bindname_format'] -> string: regular expression pattern for named parameters</li>
  1075. * <li>$options['multi_query'] -> boolean: determines if queries returning multiple result sets should be executed</li>
  1076. * <li>$options['max_identifiers_length'] -> integer: max identifier length</li>
  1077. * <li>$options['default_fk_action_onupdate'] -> string: default FOREIGN KEY ON UPDATE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li>
  1078. * <li>$options['default_fk_action_ondelete'] -> string: default FOREIGN KEY ON DELETE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']</li>
  1079. * </ul>
  1080. *
  1081. * @var array
  1082. * @access public
  1083. * @see MDB2::connect()
  1084. * @see MDB2::factory()
  1085. * @see MDB2::singleton()
  1086. * @see MDB2_Driver_Common::setOption()
  1087. */
  1088. var $options = array('ssl' => false, 'field_case' => CASE_LOWER, 'disable_query' => false,
  1089. 'result_class' => 'MDB2_Result_%s', 'buffered_result_class' => 'MDB2_BufferedResult_%s',
  1090. 'result_wrap_class' => false, 'result_buffering' => true, 'fetch_class' => 'stdClass', 'persistent' => false,
  1091. 'debug' => 0, 'debug_handler' => 'MDB2_defaultDebugOutput', 'debug_expanded_output' => false,
  1092. 'default_text_field_length' => 4096, 'lob_buffer_length' => 8192, 'log_line_break' => "\n",
  1093. 'idxname_format' => '%s_idx', 'seqname_format' => '%s_seq', 'savepoint_format' => 'MDB2_SAVEPOINT_%s',
  1094. 'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s', 'seqcol_name' => 'sequence', 'quote_identifier' => false,
  1095. 'use_transactions' => true, 'decimal_places' => 2, 'portability' => MDB2_PORTABILITY_ALL,
  1096. 'modules' => array('ex' => 'Extended', 'dt' => 'Datatype', 'mg' => 'Manager', 'rv' => 'Reverse',
  1097. 'na' => 'Native', 'fc' => 'Function'), 'emulate_prepared' => false, 'datatype_map' => array(),
  1098. 'datatype_map_callback' => array(), 'nativetype_map_callback' => array(), 'lob_allow_url_include' => false,
  1099. 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)', 'max_identifiers_length' => 30,
  1100. 'default_fk_action_onupdate' => 'RESTRICT', 'default_fk_action_ondelete' => 'RESTRICT');
  1101. /**
  1102. * string array
  1103. * @var string
  1104. * @access protected
  1105. */
  1106. var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => false, 'escape_pattern' => false);
  1107. /**
  1108. * identifier quoting
  1109. * @var array
  1110. * @access protected
  1111. */
  1112. var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
  1113. /**
  1114. * sql comments
  1115. * @var array
  1116. * @access protected
  1117. */
  1118. var $sql_comments = array(array('start' => '--', 'end' => "\n", 'escape' => false),
  1119. array('start' => '/*', 'end' => '*/', 'escape' => false));
  1120. /**
  1121. * comparision wildcards
  1122. * @var array
  1123. * @access protected
  1124. */
  1125. var $wildcards = array('%', '_');
  1126. /**
  1127. * column alias keyword
  1128. * @var string
  1129. * @access protected
  1130. */
  1131. var $as_keyword = ' AS ';
  1132. /**
  1133. * warnings
  1134. * @var array
  1135. * @access protected
  1136. */
  1137. var $warnings = array();
  1138. /**
  1139. * string with the debugging information
  1140. * @var string
  1141. * @access public
  1142. */
  1143. var $debug_output = '';
  1144. /**
  1145. * determine if there is an open transaction
  1146. * @var bool
  1147. * @access protected
  1148. */
  1149. var $in_transaction = false;
  1150. /**
  1151. * the smart transaction nesting depth
  1152. * @var int
  1153. * @access protected
  1154. */
  1155. var $nested_transaction_counter = null;
  1156. /**
  1157. * the first error that occured inside a nested transaction
  1158. * @var MDB2_Error|bool
  1159. * @access protected
  1160. */
  1161. var $has_transaction_error = false;
  1162. /**
  1163. * result offset used in the next query
  1164. * @var int
  1165. * @access protected
  1166. */
  1167. var $offset = 0;
  1168. /**
  1169. * result limit used in the next query
  1170. * @var int
  1171. * @access protected
  1172. */
  1173. var $limit = 0;
  1174. /**
  1175. * Database backend used in PHP (mysql, odbc etc.)
  1176. * @var string
  1177. * @access public
  1178. */
  1179. var $phptype;
  1180. /**
  1181. * Database used with regards to SQL syntax etc.
  1182. * @var string
  1183. * @access public
  1184. */
  1185. var $dbsyntax;
  1186. /**
  1187. * the last query sent to the driver
  1188. * @var string
  1189. * @access public
  1190. */
  1191. var $last_query;
  1192. /**
  1193. * the default fetchmode used
  1194. * @var int
  1195. * @access protected
  1196. */
  1197. var $fetchmode = MDB2_FETCHMODE_ORDERED;
  1198. /**
  1199. * array of module instances
  1200. * @var array
  1201. * @access protected
  1202. */
  1203. var $modules = array();
  1204. /**
  1205. * determines of the PHP4 destructor emulation has been enabled yet
  1206. * @var array
  1207. * @access protected
  1208. */
  1209. var $destructor_registered = true;
  1210. // }}}
  1211. // {{{ constructor: function __construct()
  1212. /**
  1213. * Constructor
  1214. */
  1215. function __construct()
  1216. {
  1217. end($GLOBALS['_MDB2_databases']);
  1218. $db_index = key($GLOBALS['_MDB2_databases']) + 1;
  1219. $GLOBALS['_MDB2_databases'][$db_index] = &$this;
  1220. $this->db_index = $db_index;
  1221. }
  1222. // }}}
  1223. // {{{ function __construct()
  1224. /**
  1225. * PHP 4 Constructor
  1226. */
  1227. // function __construct()
  1228. // {
  1229. // $this->destructor_registered = false;
  1230. // $this->__construct();
  1231. // }
  1232. // }}}
  1233. // {{{ destructor: function __destruct()
  1234. /**
  1235. * Destructor
  1236. */
  1237. function __destruct()
  1238. {
  1239. $this->disconnect(false);
  1240. }
  1241. // }}}
  1242. // {{{ function free()
  1243. /**
  1244. * Free the internal references so that the instance can be destroyed
  1245. *
  1246. * @return bool true on success, false if result is invalid
  1247. *
  1248. * @access public
  1249. */
  1250. function free()
  1251. {
  1252. unset($GLOBALS['_MDB2_databases'][$this->db_index]);
  1253. unset($this->db_index);
  1254. return MDB2_OK;
  1255. }
  1256. // }}}
  1257. // {{{ function __toString()
  1258. /**
  1259. * String conversation
  1260. *
  1261. * @return string representation of the object
  1262. *
  1263. * @access public
  1264. */
  1265. function __toString()
  1266. {
  1267. $info = get_class($this);
  1268. $info .= ': (phptype = ' . $this->phptype . ', dbsyntax = ' . $this->dbsyntax . ')';
  1269. if ($this->connection)
  1270. {
  1271. $info .= ' [connected]';
  1272. }
  1273. return $info;
  1274. }
  1275. // }}}
  1276. // {{{ function errorInfo($error = null)
  1277. /**
  1278. * This method is used to collect information about an error
  1279. *
  1280. * @param mixed error code or resource
  1281. *
  1282. * @return array with MDB2 errorcode, native error code, native message
  1283. *
  1284. * @access public
  1285. */
  1286. function errorInfo($error = null)
  1287. {
  1288. return array($error, null, null);
  1289. }
  1290. // }}}
  1291. // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
  1292. /**
  1293. * This method is used to communicate an error and invoke error
  1294. * callbacks etc. Basically a wrapper for PEAR::raiseError
  1295. * without the message string.
  1296. *
  1297. * @param mixed $code integer error code, or a PEAR error object (all
  1298. * other parameters are ignored if this parameter is
  1299. * an object
  1300. * @param int $mode error mode, see PEAR_Error docs
  1301. * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
  1302. * error level (E_USER_NOTICE etc). If error mode is
  1303. * PEAR_ERROR_CALLBACK, this is the callback function,
  1304. * either as a function name, or as an array of an
  1305. * object and method name. For other error modes this
  1306. * parameter is ignored.
  1307. * @param string $userinfo Extra debug information. Defaults to the last
  1308. * query and native error code.
  1309. * @param string $method name of the method that triggered the error
  1310. * @param string $dummy1 not used
  1311. * @param bool $dummy2 not used
  1312. *
  1313. * @return PEAR_Error instance of a PEAR Error object
  1314. * @access public
  1315. * @see PEAR_Error
  1316. */
  1317. function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null, $dummy1 = null, $dummy2 = false)
  1318. {
  1319. $userinfo = "[Error message: $userinfo]\n";
  1320. // The error is yet a MDB2 error object
  1321. if (PEAR :: isError($code))
  1322. {
  1323. // because we use the static PEAR::raiseError, our global
  1324. // handler should be used if it is set
  1325. if (is_null($mode) && ! empty($this->_default_error_mode))
  1326. {
  1327. $mode = $this->_default_error_mode;
  1328. $options = $this->_default_error_options;
  1329. }
  1330. if (is_null($userinfo))
  1331. {
  1332. $userinfo = $code->getUserinfo();
  1333. }
  1334. $code = $code->getCode();
  1335. }
  1336. elseif ($code == MDB2_ERROR_NOT_FOUND)
  1337. {
  1338. // extension not loaded: don't call $this->errorInfo() or the script
  1339. // will die
  1340. }
  1341. elseif (isset($this->connection))
  1342. {
  1343. if (! empty($this->last_query))
  1344. {
  1345. $userinfo .= "[Last executed query: {$this->last_query}]\n";
  1346. }
  1347. $native_errno = $native_msg = null;
  1348. list($code, $native_errno, $native_msg) = $this->errorInfo($code);
  1349. if (! is_null($native_errno) && $native_errno !== '')
  1350. {
  1351. $userinfo .= "[Native code: $native_errno]\n";
  1352. }
  1353. if (! is_null($native_msg) && $native_msg !== '')
  1354. {
  1355. $userinfo .= "[Native message: " . strip_tags($native_msg) . "]\n";
  1356. }
  1357. if (! is_null($method))
  1358. {
  1359. $userinfo = $method . ': ' . $userinfo;
  1360. }
  1361. }
  1362. $err = & PEAR :: raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
  1363. if ($err->getMode() !== PEAR_ERROR_RETURN && isset($this->nested_transaction_counter) && ! $this->has_transaction_error)
  1364. {

Large files files are truncated, but you can click here to view the full file