[AwlDatabase] Make attempt to nest transactions a fatal error.
[awl.git] / inc / AwlDatabase.php
blob74b4295ec1612e10566f96f7609c4746aceb5f15
1 <?php
2 /**
3 * AwlDatabase query/statement class and associated functions
5 * This subpackage provides some functions that are useful around database
6 * activity and a AwlDBDialect, AwlDatabase and AwlStatement classes to simplify
7 * handling of database queries and provide some access for a limited
8 * ability to handle varying database dialects.
10 * The class is intended to be a very lightweight wrapper with some features
11 * that have proved useful in developing and debugging web-based applications:
12 * - All queries are timed, and an expected time can be provided.
13 * - Parameters replaced into the SQL will be escaped correctly in order to
14 * minimise the chances of SQL injection errors.
15 * - Queries which fail, or which exceed their expected execution time, will
16 * be logged for potential further analysis.
17 * - Debug logging of queries may be enabled globally, or restricted to
18 * particular sets of queries.
19 * - Simple syntax for iterating through a result set.
21 * See http://wiki.davical.org/w/AwlDatabase for design and usage information.
23 * If not already connected, AwlDatabase will attempt to connect to the database,
24 * successively applying connection parameters from the array in $c->pdo_connect.
26 * We will die if the database is not currently connected and we fail to find
27 * a working connection.
29 * @package awl
30 * @subpackage AwlDatabase
31 * @author Andrew McMillan <andrew@morphoss.com>
32 * @copyright Morphoss Ltd
33 * @license http://gnu.org/copyleft/gpl.html GNU GPL v3 or later
34 * @compatibility Requires PHP 5.1 or later
37 require_once('AwlDBDialect.php');
39 if ( !defined('E_USER_ERROR') ) define('E_USER_ERROR',256);
42 /**
43 * Methods in the AwlDBDialect class which we inherit, include:
44 * __construct()
45 * SetSearchPath( $search_path )
46 * GetVersion()
47 * GetFields( $tablename_string )
48 * TranslateSQL( $sql_string )
49 * Quote( $value, $value_type = null )
50 * ReplaceParameters( $query_string [, param [, ...]] )
54 /**
55 * Typically there will only be a single instance of the database level class in an application.
56 * @package awl
58 class AwlDatabase extends AwlDBDialect {
59 /**#@+
60 * @access private
63 /**
64 * Holds the state of the transaction 0 = not started, 1 = in progress, -1 = error pending rollback/commit
66 protected $txnstate = 0;
68 /**
69 * Holds whether we are translating all statements.
71 protected $translate_all = false;
73 /**#@-*/
75 /**
76 * Returns a PDOStatement object created using this database, the supplied SQL string, and any parameters given.
77 * @param string $sql_query_string The SQL string containing optional variable replacements
78 * @param array $driver_options PDO driver options to the prepare statement, commonly to do with cursors
80 function prepare( $statement, $driver_options = array() ) {
81 if ( isset($this->translate_all) && $this->translate_all ) {
82 $statement = $this->TranslateSQL( $statement );
84 return $this->db->prepare( $statement, $driver_options );
88 /**
89 * Returns a PDOStatement object created using this database, the supplied SQL string, and any parameters given.
90 * @param string $sql_query_string The SQL string containing optional variable replacements
91 * @param mixed ... Subsequent arguments are positionally replaced into the $sql_query_string
93 function query( $statement ) {
94 return $this->db->query( $statement );
98 /**
99 * Begin a transaction.
101 function Begin() {
102 if ( $this->txnstate == 0 ) {
103 $this->db->beginTransaction();
104 $this->txnstate = 1;
106 else {
107 fatal("Cannot begin a transaction while a transaction is already active.");
109 return true;
114 * Complete a transaction.
116 function Commit() {
117 if ( $this->txnstate != 0 ) {
118 $this->db->commit();
119 $this->txnstate = 0;
121 return true;
126 * Cancel a transaction in progress.
128 function Rollback() {
129 if ( $this->txnstate != 0 ) {
130 $this->db->rollBack();
131 $this->txnstate = 0;
133 else {
134 trigger_error("Cannot rollback unless a transaction is already active.",E_USER_ERROR);
136 return true;
141 * Returns the current state of a transaction, indicating if we have begun a transaction, whether the transaction
142 * has failed, or if we are not in a transaction.
143 * @return int 0 = not started, 1 = in progress, -1 = error pending rollback/commit
145 function TransactionState() {
146 return $this->txnstate;
151 * Operates identically to AwlDatabase::Prepare, except that $this->Translate() will be called on the query
152 * before any processing.
154 function PrepareTranslated( $statement, $driver_options = array() ) {
155 $statement = $this->TranslateSQL( $statement );
156 return $this->prepare( $statement, $driver_options );
161 * Switches on or off the processing flag controlling whether subsequent calls to AwlDatabase::Prepare are translated
162 * as if PrepareTranslated() had been called.
164 function TranslateAll( $onoff_boolean ) {
165 $this->translate_all = $onoff_boolean;
166 return $onoff_boolean;
173 function ErrorInfo() {
174 return $this->db->errorInfo();