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

Documentation generated by phpDocumentor 1.3.0RC3