PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/php/DB/fbsql.php

https://bitbucket.org/adarshj/convenient_website
PHP | 770 lines | 329 code | 70 blank | 371 comment | 49 complexity | 18d3371e949bbd0cd1f11d5b59becf6e MD5 | raw file
Possible License(s): Apache-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-2-Clause, GPL-2.0, LGPL-3.0
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * The PEAR DB driver for PHP's fbsql extension
  5. * for interacting with FrontBase databases
  6. *
  7. * PHP versions 4 and 5
  8. *
  9. * LICENSE: This source file is subject to version 3.0 of the PHP license
  10. * that is available through the world-wide-web at the following URI:
  11. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  12. * the PHP License and are unable to obtain it through the web, please
  13. * send a note to license@php.net so we can mail you a copy immediately.
  14. *
  15. * @category Database
  16. * @package DB
  17. * @author Frank M. Kromann <frank@frontbase.com>
  18. * @author Daniel Convissor <danielc@php.net>
  19. * @copyright 1997-2005 The PHP Group
  20. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  21. * @version CVS: $Id: fbsql.php,v 1.82 2005/03/04 23:12:36 danielc Exp $
  22. * @link http://pear.php.net/package/DB
  23. */
  24. /**
  25. * Obtain the DB_common class so it can be extended from
  26. */
  27. require_once 'DB/common.php';
  28. /**
  29. * The methods PEAR DB uses to interact with PHP's fbsql extension
  30. * for interacting with FrontBase databases
  31. *
  32. * These methods overload the ones declared in DB_common.
  33. *
  34. * @category Database
  35. * @package DB
  36. * @author Frank M. Kromann <frank@frontbase.com>
  37. * @author Daniel Convissor <danielc@php.net>
  38. * @copyright 1997-2005 The PHP Group
  39. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  40. * @version Release: 1.7.6
  41. * @link http://pear.php.net/package/DB
  42. * @since Class functional since Release 1.7.0
  43. */
  44. class DB_fbsql extends DB_common
  45. {
  46. // {{{ properties
  47. /**
  48. * The DB driver type (mysql, oci8, odbc, etc.)
  49. * @var string
  50. */
  51. var $phptype = 'fbsql';
  52. /**
  53. * The database syntax variant to be used (db2, access, etc.), if any
  54. * @var string
  55. */
  56. var $dbsyntax = 'fbsql';
  57. /**
  58. * The capabilities of this DB implementation
  59. *
  60. * The 'new_link' element contains the PHP version that first provided
  61. * new_link support for this DBMS. Contains false if it's unsupported.
  62. *
  63. * Meaning of the 'limit' element:
  64. * + 'emulate' = emulate with fetch row by number
  65. * + 'alter' = alter the query
  66. * + false = skip rows
  67. *
  68. * @var array
  69. */
  70. var $features = array(
  71. 'limit' => 'alter',
  72. 'new_link' => false,
  73. 'numrows' => true,
  74. 'pconnect' => true,
  75. 'prepare' => false,
  76. 'ssl' => false,
  77. 'transactions' => true,
  78. );
  79. /**
  80. * A mapping of native error codes to DB error codes
  81. * @var array
  82. */
  83. var $errorcode_map = array(
  84. 22 => DB_ERROR_SYNTAX,
  85. 85 => DB_ERROR_ALREADY_EXISTS,
  86. 108 => DB_ERROR_SYNTAX,
  87. 116 => DB_ERROR_NOSUCHTABLE,
  88. 124 => DB_ERROR_VALUE_COUNT_ON_ROW,
  89. 215 => DB_ERROR_NOSUCHFIELD,
  90. 217 => DB_ERROR_INVALID_NUMBER,
  91. 226 => DB_ERROR_NOSUCHFIELD,
  92. 231 => DB_ERROR_INVALID,
  93. 239 => DB_ERROR_TRUNCATED,
  94. 251 => DB_ERROR_SYNTAX,
  95. 266 => DB_ERROR_NOT_FOUND,
  96. 357 => DB_ERROR_CONSTRAINT_NOT_NULL,
  97. 358 => DB_ERROR_CONSTRAINT,
  98. 360 => DB_ERROR_CONSTRAINT,
  99. 361 => DB_ERROR_CONSTRAINT,
  100. );
  101. /**
  102. * The raw database connection created by PHP
  103. * @var resource
  104. */
  105. var $connection;
  106. /**
  107. * The DSN information for connecting to a database
  108. * @var array
  109. */
  110. var $dsn = array();
  111. // }}}
  112. // {{{ constructor
  113. /**
  114. * This constructor calls <kbd>$this->DB_common()</kbd>
  115. *
  116. * @return void
  117. */
  118. function DB_fbsql()
  119. {
  120. $this->DB_common();
  121. }
  122. // }}}
  123. // {{{ connect()
  124. /**
  125. * Connect to the database server, log in and open the database
  126. *
  127. * Don't call this method directly. Use DB::connect() instead.
  128. *
  129. * @param array $dsn the data source name
  130. * @param bool $persistent should the connection be persistent?
  131. *
  132. * @return int DB_OK on success. A DB_Error object on failure.
  133. */
  134. function connect($dsn, $persistent = false)
  135. {
  136. if (!PEAR::loadExtension('fbsql')) {
  137. return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  138. }
  139. $this->dsn = $dsn;
  140. if ($dsn['dbsyntax']) {
  141. $this->dbsyntax = $dsn['dbsyntax'];
  142. }
  143. $params = array(
  144. $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost',
  145. $dsn['username'] ? $dsn['username'] : null,
  146. $dsn['password'] ? $dsn['password'] : null,
  147. );
  148. $connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
  149. $ini = ini_get('track_errors');
  150. $php_errormsg = '';
  151. if ($ini) {
  152. $this->connection = @call_user_func_array($connect_function,
  153. $params);
  154. } else {
  155. ini_set('track_errors', 1);
  156. $this->connection = @call_user_func_array($connect_function,
  157. $params);
  158. ini_set('track_errors', $ini);
  159. }
  160. if (!$this->connection) {
  161. return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  162. null, null, null,
  163. $php_errormsg);
  164. }
  165. if ($dsn['database']) {
  166. if (!@fbsql_select_db($dsn['database'], $this->connection)) {
  167. return $this->fbsqlRaiseError();
  168. }
  169. }
  170. return DB_OK;
  171. }
  172. // }}}
  173. // {{{ disconnect()
  174. /**
  175. * Disconnects from the database server
  176. *
  177. * @return bool TRUE on success, FALSE on failure
  178. */
  179. function disconnect()
  180. {
  181. $ret = @fbsql_close($this->connection);
  182. $this->connection = null;
  183. return $ret;
  184. }
  185. // }}}
  186. // {{{ simpleQuery()
  187. /**
  188. * Sends a query to the database server
  189. *
  190. * @param string the SQL query string
  191. *
  192. * @return mixed + a PHP result resrouce for successful SELECT queries
  193. * + the DB_OK constant for other successful queries
  194. * + a DB_Error object on failure
  195. */
  196. function simpleQuery($query)
  197. {
  198. $this->last_query = $query;
  199. $query = $this->modifyQuery($query);
  200. $result = @fbsql_query("$query;", $this->connection);
  201. if (!$result) {
  202. return $this->fbsqlRaiseError();
  203. }
  204. // Determine which queries that should return data, and which
  205. // should return an error code only.
  206. if (DB::isManip($query)) {
  207. return DB_OK;
  208. }
  209. return $result;
  210. }
  211. // }}}
  212. // {{{ nextResult()
  213. /**
  214. * Move the internal fbsql result pointer to the next available result
  215. *
  216. * @param a valid fbsql result resource
  217. *
  218. * @access public
  219. *
  220. * @return true if a result is available otherwise return false
  221. */
  222. function nextResult($result)
  223. {
  224. return @fbsql_next_result($result);
  225. }
  226. // }}}
  227. // {{{ fetchInto()
  228. /**
  229. * Places a row from the result set into the given array
  230. *
  231. * Formating of the array and the data therein are configurable.
  232. * See DB_result::fetchInto() for more information.
  233. *
  234. * This method is not meant to be called directly. Use
  235. * DB_result::fetchInto() instead. It can't be declared "protected"
  236. * because DB_result is a separate object.
  237. *
  238. * @param resource $result the query result resource
  239. * @param array $arr the referenced array to put the data in
  240. * @param int $fetchmode how the resulting array should be indexed
  241. * @param int $rownum the row number to fetch (0 = first row)
  242. *
  243. * @return mixed DB_OK on success, NULL when the end of a result set is
  244. * reached or on failure
  245. *
  246. * @see DB_result::fetchInto()
  247. */
  248. function fetchInto($result, &$arr, $fetchmode, $rownum = null)
  249. {
  250. if ($rownum !== null) {
  251. if (!@fbsql_data_seek($result, $rownum)) {
  252. return null;
  253. }
  254. }
  255. if ($fetchmode & DB_FETCHMODE_ASSOC) {
  256. $arr = @fbsql_fetch_array($result, FBSQL_ASSOC);
  257. if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
  258. $arr = array_change_key_case($arr, CASE_LOWER);
  259. }
  260. } else {
  261. $arr = @fbsql_fetch_row($result);
  262. }
  263. if (!$arr) {
  264. return null;
  265. }
  266. if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
  267. $this->_rtrimArrayValues($arr);
  268. }
  269. if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
  270. $this->_convertNullArrayValuesToEmpty($arr);
  271. }
  272. return DB_OK;
  273. }
  274. // }}}
  275. // {{{ freeResult()
  276. /**
  277. * Deletes the result set and frees the memory occupied by the result set
  278. *
  279. * This method is not meant to be called directly. Use
  280. * DB_result::free() instead. It can't be declared "protected"
  281. * because DB_result is a separate object.
  282. *
  283. * @param resource $result PHP's query result resource
  284. *
  285. * @return bool TRUE on success, FALSE if $result is invalid
  286. *
  287. * @see DB_result::free()
  288. */
  289. function freeResult($result)
  290. {
  291. return @fbsql_free_result($result);
  292. }
  293. // }}}
  294. // {{{ autoCommit()
  295. /**
  296. * Enables or disables automatic commits
  297. *
  298. * @param bool $onoff true turns it on, false turns it off
  299. *
  300. * @return int DB_OK on success. A DB_Error object if the driver
  301. * doesn't support auto-committing transactions.
  302. */
  303. function autoCommit($onoff=false)
  304. {
  305. if ($onoff) {
  306. $this->query("SET COMMIT TRUE");
  307. } else {
  308. $this->query("SET COMMIT FALSE");
  309. }
  310. }
  311. // }}}
  312. // {{{ commit()
  313. /**
  314. * Commits the current transaction
  315. *
  316. * @return int DB_OK on success. A DB_Error object on failure.
  317. */
  318. function commit()
  319. {
  320. @fbsql_commit();
  321. }
  322. // }}}
  323. // {{{ rollback()
  324. /**
  325. * Reverts the current transaction
  326. *
  327. * @return int DB_OK on success. A DB_Error object on failure.
  328. */
  329. function rollback()
  330. {
  331. @fbsql_rollback();
  332. }
  333. // }}}
  334. // {{{ numCols()
  335. /**
  336. * Gets the number of columns in a result set
  337. *
  338. * This method is not meant to be called directly. Use
  339. * DB_result::numCols() instead. It can't be declared "protected"
  340. * because DB_result is a separate object.
  341. *
  342. * @param resource $result PHP's query result resource
  343. *
  344. * @return int the number of columns. A DB_Error object on failure.
  345. *
  346. * @see DB_result::numCols()
  347. */
  348. function numCols($result)
  349. {
  350. $cols = @fbsql_num_fields($result);
  351. if (!$cols) {
  352. return $this->fbsqlRaiseError();
  353. }
  354. return $cols;
  355. }
  356. // }}}
  357. // {{{ numRows()
  358. /**
  359. * Gets the number of rows in a result set
  360. *
  361. * This method is not meant to be called directly. Use
  362. * DB_result::numRows() instead. It can't be declared "protected"
  363. * because DB_result is a separate object.
  364. *
  365. * @param resource $result PHP's query result resource
  366. *
  367. * @return int the number of rows. A DB_Error object on failure.
  368. *
  369. * @see DB_result::numRows()
  370. */
  371. function numRows($result)
  372. {
  373. $rows = @fbsql_num_rows($result);
  374. if ($rows === null) {
  375. return $this->fbsqlRaiseError();
  376. }
  377. return $rows;
  378. }
  379. // }}}
  380. // {{{ affectedRows()
  381. /**
  382. * Determines the number of rows affected by a data maniuplation query
  383. *
  384. * 0 is returned for queries that don't manipulate data.
  385. *
  386. * @return int the number of rows. A DB_Error object on failure.
  387. */
  388. function affectedRows()
  389. {
  390. if (DB::isManip($this->last_query)) {
  391. $result = @fbsql_affected_rows($this->connection);
  392. } else {
  393. $result = 0;
  394. }
  395. return $result;
  396. }
  397. // }}}
  398. // {{{ nextId()
  399. /**
  400. * Returns the next free id in a sequence
  401. *
  402. * @param string $seq_name name of the sequence
  403. * @param boolean $ondemand when true, the seqence is automatically
  404. * created if it does not exist
  405. *
  406. * @return int the next id number in the sequence.
  407. * A DB_Error object on failure.
  408. *
  409. * @see DB_common::nextID(), DB_common::getSequenceName(),
  410. * DB_fbsql::createSequence(), DB_fbsql::dropSequence()
  411. */
  412. function nextId($seq_name, $ondemand = true)
  413. {
  414. $seqname = $this->getSequenceName($seq_name);
  415. do {
  416. $repeat = 0;
  417. $this->pushErrorHandling(PEAR_ERROR_RETURN);
  418. $result = $this->query('SELECT UNIQUE FROM ' . $seqname);
  419. $this->popErrorHandling();
  420. if ($ondemand && DB::isError($result) &&
  421. $result->getCode() == DB_ERROR_NOSUCHTABLE) {
  422. $repeat = 1;
  423. $result = $this->createSequence($seq_name);
  424. if (DB::isError($result)) {
  425. return $result;
  426. }
  427. } else {
  428. $repeat = 0;
  429. }
  430. } while ($repeat);
  431. if (DB::isError($result)) {
  432. return $this->fbsqlRaiseError();
  433. }
  434. $result->fetchInto($tmp, DB_FETCHMODE_ORDERED);
  435. return $tmp[0];
  436. }
  437. /**
  438. * Creates a new sequence
  439. *
  440. * @param string $seq_name name of the new sequence
  441. *
  442. * @return int DB_OK on success. A DB_Error object on failure.
  443. *
  444. * @see DB_common::createSequence(), DB_common::getSequenceName(),
  445. * DB_fbsql::nextID(), DB_fbsql::dropSequence()
  446. */
  447. function createSequence($seq_name)
  448. {
  449. $seqname = $this->getSequenceName($seq_name);
  450. $res = $this->query('CREATE TABLE ' . $seqname
  451. . ' (id INTEGER NOT NULL,'
  452. . ' PRIMARY KEY(id))');
  453. if ($res) {
  454. $res = $this->query('SET UNIQUE = 0 FOR ' . $seqname);
  455. }
  456. return $res;
  457. }
  458. // }}}
  459. // {{{ dropSequence()
  460. /**
  461. * Deletes a sequence
  462. *
  463. * @param string $seq_name name of the sequence to be deleted
  464. *
  465. * @return int DB_OK on success. A DB_Error object on failure.
  466. *
  467. * @see DB_common::dropSequence(), DB_common::getSequenceName(),
  468. * DB_fbsql::nextID(), DB_fbsql::createSequence()
  469. */
  470. function dropSequence($seq_name)
  471. {
  472. return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)
  473. . ' RESTRICT');
  474. }
  475. // }}}
  476. // {{{ modifyLimitQuery()
  477. /**
  478. * Adds LIMIT clauses to a query string according to current DBMS standards
  479. *
  480. * @param string $query the query to modify
  481. * @param int $from the row to start to fetching (0 = the first row)
  482. * @param int $count the numbers of rows to fetch
  483. * @param mixed $params array, string or numeric data to be used in
  484. * execution of the statement. Quantity of items
  485. * passed must match quantity of placeholders in
  486. * query: meaning 1 placeholder for non-array
  487. * parameters or 1 placeholder per array element.
  488. *
  489. * @return string the query string with LIMIT clauses added
  490. *
  491. * @access protected
  492. */
  493. function modifyLimitQuery($query, $from, $count, $params = array())
  494. {
  495. if (DB::isManip($query)) {
  496. return preg_replace('/^([\s(])*SELECT/i',
  497. "\\1SELECT TOP($count)", $query);
  498. } else {
  499. return preg_replace('/([\s(])*SELECT/i',
  500. "\\1SELECT TOP($from, $count)", $query);
  501. }
  502. }
  503. // }}}
  504. // {{{ quoteSmart()
  505. /**
  506. * Formats input so it can be safely used in a query
  507. *
  508. * @param mixed $in the data to be formatted
  509. *
  510. * @return mixed the formatted data. The format depends on the input's
  511. * PHP type:
  512. * + null = the string <samp>NULL</samp>
  513. * + boolean = string <samp>TRUE</samp> or <samp>FALSE</samp>
  514. * + integer or double = the unquoted number
  515. * + other (including strings and numeric strings) =
  516. * the data escaped according to FrontBase's settings
  517. * then encapsulated between single quotes
  518. *
  519. * @see DB_common::quoteSmart()
  520. * @since Method available since Release 1.6.0
  521. */
  522. function quoteSmart($in)
  523. {
  524. if (is_int($in) || is_double($in)) {
  525. return $in;
  526. } elseif (is_bool($in)) {
  527. return $in ? 'TRUE' : 'FALSE';
  528. } elseif (is_null($in)) {
  529. return 'NULL';
  530. } else {
  531. return "'" . $this->escapeSimple($in) . "'";
  532. }
  533. }
  534. // }}}
  535. // {{{ fbsqlRaiseError()
  536. /**
  537. * Produces a DB_Error object regarding the current problem
  538. *
  539. * @param int $errno if the error is being manually raised pass a
  540. * DB_ERROR* constant here. If this isn't passed
  541. * the error information gathered from the DBMS.
  542. *
  543. * @return object the DB_Error object
  544. *
  545. * @see DB_common::raiseError(),
  546. * DB_fbsql::errorNative(), DB_common::errorCode()
  547. */
  548. function fbsqlRaiseError($errno = null)
  549. {
  550. if ($errno === null) {
  551. $errno = $this->errorCode(fbsql_errno($this->connection));
  552. }
  553. return $this->raiseError($errno, null, null, null,
  554. @fbsql_error($this->connection));
  555. }
  556. // }}}
  557. // {{{ errorNative()
  558. /**
  559. * Gets the DBMS' native error code produced by the last query
  560. *
  561. * @return int the DBMS' error code
  562. */
  563. function errorNative()
  564. {
  565. return @fbsql_errno($this->connection);
  566. }
  567. // }}}
  568. // {{{ tableInfo()
  569. /**
  570. * Returns information about a table or a result set
  571. *
  572. * @param object|string $result DB_result object from a query or a
  573. * string containing the name of a table.
  574. * While this also accepts a query result
  575. * resource identifier, this behavior is
  576. * deprecated.
  577. * @param int $mode a valid tableInfo mode
  578. *
  579. * @return array an associative array with the information requested.
  580. * A DB_Error object on failure.
  581. *
  582. * @see DB_common::tableInfo()
  583. */
  584. function tableInfo($result, $mode = null)
  585. {
  586. if (is_string($result)) {
  587. /*
  588. * Probably received a table name.
  589. * Create a result resource identifier.
  590. */
  591. $id = @fbsql_list_fields($this->dsn['database'],
  592. $result, $this->connection);
  593. $got_string = true;
  594. } elseif (isset($result->result)) {
  595. /*
  596. * Probably received a result object.
  597. * Extract the result resource identifier.
  598. */
  599. $id = $result->result;
  600. $got_string = false;
  601. } else {
  602. /*
  603. * Probably received a result resource identifier.
  604. * Copy it.
  605. * Deprecated. Here for compatibility only.
  606. */
  607. $id = $result;
  608. $got_string = false;
  609. }
  610. if (!is_resource($id)) {
  611. return $this->fbsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  612. }
  613. if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
  614. $case_func = 'strtolower';
  615. } else {
  616. $case_func = 'strval';
  617. }
  618. $count = @fbsql_num_fields($id);
  619. $res = array();
  620. if ($mode) {
  621. $res['num_fields'] = $count;
  622. }
  623. for ($i = 0; $i < $count; $i++) {
  624. $res[$i] = array(
  625. 'table' => $case_func(@fbsql_field_table($id, $i)),
  626. 'name' => $case_func(@fbsql_field_name($id, $i)),
  627. 'type' => @fbsql_field_type($id, $i),
  628. 'len' => @fbsql_field_len($id, $i),
  629. 'flags' => @fbsql_field_flags($id, $i),
  630. );
  631. if ($mode & DB_TABLEINFO_ORDER) {
  632. $res['order'][$res[$i]['name']] = $i;
  633. }
  634. if ($mode & DB_TABLEINFO_ORDERTABLE) {
  635. $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
  636. }
  637. }
  638. // free the result only if we were called on a table
  639. if ($got_string) {
  640. @fbsql_free_result($id);
  641. }
  642. return $res;
  643. }
  644. // }}}
  645. // {{{ getSpecialQuery()
  646. /**
  647. * Obtains the query string needed for listing a given type of objects
  648. *
  649. * @param string $type the kind of objects you want to retrieve
  650. *
  651. * @return string the SQL query string or null if the driver doesn't
  652. * support the object type requested
  653. *
  654. * @access protected
  655. * @see DB_common::getListOf()
  656. */
  657. function getSpecialQuery($type)
  658. {
  659. switch ($type) {
  660. case 'tables':
  661. return 'SELECT "table_name" FROM information_schema.tables'
  662. . ' t0, information_schema.schemata t1'
  663. . ' WHERE t0.schema_pk=t1.schema_pk AND'
  664. . ' "table_type" = \'BASE TABLE\''
  665. . ' AND "schema_name" = current_schema';
  666. case 'views':
  667. return 'SELECT "table_name" FROM information_schema.tables'
  668. . ' t0, information_schema.schemata t1'
  669. . ' WHERE t0.schema_pk=t1.schema_pk AND'
  670. . ' "table_type" = \'VIEW\''
  671. . ' AND "schema_name" = current_schema';
  672. case 'users':
  673. return 'SELECT "user_name" from information_schema.users';
  674. case 'functions':
  675. return 'SELECT "routine_name" FROM'
  676. . ' information_schema.psm_routines'
  677. . ' t0, information_schema.schemata t1'
  678. . ' WHERE t0.schema_pk=t1.schema_pk'
  679. . ' AND "routine_kind"=\'FUNCTION\''
  680. . ' AND "schema_name" = current_schema';
  681. case 'procedures':
  682. return 'SELECT "routine_name" FROM'
  683. . ' information_schema.psm_routines'
  684. . ' t0, information_schema.schemata t1'
  685. . ' WHERE t0.schema_pk=t1.schema_pk'
  686. . ' AND "routine_kind"=\'PROCEDURE\''
  687. . ' AND "schema_name" = current_schema';
  688. default:
  689. return null;
  690. }
  691. }
  692. // }}}
  693. }
  694. /*
  695. * Local variables:
  696. * tab-width: 4
  697. * c-basic-offset: 4
  698. * End:
  699. */
  700. ?>