Merge ../butv10/core/framework
[isso.git] / Db.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
5 || # Copyright (c)2005-2008 Blue Static
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version 2 of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Abstract Database Layer (Db.php)
24 *
25 * @package ISSO
26 */
27
28 require_once(ISSO . '/Functions.php');
29
30 /**
31 * Abstract Database Layer
32 *
33 * This class provides an abstract template for all RDBMS layers. All
34 * ISSO abstraction layers should inherit this class. It provides error
35 * reporting, SQL analysis, and general connection functionality.
36 *
37 * Constants:
38 * ISSO_SHOW_QUERIES_LIVE - Show queries in page output as they are sent
39 *
40 * @author Blue Static
41 * @copyright Copyright (c)2005 - 2008, Blue Static
42 * @package ISSO
43 *
44 */
45 abstract class BSDb
46 {
47 /**
48 * Determines whether or not errors should be shown
49 * @var bool
50 */
51 public $showerrors = true;
52
53 /**
54 * Current error number
55 * @var integer
56 */
57 protected $errnum = 0;
58
59 /**
60 * Description of current error
61 * @var string
62 */
63 protected $errstr = '';
64
65 /**
66 * Currend open database connection
67 * @var integer
68 */
69 protected $dblink = null;
70
71 /**
72 * Current query ID
73 * @var integer
74 */
75 protected $result = null;
76
77 /**
78 * Current query string
79 * @var string
80 */
81 protected $querystr = '';
82
83 /**
84 * History of all executed queryies
85 * @var array
86 */
87 protected $history = array();
88
89 /**
90 * Returns the history information array
91 *
92 * @return array History record
93 */
94 public function getHistory()
95 {
96 return $this->history;
97 }
98
99 /**
100 * Connect to a the specified database
101 *
102 * @param string Server name
103 * @param string User name
104 * @param string Password
105 * @param string Database name
106 *
107 * @return bool Result of connect
108 */
109 public function connect($server, $user, $password, $database)
110 {
111 if ($this->dblink == false)
112 {
113 $this->dblink = $this->_connect($server, $user, $password, $database);
114
115 if ($this->dblink == false)
116 {
117 throw new BSDbException('Connect Failed', -1, 'DB-Link == false; connect failed');
118 return false;
119 }
120
121 return true;
122 }
123 }
124
125 /**
126 * Abstract function that returns a database link after establishing a connection. This just
127 * calls the function and does not do any checking
128 *
129 * @param string Server name
130 * @param string User name
131 * @param string Password
132 * @param string Database name
133 *
134 * @return integer Database link
135 */
136 protected abstract function _connect($server, $user, $password, $database);
137
138 /**
139 * Send a query to the open database link
140 *
141 * @param string Query string
142 *
143 * @return BSDbResult Result object, or NULL
144 */
145 public function query($string)
146 {
147 $time = microtime();
148
149 $this->querystr = $string;
150 $this->result = $this->_query($string);
151
152 if (!$this->result)
153 {
154 throw new BSDbException($this->_errorString(), $this->_errorNumber(), $string);
155 }
156
157 $this->history[] = $history = array('query' => $string, 'time' => BSFunctions::fetch_microtime_diff($time), 'trace' => BSFunctions::format_backtrace(debug_backtrace()));
158
159 if (defined('ISSO_SHOW_QUERIES_LIVE'))
160 {
161 if (constant('ISSO_SHOW_QUERIES_LIVE'))
162 {
163 print($this->_constructDebugQuery($history));
164 }
165 }
166
167 if (strtoupper(substr(trim($string), 0, 6)) == 'SELECT')
168 {
169 $class = get_class($this) . 'Result';
170 return new $class($this->result);
171 }
172 }
173
174 /**
175 * Abstract function that executes the query command on the database
176 *
177 * @param string Query string
178 *
179 * @return integer Result ID
180 */
181 protected abstract function _query($query);
182
183 /**
184 * Escape a string (depending on character set, if supported)
185 *
186 * @param string String to be escaped
187 *
188 * @return string Escaped string
189 */
190 public function escapeString($string)
191 {
192 return $this->_escapeString($string);
193 }
194
195 /**
196 * Abstract function that calls the escape_string() method
197 *
198 * @param string String to escape
199 *
200 * @return string Escaped string
201 */
202 protected abstract function _escapeString($string);
203
204 /**
205 * Escapes a binary string for insertion into the database
206 *
207 * @param string Unescaped data
208 *
209 * @return string Escaped binary data
210 */
211 public function escapeBinary($binary)
212 {
213 return $this->_escapeBinary($binary);
214 }
215
216 /**
217 * Abstract function that calls escape_binary()
218 *
219 * @param string Binary to escape
220 *
221 * @return string Escaped binary
222 */
223 protected abstract function _escapeBinary($string);
224
225 /**
226 * Unescapes a binary string that was fetched from the database
227 *
228 * @param string Escaped data
229 *
230 * @return string Unescaped binary data
231 */
232 public function unescapeBinary($binary)
233 {
234 return $this->_unescapeBinary($binary);
235 }
236
237 /**
238 * Abstract function that calls unescape_binary()
239 *
240 * @param string Escaped data
241 *
242 * @return string Data that has been unescaped
243 */
244 protected abstract function _unescapeBinary($string);
245
246 /**
247 * Send a query and return the first row of the results
248 *
249 * @param string Query string
250 * @param string Result return function (in the database layer)
251 *
252 * @return mixed Results in variable formats
253 */
254 public function queryFirst($string, $callback = 'fetchArray')
255 {
256 $resource = $this->query($string);
257 if ($resource)
258 {
259 $return = $resource->$callback();
260 $resource->free();
261 return $return;
262 }
263 else
264 {
265 return false;
266 }
267 }
268
269 /**
270 * Returns the errror number
271 */
272 public abstract function _errorNumber();
273
274 /**
275 * Returns the error string
276 */
277 public abstract function _errorString();
278
279 /**
280 * Fetch the unique ID of the record just inserted
281 *
282 * @return integer Insert-ID
283 */
284 public function insertId()
285 {
286 return $this->_insertID();
287 }
288
289 /**
290 * Abstract function that returns the ID of the most recently-inserted
291 * record
292 *
293 * @return integer Insertion ID
294 */
295 protected abstract function _insertId();
296
297 /**
298 * Fetch the number of rows affected by the query
299 *
300 * @param integer Result
301 *
302 * @return integer Number of affected rows
303 */
304 public function affectedRows()
305 {
306 return $this->_affectedRows($this->result);
307 }
308
309 /**
310 * Abstract function that returns the number of affected rows in the result
311 *
312 * @param integer Result ID
313 *
314 * @return integer Number of rows
315 */
316 protected abstract function _affectedRows($result);
317
318 /**
319 * Sends the command to start a transaction. This command should never
320 * be reached as it's always overridden
321 */
322 public abstract function begin();
323
324 /**
325 * Sends the command to rollback to a given savepoint. This command
326 * should never be reached as it's always overridden
327 *
328 * @param string Named savepoint
329 */
330 public abstract function rollback();
331
332 /**
333 * Sends the command to commit the entire transaction. This command
334 * should never be reached as it's always overridden
335 */
336 public abstract function commit();
337 }
338
339 /**
340 * Database Result
341 *
342 * This class holds result information for a database result
343 *
344 * @author rsesek
345 * @copyright Copyright (c)2005 - 2008, Blue Static
346 * @package ISSO
347 *
348 */
349 abstract class BSDbResult
350 {
351 /**
352 * The result resource
353 * @var resource
354 */
355 private $result;
356
357 /**
358 * Sets the resource and returns a result object
359 *
360 * @param resource The result of the query
361 */
362 public function __construct($result)
363 {
364 $this->result = $result;
365 }
366
367 /**
368 * Fetch the query result as an array
369 *
370 * @param integer Result
371 * @param bool Return an associative array?
372 *
373 * @return array A row of the query result
374 */
375 public function fetchArray($assoc = true)
376 {
377 return $this->{($assoc ? '_fetchAssocArray' : '_fetchRowArray')}($this->result);
378 }
379
380 /**
381 * Abstract function that returns an associative array of given result
382 *
383 * @param integer Result
384 *
385 * @return array Result array
386 */
387 protected abstract function _fetchAssocArray($result);
388
389 /**
390 * Abstract function that returns a row array of given result
391 *
392 * @param integer Result
393 *
394 * @return array Result array
395 */
396 protected abstract function _fetchRowArray($result);
397
398 /**
399 * Fetch the query result as an object
400 *
401 * @param integer Result
402 *
403 * @return object An object with the query result
404 */
405 public function fetchObject()
406 {
407 return $this->_fetchObject($this->result);
408 }
409
410 /**
411 * Abstract function that returns an object for a given result
412 *
413 * @param integer Result
414 *
415 * @return object Row object
416 */
417 public abstract function _fetchObject($result);
418
419 /**
420 * Free the current query result
421 *
422 * @param integer Result
423 */
424 public function free()
425 {
426 $this->_freeResult($this->result);
427 }
428
429 /**
430 * Abstract function that frees a given result
431 *
432 * @param integer Result ID
433 */
434 protected abstract function _freeResult($result);
435
436 /**
437 * Fetch the number of rows in the result
438 *
439 * @param integer Result
440 *
441 * @return integer Number of rows
442 */
443 public function size()
444 {
445 return $this->_numRows($this->result);
446 }
447
448 /**
449 * Abstract function that returns the number of rows in the result
450 *
451 * @param integer Result ID
452 *
453 * @return integer Number of rows
454 */
455 protected abstract function _numRows($result);
456 }
457
458 /**
459 * Database Exception
460 *
461 * Exception handler class for the database classes
462 *
463 * @author Blue Static
464 * @copyright Copyright (c)2005 - 2008, Blue Static
465 * @package ISSO
466 *
467 */
468 class BSDbException extends Exception
469 {
470 /**
471 * The query string that caused the error
472 * @var string
473 */
474 private $query;
475
476 /**
477 * Initializes a new database exception
478 *
479 * @param string The error message
480 * @param ineger MySQL error code
481 * @param sring Query string that caused the error
482 */
483 public function __construct($error, $errorNum, $query)
484 {
485 $this->query = $query;
486 parent::__construct($error, $errorNum);
487 }
488
489 /**
490 * Returns the query that failed
491 *
492 * @return string
493 */
494 public function getQuery()
495 {
496 return $this->query;
497 }
498 }
499
500 ?>