Source for file query-defs.php

Documentation is available at query-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: query-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for making queries on the database */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package database */
  27. include_once("datetime-defs.php");
  28.  
  29. // ----------------------------------------------------------------------
  30. // TRANSACTION Class
  31.  
  32. /** Transaction response to failure - rollback */
  33. ("ROLLBACK_ON_FAIL", true);
  34. /** Transaction response to failure - do nothing */
  35. ("NO_ROLLBACK_ON_FAIL", false);
  36.  
  37. // ----------------------------------------------------------------------
  38. // NULL query term
  39.  
  40. /** This value indicates a NULL field value for queries */
  41. ("NULLVALUE", "NULL!FIELD!VALUE");
  42.  
  43. // ----------------------------------------------------------------------
  44. /**
  45. * Transaction class
  46. * Encapsulates the query transaction.
  47. * @package database
  48. * @access private
  49. */
  50. class transaction {
  51. /** Transaction mode */
  52.  
  53. var $mode = ROLLBACK_ON_FAIL;
  54. /** True if there is an open transaction */
  55.  
  56. var $open = false;
  57. /** True if the transaction failed */
  58.  
  59. var $failed = false;
  60. /** If failed, message describing failure */
  61.  
  62. var $failed_msg = "";
  63. // ....................................................................
  64. /**
  65. * Constructor
  66. *
  67. * Create a transaction. Sets basic transaction attributes.
  68. * This transaction object is used, via global functions, for
  69. * every transaction using these query routines.
  70. * @param bool $mode Transaction rollback mode (true = rollback on failure)
  71. */
  72. function transaction($mode=ROLLBACK_ON_FAIL) {
  73. $this->mode = $mode;
  74. }
  75. // ....................................................................
  76. /**
  77. * Begin transaction
  78. * Start a transaction.
  79. * @param bool $mode Transaction rollback mode (true = rollback on failure)
  80. */
  81. function begin($mode=ROLLBACK_ON_FAIL) {
  82. global $RESPONSE;
  83. if ($RESPONSE->db_backed && !$this->open) {
  84. $RESPONSE->datasource->begin_transaction();
  85. $this->open = true;
  86. $this->mode = $mode;
  87. $this->failed = false;
  88. $this->failed_msg = "";
  89. if (debugging()) {
  90. debugbr("TOK: Start transaction.", DBG_SQL);
  91. }
  92. }
  93. }
  94. // ....................................................................
  95. /**
  96. * Commit transaction
  97. * Try to commit the open transaction. If an error
  98. * occurs then try to roll back if flagged to do so.
  99. * @return boolean True if the transaction succeeded.
  100. */
  101. function commit() {
  102. global $RESPONSE;
  103. $tok = false;
  104. if ($RESPONSE->db_backed && $this->open) {
  105. // Deal with failed transactions..
  106. if ($this->failed) {
  107. $errmsg = "transaction failed";
  108. error_log("TFAIL: " . APP_NAME . ": $errmsg", 0);
  109. if (debugging()) {
  110. debugbr("TFAIL: $errmsg", DBG_SQL);
  111. }
  112. if ($this->mode == ROLLBACK_ON_FAIL) {
  113. $this->rollback();
  114. }
  115. }
  116. // Handle successful transactions..
  117. else {
  118. $RESPONSE->datasource->commit();
  119. if (debugging()) {
  120. debugbr("TOK: transaction committed.", DBG_SQL);
  121. }
  122. $tok = true;
  123. }
  124. // Always end up with it closed..
  125. $this->open = false;
  126. }
  127. return $tok;
  128. }
  129. // ....................................................................
  130. /**
  131. * Roll back transaction
  132. * Tell the database to roll back the transaction..
  133. */
  134. function rollback() {
  135. global $RESPONSE;
  136. if ($RESPONSE->db_backed && $this->open) {
  137. $RESPONSE->datasource->rollback();
  138. $errmsg = "transaction rolled back";
  139. error_log("TFAIL: " . APP_NAME . " $errmsg", 0);
  140. if (debugging()) {
  141. debugbr("TFAIL: $errmsg", DBG_SQL);
  142. }
  143. $this->open = false;
  144. }
  145. }
  146. } // transaction class
  147. // Instantiate a generic transaction to use..
  148.  
  149. $global_tran = new transaction();
  150.  
  151. // ----------------------------------------------------------------------
  152. /**
  153. * List of things class
  154. * Encapsulates lists of items. A general-purpose class for containing
  155. * lists of things. A utility class to hold lists of things like field
  156. * lists, lists of tablenbames, orderby lists, etc.
  157. * @package database
  158. * @access private
  159. */
  160. class listofthings {
  161. /** The list of things being held */
  162.  
  163. var $things;
  164. /** Total things we have */
  165.  
  166. var $total = 0;
  167. // ....................................................................
  168. /**
  169. * Constructor
  170. * Create a new listofthings object.
  171. */
  172. function listofthings() {
  173. $this->clear();
  174. }
  175. // ....................................................................
  176. /**
  177. * Add thing
  178. * @param string $thing The identifier of the thing we are adding
  179. * @param mixed $val The value of the thing we are adding
  180. */
  181. function add($thing, $val="") {
  182. $this->things[$thing] = $val;
  183. $this->total += 1;
  184. }
  185. // ....................................................................
  186. /**
  187. * Clear things
  188. * Clears all things from the list.
  189. */
  190. function clear() {
  191. if (isset($this->things)) unset($this->things);
  192. $this->total = 0;
  193. }
  194. // ....................................................................
  195. /**
  196. * Return list
  197. * @param string $delim The delimiter for the returned list
  198. * @return string The delimited list of names of things
  199. */
  200. function listed($delim=",") {
  201. $list = "";
  202. if (isset($this->things)) {
  203. reset($this->things);
  204. while (list($thing, $val) = each($this->things)) {
  205. $list .= "$thing~^";
  206. }
  207. $list = str_replace("~^", $delim, trim($list));
  208. if (substr($list, -1) == $delim) {
  209. $list = substr($list, 0, strlen($list) - 1);
  210. }
  211. }
  212. return $list;
  213. }
  214. // ....................................................................
  215. /**
  216. * Return values
  217. * @param string $delim The delimiter for the returned list
  218. * @return string The delimited list of values of things
  219. */
  220. function values($delim=",") {
  221. $list = "";
  222. if (isset($this->things)) {
  223. reset($this->things);
  224. while (list($thing, $value) = each($this->things)) {
  225. if ($value === "") $value = "''";
  226. $list .= "$value~^";
  227. }
  228. $list = str_replace("~^", $delim, trim($list));
  229. if (substr($list, -1) == $delim) {
  230. $list = substr($list, 0, strlen($list) - 1);
  231. }
  232. }
  233. return $list;
  234. }
  235. // ....................................................................
  236. /**
  237. * Return equates
  238. * Returns the things we contain in key=value format, and all
  239. * as a string delimited by the given character.
  240. * @param string $delim The delimiter for the returned list
  241. * @return string The delimited list of equated things
  242. */
  243. function equated($delim=",") {
  244. $list = "";
  245. if (isset($this->things)) {
  246. reset($this->things);
  247. while (list($thing, $value) = each($this->things)) {
  248. if ($value === "") $value = "''";
  249. $list .= "$thing=$value~^";
  250. }
  251. $list = str_replace("~^", $delim, trim($list));
  252. if (substr($list, -1) == $delim) {
  253. $list = substr($list, 0, strlen($list) - 1);
  254. }
  255. }
  256. return $list;
  257. }
  258. } // listofthings class
  259. // ----------------------------------------------------------------------
  260.  
  261. /**
  262. * SQLquery class
  263. * An SQL Statement Text Container.
  264. * This class is the parent of the main dbquery class which directs the
  265. * query to the database. It is mainly a container of SQL query text, in
  266. * the variable 'sql', but also offers a few basic methods for building
  267. * queries. For complex queries however, build your own in a string and
  268. * then just set the 'sql' variable.
  269. * @package database
  270. */
  271. class sqlquery {
  272. /** Type of query 'SELECT', 'DELETE', 'INSERT' or 'UPDATE' */
  273.  
  274. var $type = "";
  275. /** List of fields in the query */
  276.  
  277. var $fields;
  278. /** List of tables in the query */
  279.  
  280. var $tables;
  281. /** The query WHERE clause components */
  282.  
  283. var $where;
  284. /** The GROUP BY clause */
  285.  
  286. var $groupby;
  287. /** The ORDER BY clause */
  288.  
  289. var $orderby;
  290. /** The LIMIT value */
  291.  
  292. var $limit;
  293. /** The OFFSET value */
  294.  
  295. var $offset;
  296. /** The formatted SQL query itself @see build() */
  297.  
  298. var $sql = "";
  299. // ....................................................................
  300. /**
  301. * Constructor
  302. * Create a new SQL Query object.
  303. * @param string $sql The SQL statement in full
  304. */
  305. function sqlquery($sql="") {
  306. $this->clear();
  307. $this->sql = $sql;
  308. } // sqlquery
  309. // ....................................................................
  310. /**
  311. * Clear query - Wipe all of the current query definitions.
  312. */
  313. function clear() {
  314. if (isset($this->fields)) unset($this->fields);
  315. if (isset($this->tables)) unset($this->tables);
  316. if (isset($this->where)) unset($this->where);
  317. if (isset($this->groupby)) unset($this->groupby);
  318. if (isset($this->orderby)) unset($this->orderby);
  319. $this->fields = new listofthings();
  320. $this->tables = new listofthings();
  321. $this->where = new listofthings();
  322. $this->groupby = new listofthings();
  323. $this->orderby = new listofthings();
  324. $this->sql = "";
  325. $this->limit = 0;
  326. $this->offset = 0;
  327. } // clear
  328. // ....................................................................
  329. /**
  330. * Utility function to help building list of things
  331. * @param listofthings $list_of_things listofthings to add to
  332. * @param mixed $list A simple array or a delimited list
  333. * @param string $delim Delimiter, "," default
  334. * @access private
  335. */
  336. function addlist(&$list_of_things, $list, $delim=",") {
  337. if (is_array($list)) {
  338. $items = $list;
  339. }
  340. else {
  341. $items = explode($delim, $list);
  342. }
  343. // Add to our existing list..
  344. foreach ($items as $item) {
  345. if ($item != "") $list_of_things->add($item);
  346. }
  347. } // addlist
  348. // ....................................................................
  349. /**
  350. * Define field list
  351. * Add a list of fields to return in query. This is a cumulative function
  352. * which may be called more than once to add fields. You can specify the
  353. * list of fields either as an array, or as a delimited list. If the latter,
  354. * then default delimiter is a comma, unless you specify your own.
  355. * Applicable to SELECT, DELETE and UPDATE.
  356. * @param string $field_spec The field list to add to the query
  357. * @param string $delim The delimter you want to separate fields with
  358. */
  359. function fieldlist($field_spec="*", $delim=",") {
  360. $this->addlist($this->fields, $field_spec, $delim);
  361. } // fieldlist
  362. // ....................................................................
  363. /**
  364. * Define table list
  365. * Add the table specification to our list. This is a cumulative function
  366. * which may be called more than once to add tables. You can specify the
  367. * list of tables either as an array, or as a delimited list. If the latter,
  368. * then default delimiter is a comma, unless you specify your own.
  369. * @param string $table_spec The table list to add to the query
  370. * @param string $delim The delimiter you want to separate tables with
  371. */
  372. function tables($table_spec, $delim=",") {
  373. $this->addlist($this->tables, $table_spec, $delim);
  374. } // tables
  375. // ....................................................................
  376. /**
  377. * Define table FROM list
  378. * A nicer synonym for "tables()" for SELECT
  379. * @param string $table_spec The table list to add to the query
  380. * @param string $delim The delimiter you want to separate tables with
  381. */
  382. function from($table_spec, $delim=",") {
  383. $this->tables($table_spec, $delim);
  384. } // from
  385. // ....................................................................
  386. /**
  387. * Define table INSERT INTO list
  388. * A nicer synonym for "tables()" for INSERT
  389. * @param string $table_spec The table list to add to the query
  390. * @param string $delim The delimiter you want to separate tables with
  391. */
  392. function into($table_spec, $delim=",") {
  393. $this->tables($table_spec, $delim);
  394. } // into
  395. // ....................................................................
  396. /**
  397. * Define group by field list
  398. * The fields can be an array, or a delimited list. If the latter, then default delimiter is a comma,
  399. * unless you specify your own.
  400. * @param string $field_spec The field list to add to the GROUP BY. Do not include words "GROUP BY".
  401. * @param string $delim The delimiter you want to separate the fields with
  402. */
  403. function groupby($field_spec="", $delim=",") {
  404. $this->addlist($this->groupby, $field_spec, $delim);
  405. } // groupby
  406. // ....................................................................
  407. /**
  408. * Define order field list
  409. * Defines the Sort order field list. The fields can be an array, or a
  410. * delimited list. If the latter, then default delimiter is a comma,
  411. * unless you specify your own.
  412. * @param string $field_spec The field list to add to the ORDER BY. Do not include words "ORDER BY".
  413. * @param string $delim The delimiter you want to separate the fields with
  414. */
  415. function orderby($field_spec="", $delim=",") {
  416. $this->addlist($this->orderby, $field_spec, $delim);
  417. } // orderby
  418. // ....................................................................
  419. /**
  420. * Define query LIMIT
  421. * @param integer $limit Numeric value for limit rows to return. Do not include the word "LIMIT".
  422. * @param integer $offset Numeric value for start row. Do not include the word "OFFSET".
  423. */
  424. function limit($limit) {
  425. $this->limit = $limit;
  426. } // limit
  427. // ....................................................................
  428. /**
  429. * Define query OFFSET
  430. * @param integer $offset Numeric value for start row. Do not include the word "OFFSET".
  431. */
  432. function offset($offset) {
  433. $this->offset = $offset;
  434. } // set
  435. // ....................................................................
  436. /**
  437. * Define field assignments
  438. * Defines the field assignment clauses for UPDATE and INSERT queries.
  439. * @param string $field The name of the field to assign a value to
  440. * @param mixed $val The value to assign to the field. Processed according to type.
  441. */
  442. function set($field, $val) {
  443. global $RESPONSE;
  444. // Numerics are done without quotes
  445. if (is_int($val) || is_float($val)) {
  446. $this->fields->add($field, $val);
  447. }
  448. // Boolean formats dependent on database type..
  449. elseif (is_bool($val)) {
  450. $val = $RESPONSE->datasource->db_value_from_bool($val);
  451. if (!is_int($val)) $val = "'$val'";
  452. $this->fields->add($field, $val);
  453. }
  454. // Everything else is a quoted, escaped string..
  455. else {
  456. $val = trim($val);
  457. $bits = explode("::", $val);
  458. $val = $bits[0];
  459. if ($RESPONSE->multilang && $RESPONSE->mbstring_avail) {
  460. if (mb_substr($val, 0, 1) == "'") $val = mb_substr($val, 1);
  461. if (mb_substr($val, -1) == "'") $val = mb_substr($val, 0, strlen($val) - 1);
  462. }
  463. else {
  464. if (substr($val, 0, 1) == "'") $val = substr($val, 1);
  465. if (substr($val, -1) == "'") $val = substr($val, 0, strlen($val) - 1);
  466. }
  467. $val = addslashes($val);
  468. $this->fields->add($field, "'$val'");
  469. }
  470. } // set
  471. // ....................................................................
  472. /**
  473. * Add WHERE clause component
  474. * This function allows you to add a WHERE clause component. An example might
  475. * be something like: "AND c.foo='myval'". Either call this once with the whole
  476. * WHERE cluase string (minus the word "WHERE"), or multiple times with
  477. * parts of the where clause as in the example above.
  478. * @param string $where_clause A WHERE clause component, without the "WHERE".
  479. */
  480. function where($where_clause) {
  481. if ($where_clause != "") {
  482. $this->where->add($where_clause);
  483. }
  484. } // where
  485. // ....................................................................
  486. /**
  487. * This is useful when you change some part of the query after it has been
  488. * executed once, and want it to rebuild the SQL anew before it gets
  489. * executed again.
  490. */
  491. function rebuild() {
  492. $this->sql = "";
  493. $this->build();
  494. } // rebuild
  495. // ....................................................................
  496. /**
  497. * Build the SQL query
  498. * This takes the various components which have been added to the object
  499. * and parses them to build the full SQL statement which will be sent
  500. * to the server. The result is stored in $this->sql.
  501. * NOTE: this method calls the appropriate database-specific SQL
  502. * builder method.
  503. */
  504. function build() {
  505. global $RESPONSE;
  506. $this->sql = $RESPONSE->datasource->SQL($this);
  507. return $this->sql;
  508. } // build
  509.  
  510. } // sqlquery class
  511. // ----------------------------------------------------------------------
  512.  
  513. /**
  514. * DB Query class
  515. * This class is the one which executes queries against the
  516. * connected database.
  517. * @package database
  518. */
  519. class dbquery extends sqlquery {
  520. /** Number of rows returned after execute */
  521.  
  522. var $rowcount = 0;
  523. /** Number of rows affected by query */
  524.  
  525. var $affectedrowcount = 0;
  526. /** Current row in the query */
  527.  
  528. var $rowno = 0;
  529. /** Current row resource ID */
  530.  
  531. var $rid = false;
  532. /** True if query is valid, post execution */
  533.  
  534. var $valid = false;
  535. /** True if data was returned, after execute */
  536.  
  537. var $hasdata = false;
  538. /** Record last error/info message */
  539.  
  540. var $last_errormsg = "";
  541. // ....................................................................
  542. /**
  543. * Constructor
  544. * Create a new DB Query object.
  545. * @param string $sql An SQL statement in full
  546. */
  547. function dbquery($sql="") {
  548. $this->sqlquery($sql);
  549. return $this;
  550. } // dbquery
  551. // ....................................................................
  552. /**
  553. * Exceute the query
  554. * If we have an SQL phrase, execute it now. We store
  555. * the result in this->valid, and also return it. If
  556. * a transaction is open, update the status.
  557. * @return bool True if query was executed successfully
  558. */
  559. function execute() {
  560. global $RESPONSE;
  561.  
  562. // Head it off at the pass if the system is being run
  563. // standalone, or there is no defined datasource..
  564. if (!isset($RESPONSE->datasource) || !$RESPONSE->db_backed) {
  565. return false;
  566. }
  567.  
  568. global $global_tran;
  569. $this->rid = false;
  570. if ($this->sql == "") {
  571. $this->build();
  572. }
  573. if ($this->sql != "") {
  574. // Execute the query using low-level DB module..
  575. $this->rid = $RESPONSE->datasource->query($this->sql);
  576. // Now examine the result..
  577. if ($this->rid != false) {
  578. if (preg_match("/(^select|^\(select)/i", $this->sql)) {
  579. $this->rowcount = $RESPONSE->datasource->numrows($this->rid);
  580. }
  581. $this->rowno = 0;
  582. $this->hasdata = ($this->rowcount > 0);
  583. }
  584. else {
  585. // Log the failed query..
  586. $db_err = $RESPONSE->datasource->errormessage();
  587. if ($db_err) $errstr .= " DBSERVER: $db_err";
  588. $this->last_errormsg = $errstr;
  589. if (debugging()) {
  590. debugbr($errstr, DBG_SQL);
  591. }
  592. // Set failed status for any open transaction..
  593. if ($global_tran->open) {
  594. $global_tran->failed = true;
  595. $global_tran->failed_msg = $errstr;
  596. }
  597. }
  598. }
  599. $this->valid = ($this->rid != false);
  600. return $this->valid;
  601. } // execute
  602. // ....................................................................
  603. /**
  604. * Set the SQL statement
  605. * @param string $sql An SQL statement in full
  606. */
  607. function set_sql($sql) {
  608. $this->tidyup();
  609. $this->sql = $sql;
  610. return $this;
  611. } // set_sql
  612. // ....................................................................
  613. /**
  614. * Free resources.
  615. * Not really necessary, but you might be that fastidious kind of person.
  616. */
  617. function tidyup() {
  618. global $RESPONSE;
  619. if ($this->rid) {
  620. $RESPONSE->datasource->freeresult($this->rid);
  621. $this->clear();
  622. $this->rowcount = 0;
  623. $this->affectedrowcount = 0;
  624. $this->rid = false;
  625. $this->valid = false;
  626. $this->hasdata = false;
  627. }
  628. } // tidyup
  629.  
  630. } // dbquery class
  631. // ----------------------------------------------------------------------
  632.  
  633. /**
  634. * DB Rows class
  635. * Renders a query into data and allows access to the data either
  636. * directly or via the usual get first,last,next,previous cursor
  637. * navigation.
  638. * This class returns data as "rows" which is to say a standard
  639. * array of data. For the associative array version then please
  640. * @see dbrecords
  641. * NOTE: On creation, it executes the query and positions to the
  642. * initial record (defaulted to the first).
  643. * @package database
  644. */
  645. class dbrows extends dbquery {
  646. /** An array containing the current DB row */
  647.  
  648. var $current_row;
  649. // ....................................................................
  650. /**
  651. * Constructor
  652. * Create a new DB Rows object.
  653. * @param string $sql An SQL statement in full
  654. */
  655. function dbrows($sql="") {
  656. $this->dbquery($sql);
  657. if ($sql != "") {
  658. $this->execute();
  659. }
  660. } // dbrows
  661. // ....................................................................
  662. /**
  663. * Execute query
  664. * Execute this query. We override the parent method here
  665. * simply to ensure we are positioned at the first row.
  666. * @return bool True if query was executed successfully
  667. */
  668. function execute() {
  669. dbquery::execute();
  670. if ($this->valid) {
  671. $this->get_first();
  672. }
  673. return $this->valid;
  674. } // execute
  675. // ....................................................................
  676. /**
  677. * Set the SQL statement
  678. * In this case we re-execute the SQL automatically.
  679. * @param string $sql An SQL statement in full
  680. * @return bool True if query was executed successfully
  681. */
  682. function set_sql($sql) {
  683. $this->tidyup();
  684. $this->sql = $sql;
  685. return $this->execute();
  686. } // set_sql
  687. // ....................................................................
  688. /**
  689. * Get row raw
  690. * Return the given database row from the resultset. This method may
  691. * be over-ridden in subsequent child classes.
  692. * @param integer $rowno The row number to return
  693. * @return array True if row was available
  694. * @access private
  695. */
  696. function get_row_raw($rowno) {
  697. global $RESPONSE;
  698. if ($this->rid != false) {
  699. return $RESPONSE->datasource->fetch_row($this->rid, $rowno);
  700. }
  701. else return false;
  702. } // get_row_raw
  703. // ....................................................................
  704. /**
  705. * Get row
  706. * Return the given database row from the resultset. Uses the
  707. * get_row_raw() method applicable to this class.
  708. * @see get_row_raw()
  709. * @param integer $rowno The row number to return
  710. * @return mixed The row if it is available, else returns FALSE.
  711. */
  712. function get_row($rowno) {
  713. if ($this->valid && ($this->rowcount > 0)) {
  714. if ($rowno > ($this->rowcount - 1)) $rowno = $this->rowcount - 1;
  715. elseif ($rowno < 0) $rowno = 0;
  716. $this->current_row = $this->get_row_raw($rowno);
  717. if ($this->current_row !== false) {
  718. $this->rowno = $rowno;
  719. if (debugging()) {
  720. $errstr = "";
  721. for($i=0; $i < count($this->current_row); $i++) {
  722. if ($errstr != "") $errstr .= ", ";
  723. $errstr .= $this->current_row[$i];
  724. }
  725. //$errstr = var_dump($this->current_row);
  726. debugbr("QDATA: Row $rowno: $errstr", DBG_SQLDATA);
  727. }
  728. }
  729. else {
  730. debugbr("QDATA: Row $rowno: returned FALSE", DBG_SQLDATA);
  731. }
  732. }
  733. else {
  734. if (isset($this->current_row)) unset($this->current_row);
  735. $this->current_row = false;
  736. }
  737. return $this->current_row;
  738. } // get_row
  739. // ....................................................................
  740. /**
  741. * Returns true if the row number exists in the returned resultset.
  742. * The query has to be valid, and there have to be some rows in it.
  743. * @param integer $rowno Number of the row, zero (0) is first row
  744. * @return bool True if the row is present in the current resultset
  745. */
  746. function rowexists($rowno) {
  747. return (
  748. ($this->valid)
  749. && ($this->rowcount > 0)
  750. && ($rowno >= 0)
  751. && ($rowno <= ($this->rowcount - 1))
  752. );
  753. } // rowexists
  754. // ....................................................................
  755. /**
  756. * Refresh the query
  757. * Re-run the current SQL query. If successful the row will be stored
  758. * in $this->current_row.
  759. */
  760. function refresh() {
  761. $rowno = $this->rowno;
  762. $this->execute();
  763. $this->get_row($rowno);
  764. } // refresh
  765. // ....................................................................
  766. /**
  767. * Get current row
  768. * If current query is invalid, try to execute it first, then do a
  769. * get_first(). If query is then valid, return the current row.
  770. * @see get_first()
  771. * @return mixed The row if it is available, else returns FALSE.
  772. */
  773. function get_current() {
  774. if (!$this->valid) {
  775. $this->execute();
  776. $this->get_first();
  777. }
  778. return $this->current_row;
  779. } // get_current
  780. // ....................................................................
  781. /**
  782. * Get current row
  783. * If current query is invalid, try to execute it first, then do a
  784. * get_first(). If query is then valid, return the current row.
  785. * @see get_first()
  786. * @return mixed The row if it is available, else returns FALSE.
  787. */
  788. function get_first() {
  789. if (!$this->valid) $this->execute();
  790. return $this->get_row(0);
  791. } // get_first
  792. // ....................................................................
  793. /**
  794. * Get last row
  795. * If current query is invalid, try to execute it first, then get
  796. * the last row from the resultset.
  797. * @return mixed The row if it is available, else returns FALSE.
  798. */
  799. function get_last() {
  800. if (!$this->valid) $this->execute();
  801. return $this->get_row($this->rowcount - 1);
  802. } // get_last
  803. // ....................................................................
  804. /**
  805. * Get previous row
  806. * If current query is invalid, try to execute it first, then get
  807. * the previous row from the resultset.
  808. * @return mixed The row if it is available, else returns FALSE.
  809. */
  810. function get_previous() {
  811. if (!$this->valid) $this->execute();
  812. if ($this->rowno > 0) {
  813. return $this->get_row($this->rowno - 1);
  814. }
  815. else return false;
  816. } // get_previous
  817. // ....................................................................
  818. /**
  819. * Get next row
  820. * If current query is invalid, try to execute it first, then get
  821. * the next row from the resultset.
  822. * @return mixed The row if it is available, else returns FALSE.
  823. */
  824. function get_next() {
  825. if (!$this->valid) $this->execute();
  826. if ($this->rowno < ($this->rowcount - 1)) {
  827. return $this->get_row($this->rowno + 1);
  828. }
  829. else return false;
  830. } // get_next
  831. // ....................................................................
  832. /**
  833. * Return the EOF (end-of-file) indicator for this query. Returns
  834. * true if no more results can be returned with get_next(), ie. we
  835. * are at the end of the results set.
  836. * @return boolean True if we are at the end of the results set.
  837. */
  838. function eof() {
  839. if (!$this->valid) return true;
  840. else return ($this->rowno >= ($this->rowcount - 1));
  841. } // eof
  842.  
  843. } // dbrows class
  844. // ----------------------------------------------------------------------
  845.  
  846. /**
  847. * DB Records class
  848. * Renders a query into data and allows access to the data either
  849. * directly or via the usual get first,last,next,previous cursor
  850. * navigation.
  851. * This class returns data as an associative array and is thus
  852. * the most useful of all the data access methods. It extends the
  853. * dbrows class, and over-rides the get_row_raw method to retrieve
  854. * data.
  855. * @see dbrows.
  856. * @package database
  857. */
  858. class dbrecords extends dbrows {
  859. /**
  860. * Constructor
  861. * Create a new DB Records object.
  862. * @param string $sql An SQL statement in full
  863. */
  864. function dbrecords($sql="") {
  865. $this->dbrows($sql);
  866. } // dbrecords
  867. // ....................................................................
  868. /**
  869. * Get row raw
  870. * Return the given database row from the resultset. This over-rides
  871. * the parent method of the same name and returns an array.
  872. * @param integer $rowno The row number to return
  873. * @return array True if row was available
  874. * @access private
  875. */
  876. function get_row_raw($rowno) {
  877. global $RESPONSE;
  878. if ($this->rid) {
  879. return $RESPONSE->datasource->fetch_array($this->rid, $rowno);
  880. }
  881. else return false;
  882. } // get_row_raw
  883. // ....................................................................
  884. /**
  885. * Get field content
  886. * Return the field content from the current database array (row).
  887. * Does not provide ANY pre/post-processing.
  888. * @param string $fieldname The name of the field to return value of
  889. * @return mixed Value of the named field
  890. */
  891. function rawfield($fieldname) {
  892. global $RESPONSE;
  893. // Intercept any errant querying in standalone mode..
  894. if (!$RESPONSE->db_backed) return "";
  895. if ($this->rid) {
  896. $value = $this->current_row[$fieldname];
  897. return $value;
  898. }
  899. else return false;
  900. } // rawfield
  901. // ....................................................................
  902. /**
  903. * Get field content
  904. * Return the field content from the current database array (row).
  905. * If the value is a string, then stripslashes is done automatically.
  906. * @param string $fieldname The name of the field to return value of
  907. * @return mixed Value of the named field
  908. */
  909. function field($fieldname) {
  910. global $RESPONSE;
  911. // Intercept any errant querying in standalone mode..
  912. if (!$RESPONSE->db_backed) return "";
  913. if ($this->rid) {
  914. $value = $this->rawfield($fieldname);
  915. if (is_string($value)) {
  916. $value = stripslashes($value);
  917. }
  918. return $value;
  919. }
  920. else return false;
  921. } // field
  922. // ....................................................................
  923. /**
  924. * Database independent boolean handling. Returns TRUE if the named
  925. * field in the current row is boolean true according to the rules of the
  926. * underlying database, else returns FALSE.
  927. * @param string $fieldname The name of the field to return boolean value of
  928. * @return boolean True if field contains database-dependent true value
  929. */
  930. function istrue($fieldname) {
  931. global $RESPONSE;
  932. $value = $this->field($fieldname);
  933. return $RESPONSE->datasource->bool_from_db_value($value);
  934. } // istrue
  935.  
  936. } // dbrecords class
  937. // ----------------------------------------------------------------------
  938. // SPECIFIC DBQUERY TYPES..
  939. // Wrappers which save you specifying some variables, when instantiating
  940. // a new 'dbquery' object that's all..
  941.  
  942. /**
  943. * DB Select class
  944. * A special case of the dbrecords class.
  945. * @package database
  946. */
  947. class dbselect extends dbrecords {
  948. /**
  949. * Constructor
  950. * Create a new DB Select object. This is for selecting rows from
  951. * the database, and returning fields from those rows.
  952. * @param string $table Table(s) to run select on
  953. */
  954. function dbselect($table="") {
  955. $this->dbrecords();
  956. $this->type = "SELECT";
  957. if ($table != "") {
  958. $this->from($table);
  959. }
  960. } // dbselect
  961.  
  962. } // dbselect class
  963. // ----------------------------------------------------------------------
  964.  
  965. /**
  966. * DB Delete class
  967. * A special case of the dbquery class. This is for deleting
  968. * rows from the database.
  969. * @package database
  970. */
  971. class dbdelete extends dbquery {
  972. /**
  973. * Constructor
  974. * Create a new DB Delete object.
  975. * @param string $table Table to delete rows from.
  976. */
  977. function dbdelete($table="") {
  978. $this->dbquery();
  979. $this->type = "DELETE";
  980. if ($table != "") {
  981. $this->into($table);
  982. }
  983. } // dbdelete
  984.  
  985. } // dbdelete class
  986. // ----------------------------------------------------------------------
  987.  
  988. /**
  989. * DB tablemod class
  990. * Parent class for classes which only modify a single table. This
  991. * means either update or inserts. This class is provided so we can
  992. * define a common method for sequence definition.
  993. * @package database
  994. * @abstract
  995. */
  996. class dbtablemod extends dbquery {
  997. /**
  998. * Constructor
  999. * Create a new DB Insert object. This is for inserting
  1000. * a record into the database.
  1001. * @param string $table Table to modify, mandatory parameter.
  1002. */
  1003. function dbtablemod($table) {
  1004. $this->dbquery();
  1005. $this->tables($table);
  1006. }
  1007. // ....................................................................
  1008. /**
  1009. * Set the next sequence value for a column, using either a named
  1010. * sequence or, if that is nullstring or the underlying DB does
  1011. * not support sequences, other means. See the next_sequencevalue()
  1012. * method in the underlying DB module db-xxxx.php.
  1013. */
  1014. function next_sequencevalue($sequencename, $column) {
  1015. global $RESPONSE;
  1016. $nextseq = $RESPONSE->datasource->next_sequencevalue(
  1017. $sequencename,
  1018. $this->tables->listed(),
  1019. $column
  1020. );
  1021. $this->set($column, $nextseq);
  1022. }
  1023. }
  1024. // ----------------------------------------------------------------------
  1025. /**
  1026. * DB Insert class
  1027. * A special case of the dbtablemod class.
  1028. * @package database
  1029. */
  1030. class dbinsert extends dbtablemod {
  1031. /**
  1032. * Constructor
  1033. * Create a new DB Insert object. This is for inserting
  1034. * a record into the database.
  1035. * @param string $table Table to insert into
  1036. */
  1037. function dbinsert($table) {
  1038. $this->dbtablemod($table);
  1039. $this->type = "INSERT";
  1040. } // dbinsert
  1041.  
  1042. } // dbinsert class
  1043. // ----------------------------------------------------------------------
  1044.  
  1045. /**
  1046. * DB Update class
  1047. * A special case of the dbquery class. This is for updating data in
  1048. * particular rows in the database.
  1049. * @package database
  1050. */
  1051. class dbupdate extends dbtablemod {
  1052. /**
  1053. * Constructor
  1054. * Create a new DB Select object.
  1055. * @param string $table Table to update
  1056. */
  1057. function dbupdate($table) {
  1058. $this->dbtablemod($table);
  1059. $this->type = "UPDATE";
  1060. } // dbupdate
  1061.  
  1062. } // dbupdate class
  1063. // ----------------------------------------------------------------------
  1064.  
  1065. /**
  1066. * DB seq class
  1067. * A class which allows the management and use of sequences.
  1068. * @package database
  1069. */
  1070. class dbseq extends dbquery {
  1071. // Public
  1072. // Private
  1073. /** The name of the sequence
  1074. @access private */
  1075. var $sequencename = "";
  1076. // ....................................................................
  1077. /**
  1078. * Create a new object to manage a sequence, optionally
  1079. * specifying the sequence name..
  1080. * @param string $sequencename Name of the sequence to manage
  1081. */
  1082. function dbseq($sequencename) {
  1083. $this->sequencename = $sequencename;
  1084. $this->dbquery();
  1085. } // dbseq
  1086. // ....................................................................
  1087. /**
  1088. * Get the next sequence value. We can optionally specify the table and
  1089. * column associated with it. The requirement for these parameters is in fact
  1090. * implementation-specific. If your underlying database does not support
  1091. * named sequences, then you will probably have to nominate the table/column
  1092. * so that the low-level DB access module can do a MAX() to obtain the next
  1093. * value. If it does upport tham then you probably only need the sequence
  1094. * name as specified in the constructor.
  1095. * @param string $table Name of the table associated with this sequence
  1096. * @param string $column Name of the column associated with this sequence
  1097. * @return integer The value of the next integer in this sequence
  1098. */
  1099. function next_sequencevalue($table="", $column="") {
  1100. global $RESPONSE;
  1101. return $RESPONSE->datasource->next_sequencevalue($this->sequencename, $table, $column);
  1102. } // next_sequencevalue
  1103. // ....................................................................
  1104. /**
  1105. * Get the current sequence value.
  1106. * @param string $table Name of the table associated with this sequence
  1107. * @param string $column Name of the column associated with this sequence
  1108. * @return integer The current sequence value
  1109. */
  1110. function current_sequencevalue($table="", $column="") {
  1111. global $RESPONSE;
  1112. return $RESPONSE->datasource->current_sequencevalue($this->sequencename, $table, $column);
  1113. } // current_sequencevalue
  1114. // ....................................................................
  1115. /**
  1116. * Set a sequence value.
  1117. * @param integer $newval New integer value to set sequence to
  1118. * @param string $table Name of the table associated with this sequence
  1119. * @param string $column Name of the column associated with this sequence
  1120. */
  1121. function set_sequencevalue($newval, $table="", $column="") {
  1122. global $RESPONSE;
  1123. return $RESPONSE->datasource->set_sequencevalue($newval, $this->sequencename, $table, $column);
  1124. } // set_sequencevalue
  1125.  
  1126. } // dbseq class
  1127. // ######################################################################
  1128. // Utility functions..
  1129.  
  1130. /**
  1131. * Execute a DB command
  1132. * A wrapper which caters for the 'command' type of SQL
  1133. * query where no results are reauired, such as for a
  1134. * DELETE or UPDATE, or INSERT etc. Returns true if all
  1135. * ok, otherwise returns false.
  1136. * @param string $sql An SQL statement in full
  1137. * @return bool True if dbcommand succeeded
  1138. */
  1139. function dbcommand($sql) {
  1140. $q = new dbquery($sql);
  1141. $res = $q->execute();
  1142. return $res;
  1143. } // dbcommand
  1144. // ......................................................................
  1145.  
  1146. /**
  1147. * A wrapper which caters for queries which will return
  1148. * a record set identifier for returning data.
  1149. * @param string $sql An SQL statement in full
  1150. * @return resource Returns a resource ID for the recordset
  1151. */
  1152. function dbrecordset($sql) {
  1153. $res = new dbrecords($sql);
  1154. return $res;
  1155. } // dbrecordset
  1156. // ......................................................................
  1157.  
  1158. /**
  1159. * A wrapper to get the next sequence value from a named sequence..
  1160. * @param string $sequencename Name of the sequence
  1161. * @param string $column Name of the column sequence is on
  1162. * @param string $table Name of the table column is on
  1163. * @return integer The value of the next integer in this sequence
  1164. */
  1165. function get_next_sequencevalue($sequencename, $table="", $column="") {
  1166. $seq = new dbseq($sequencename);
  1167. return $seq->next_sequencevalue($table, $column);
  1168. } // get_next_sequencevalue
  1169. // ......................................................................
  1170. // TRANSACTION Functions
  1171.  
  1172. /**
  1173. * Start a DB transaction. Alias for begin_transaction()
  1174. * @see begin_transaction()
  1175. */
  1176. function start_transaction() {
  1177. return begin_transaction();
  1178. } // start_transaction
  1179. // ......................................................................
  1180.  
  1181. /**
  1182. * Begin a DB transaction
  1183. */
  1184. function begin_transaction() {
  1185. global $global_tran;
  1186. $result = $global_tran->begin();
  1187. return $result;
  1188. } // begin_transaction
  1189. // ......................................................................
  1190.  
  1191. /**
  1192. * Return DB transaction failure status.
  1193. * @return bool True if transaction failed
  1194. */
  1195. function transaction_failed() {
  1196. global $global_tran;
  1197. return $global_tran->failed;
  1198. } // transaction_failed
  1199. // ......................................................................
  1200.  
  1201. /**
  1202. * Return DB transaction success status.
  1203. * @return bool True if transaction succeeded
  1204. */
  1205. function transaction_succeeded() {
  1206. return !transaction_failed();
  1207. } // transaction_succeeded
  1208. // ......................................................................
  1209.  
  1210. /**
  1211. * Return DB transaction open status.
  1212. * @return bool True if transaction already open
  1213. */
  1214. function transaction_open() {
  1215. global $global_tran;
  1216. return $global_tran->open;
  1217. } // transaction_open
  1218. // ......................................................................
  1219.  
  1220. /**
  1221. * Commit a DB transaction
  1222. * @return bool True if transaction committed
  1223. */
  1224. function commit() {
  1225. global $global_tran;
  1226. $result = $global_tran->commit();
  1227. return $result;
  1228. } // commit
  1229. // ......................................................................
  1230.  
  1231. /**
  1232. * Rollback a DB transaction
  1233. * @return bool True if transaction rolled back
  1234. */
  1235. function rollback() {
  1236. global $global_tran;
  1237. $result = $global_tran->rollback();
  1238. return $result;
  1239. } // rollback
  1240. // ----------------------------------------------------------------------
  1241. // LOCKING
  1242.  
  1243. /**
  1244. * Take out a lock on a table or tables, in a given mode. The mode string
  1245. * is database-specific and will vary according to the implementation
  1246. * of its locking scheme.
  1247. * @param string $tablelist List of tables to lock, comma-delimited
  1248. * @param string $mode Databes-specific locking-mode or type
  1249. */
  1250. function lock($tablelist, $mode) {
  1251. global $RESPONSE;
  1252. return $RESPONSE->datasource->lock($tablelist, $mode);
  1253. } // lock
  1254. ?>

Documentation generated by phpDocumentor 1.3.0RC3