CWIS Developer Documentation

- Home
- Main Page
- Classes
- Files

- File List
- File Members

Axis--Database.php
Go to the documentation of this file.
1 <?PHP
2
3 #
4 # Axis--Database.php
5 # A Simple SQL Database Abstraction Object
6 #
7 # Copyright 1999-2002 Axis Data
8 # This code is free software that can be used or redistributed under the
9 # terms of Version 2 of the GNU General Public License, as published by the
10 # Free Software Foundation (http://www.fsf.org).
11 #
12 # Author: Edward Almasy (almasy@axisdata.com)
13 #
14 # Part of the AxisPHP library v1.2.5
15 # For more information see http://www.axisdata.com/AxisPHP/
16 #
17
22 class Database {
23
24 # ---- PUBLIC INTERFACE --------------------------------------------------
25 /*@(*/
27
40 function Database(
41 $UserName = NULL, $Password = NULL, $DatabaseName = NULL, $HostName = NULL)
42 {
43 # save DB access parameter values
44 $this->DBUserName = $UserName ? $UserName : self::$GlobalDBUserName;
45 $this->DBPassword = $Password ? $Password : self::$GlobalDBPassword;
46 $this->DBHostName = $HostName ? $HostName :
47 (isset(self::$GlobalDBHostName) ? self::$GlobalDBHostName
48 : "localhost");
49 $this->DBName = $DatabaseName ? $DatabaseName : self::$GlobalDBName;
50
51 # if we don't already have a connection or DB access parameters were supplied
52 $HandleIndex = $this->DBHostName.":".$this->DBName;
53 if (!array_key_exists($HandleIndex, self::$ConnectionHandles)
54 || $UserName || $Password || $DatabaseName || $HostName)
55 {
56 # open connection to DB server
57 self::$ConnectionHandles[$HandleIndex] = mysql_connect(
58 $this->DBHostName, $this->DBUserName,
59 $this->DBPassword, TRUE)
60 or die("Could not connect to database: ".mysql_error());
61
62 # set local connection handle
63 $this->Handle = self::$ConnectionHandles[$HandleIndex];
64
65 # select DB
66 mysql_select_db($this->DBName, $this->Handle)
67 or die(mysql_error($this->Handle));
68 }
69 else
70 {
71 # set local connection handle
72 $this->Handle = self::$ConnectionHandles[$HandleIndex];
73 }
74 }
75
80 function __sleep()
81 {
82 return array("DBUserName", "DBPassword", "DBHostName", "DBName");
83 }
87 function __wakeup()
88 {
89 # open connection to DB server
90 $this->Handle = mysql_connect(
91 $this->DBHostName, $this->DBUserName, $this->DBPassword)
92 or die("could not connect to database");
93
94 # select DB
95 mysql_select_db($this->DBName, $this->Handle)
96 or die(mysql_error($this->Handle));
97 }
107 static function SetGlobalServerInfo($UserName, $Password, $HostName = "localhost")
108 {
109 # save default DB access parameters
110 self::$GlobalDBUserName = $UserName;
111 self::$GlobalDBPassword = $Password;
112 self::$GlobalDBHostName = $HostName;
113
114 # clear any existing DB connection handles
115 self::$ConnectionHandles = array();
116 }
117
122 static function SetGlobalDatabaseName($DatabaseName)
123 {
124 # save new default DB name
125 self::$GlobalDBName = $DatabaseName;
126
127 # clear any existing DB connection handles
128 self::$ConnectionHandles = array();
129 }
130
135 function SetDefaultStorageEngine($Engine)
136 {
137 # choose config variable to use based on server version number
138 $ConfigVar = version_compare($this->GetServerVersion(), "5.5", "<")
139 ? "storage_engine" : "default_storage_engine";
140
141 # set storage engine in database
142 $this->Query("SET ".$ConfigVar." = ".$Engine);
143 }
144
149 function GetServerVersion()
150 {
151 # retrieve version string
152 $Version = $this->Query("SELECT VERSION() AS ServerVer", "ServerVer");
153
154 # strip off any build/config suffix
155 $Pieces = explode("-", $Version);
156 $Version = array_shift($Pieces);
157
158 # return version number to caller
159 return $Version;
160 }
161
167 function DBHostName() { return $this->DBHostName; }
168
174 function DBName() { return $this->DBName; }
175
181 function DBUserName() { return $this->DBUserName; }
182
190 static function Caching($NewSetting = NULL)
191 {
192 # if cache setting has changed
193 if (($NewSetting !== NULL) && ($NewSetting != self::$CachingFlag))
194 {
195 # save new setting
196 self::$CachingFlag = $NewSetting;
197
198 # clear any existing cached results
199 self::$QueryResultCache = array();
200 }
201
202 # return current setting to caller
203 return self::$CachingFlag;
204 }
205
216 static function AdvancedCaching($NewSetting = NULL)
217 {
218 if ($NewSetting !== NULL)
219 {
220 self::$AdvancedCachingFlag = $NewSetting;
221 }
222 return self::$AdvancedCachingFlag;
223 }
224
244 function SetQueryErrorsToIgnore($ErrorsToIgnore, $NormalizeWhitespace = TRUE)
245 {
246 if ($NormalizeWhitespace && ($ErrorsToIgnore !== NULL))
247 {
248 $RevisedErrorsToIgnore = array();
249 foreach ($ErrorsToIgnore as $SqlPattern => $ErrMsgPattern)
250 {
251 $SqlPattern = preg_replace("/\\s+/", "\\s+", $SqlPattern);
252 $RevisedErrorsToIgnore[$SqlPattern] = $ErrMsgPattern;
253 }
254 $ErrorsToIgnore = $RevisedErrorsToIgnore;
255 }
256 $this->ErrorsToIgnore = $ErrorsToIgnore;
257 }
258
264 function IgnoredError()
265 {
266 return $this->ErrorIgnored;
267 }
268
269 /*@)*/ /* Setup/Initialization */ /*@(*/
271
279 function Query($QueryString, $FieldName = "")
280 {
281 # clear flag that indicates whether query error was ignored
282 $this->ErrorIgnored = FALSE;
283
284 # if caching is enabled
285 if (self::$CachingFlag)
286 {
287 # if SQL statement is read-only
288 if ($this->IsReadOnlyStatement($QueryString))
289 {
290 # if we have statement in cache
291 if (isset(self::$QueryResultCache[$QueryString]["NumRows"]))
292 {
293 if (self::$QueryDebugOutputFlag)
294 { print("DB-C: $QueryString<br>\n"); }
295
296 # make sure query result looks okay
297 $this->QueryHandle = TRUE;
298
299 # increment cache hit counter
300 self::$CachedQueryCounter++;
301
302 # make local copy of results
303 $this->QueryResults = self::$QueryResultCache[$QueryString];
304 $this->NumRows = self::$QueryResultCache[$QueryString]["NumRows"];
305
306 # set flag to indicate that results should be retrieved from cache
307 $this->GetResultsFromCache = TRUE;
308 }
309 else
310 {
311 # execute SQL statement
312 $this->QueryHandle = $this->RunQuery($QueryString);
313 if (!is_resource($this->QueryHandle)) { return FALSE; }
314
315 # save number of rows in result
316 $this->NumRows = mysql_num_rows($this->QueryHandle);
317
318 # if too many rows to cache
319 if ($this->NumRows >= 50)
320 {
321 # set flag to indicate that query results should not
322 # be retrieved from cache
323 $this->GetResultsFromCache = FALSE;
324 }
325 else
326 {
327 # if advanced caching is enabled
328 if (self::$AdvancedCachingFlag)
329 {
330 # save tables accessed by query
331 self::$QueryResultCache[$QueryString]["TablesAccessed"] =
332 $this->TablesAccessed($QueryString);
333 }
334
335 # if rows found
336 if ($this->NumRows > 0)
337 {
338 # load query results
339 for ($Row = 0; $Row < $this->NumRows; $Row++)
340 {
341 $this->QueryResults[$Row] =
342 mysql_fetch_assoc($this->QueryHandle);
343 }
344
345 # cache query results
346 self::$QueryResultCache[$QueryString] = $this->QueryResults;
347 }
348 else
349 {
350 # clear local query results
351 unset($this->QueryResults);
352 }
353
354 # cache number of rows
355 self::$QueryResultCache[$QueryString]["NumRows"] = $this->NumRows;
356
357 # set flag to indicate that query results should be retrieved from cache
358 $this->GetResultsFromCache = TRUE;
359 }
360 }
361 }
362 else
363 {
364 # if advanced caching is enabled
365 if (self::$AdvancedCachingFlag)
366 {
367 # if table modified by statement is known
368 $TableModified = $this->TableModified($QueryString);
369 if ($TableModified)
370 {
371 # for each cached query
372 foreach (self::$QueryResultCache
373 as $CachedQueryString => $CachedQueryResult)
374 {
375 # if we know what tables were accessed
376 if ($CachedQueryResult["TablesAccessed"])
377 {
378 # if tables accessed include the one we may modify
379 if (in_array($TableModified, $CachedQueryResult["TablesAccessed"]))
380 {
381 # clear cached query results
382 unset($GLOBALS["APDBQueryResultCache"][$CachedQueryString]);
383 }
384 }
385 else
386 {
387 # clear cached query results
388 unset($GLOBALS["APDBQueryResultCache"][$CachedQueryString]);
389 }
390 }
391 }
392 else
393 {
394 # clear entire query result cache
395 self::$QueryResultCache = array();
396 }
397 }
398 else
399 {
400 # clear entire query result cache
401 self::$QueryResultCache = array();
402 }
403
404 # execute SQL statement
405 $this->QueryHandle = $this->RunQuery($QueryString);
406 if ($this->QueryHandle === FALSE) { return FALSE; }
407
408 # set flag to indicate that query results should not be retrieved from cache
409 $this->GetResultsFromCache = FALSE;
410 }
411
412 # reset row counter
413 $this->RowCounter = 0;
414
415 # increment query counter
416 self::$QueryCounter++;
417 }
418 else
419 {
420 # execute SQL statement
421 $this->QueryHandle = $this->RunQuery($QueryString);
422 if ($this->QueryHandle === FALSE) { return FALSE; }
423 }
424
425 if (($FieldName != "") && ($this->QueryHandle != FALSE))
426 {
427 return $this->FetchField($FieldName);
428 }
429 else
430 {
431 return $this->QueryHandle;
432 }
433 }
434
447 function ExecuteQueriesFromFile($FileName)
448 {
449 # open file
450 $FHandle = fopen($FileName, "r");
451
452 # if file open succeeded
453 if ($FHandle !== FALSE)
454 {
455 # while lines left in file
456 $Query = "";
457 $QueryCount = 0;
458 while (!feof($FHandle))
459 {
460 # read in line from file
461 $Line = fgets($FHandle, 32767);
462
463 # trim whitespace from line
464 $Line = trim($Line);
465
466 # if line is not empty and not a comment
467 if (!preg_match("/^#/", $Line)
468 && !preg_match("/^--/", $Line)
469 && strlen($Line))
470 {
471 # add line to current query
472 $Query .= " ".$Line;
473
474 # if line completes a query
475 if (preg_match("/;$/", $Line))
476 {
477 # run query
478 $QueryCount++;
479 $Result = $this->Query($Query);
480 $Query = "";
481
482 # if query resulted in an error that is not ignorable
483 if ($Result === FALSE)
484 {
485 # stop processing queries and set error code
486 $QueryCount = NULL;
487 break;
488 }
489 }
490 }
491 }
492
493 # close file
494 fclose($FHandle);
495 }
496
497 # return number of executed queries to caller
498 return $QueryCount;
499 }
500
506 function QueryErrMsg()
507 {
508 return $this->ErrMsg;
509 }
510
516 function QueryErrNo()
517 {
518 return $this->ErrNo;
519 }
520
527 static function DisplayQueryErrors($NewValue = NULL)
528 {
529 if ($NewValue !== NULL) { self::$DisplayErrors = $NewValue; }
530 return self::$DisplayErrors;
531 }
532
537 function NumRowsSelected()
538 {
539 # if caching is enabled and query was cached
540 if (self::$CachingFlag && $this->GetResultsFromCache)
541 {
542 # return cached number of rows to caller
543 return $this->NumRows;
544 }
545 else
546 {
547 # call to this method after an unsuccessful query
548 if (!is_resource($this->QueryHandle))
549 {
550 return 0;
551 }
552
553 # retrieve number of rows and return to caller
554 return mysql_num_rows($this->QueryHandle);
555 }
556 }
557
563 function NumRowsAffected()
564 {
565 # call to this method after an unsuccessful query
566 if (!is_resource($this->QueryHandle))
567 {
568 return 0;
569 }
570
571 # retrieve number of rows and return to caller
572 return mysql_affected_rows($this->Handle);
573 }
574
580 function FetchRow()
581 {
582 # if caching is enabled and query was cached
583 if (self::$CachingFlag && $this->GetResultsFromCache)
584 {
585 # if rows left to return
586 if ($this->RowCounter < $this->NumRows)
587 {
588 # retrieve row from cache
589 $Result = $this->QueryResults[$this->RowCounter];
590
591 # increment row counter
592 $this->RowCounter++;
593 }
594 else
595 {
596 # return nothing
597 $Result = FALSE;
598 }
599 }
600 else
601 {
602 # call to this method after successful query
603 if (is_resource($this->QueryHandle))
604 {
605 $Result = mysql_fetch_assoc($this->QueryHandle);
606 }
607
608 # call to this method after unsuccessful query
609 else
610 {
611 $Result = FALSE;
612 }
613 }
614
615 # return row to caller
616 return $Result;
617 }
618
625 function FetchRows($NumberOfRows = NULL)
626 {
627 # assume no rows will be returned
628 $Result = array();
629
630 # for each available row
631 $RowsFetched = 0;
632 while ((($RowsFetched < $NumberOfRows) || ($NumberOfRows == NULL))
633 && ($Row = $this->FetchRow()))
634 {
635 # add row to results
636 $Result[] = $Row;
637 $RowsFetched++;
638 }
639
640 # return array of rows to caller
641 return $Result;
642 }
643
660 function FetchColumn($FieldName, $IndexFieldName = NULL)
661 {
662 $Array = array();
663 while ($Record = $this->FetchRow())
664 {
665 if ($IndexFieldName != NULL)
666 {
667 $Array[$Record[$IndexFieldName]] = $Record[$FieldName];
668 }
669 else
670 {
671 $Array[] = $Record[$FieldName];
672 }
673 }
674 return $Array;
675 }
676
685 function FetchField($FieldName)
686 {
687 $Record = $this->FetchRow();
688 return isset($Record[$FieldName]) ? $Record[$FieldName] : NULL;
689 }
690
697 function LastInsertId()
698 {
699 return (int)$this->Query(
700 "SELECT LAST_INSERT_ID() AS InsertId",
701 "InsertId");
702 }
703
718 function UpdateValue(
719 $TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
720 {
721 # expand condition if supplied
722 if ($Condition != NULL) { $Condition = " WHERE ".$Condition; }
723
724 # read cached record from database if not already loaded
725 if (!isset($CachedRecord))
726 {
727 $this->Query("SELECT * FROM `".$TableName."` ".$Condition);
728 $CachedRecord = $this->FetchRow();
729 }
730
731 # if new value supplied
732 if ($NewValue !== DB_NOVALUE)
733 {
734 # update value in database
735 $this->Query("UPDATE `".$TableName."` SET `".$FieldName."` = "
736 .(($NewValue === NULL) ? "NULL" : "'"
737 .mysql_real_escape_string($NewValue)."'")
738 .$Condition);
739
740 # update value in cached record
741 $CachedRecord[$FieldName] = $NewValue;
742 }
743
744 # return value from cached record to caller
745 return isset($CachedRecord[$FieldName])
746 ? $CachedRecord[$FieldName] : NULL;
747 }
748
765 function UpdateIntValue(
766 $TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
767 {
768 return $this->UpdateValue($TableName, $FieldName,
769 (($NewValue === DB_NOVALUE) ? DB_NOVALUE : (int)$NewValue),
770 $Condition, $CachedRecord);
771 }
772
789 function UpdateFloatValue(
790 $TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
791 {
792 return $this->UpdateValue($TableName, $FieldName,
793 (($NewValue === DB_NOVALUE) ? DB_NOVALUE : (float)$NewValue),
794 $Condition, $CachedRecord);
795 }
796
797 /*@)*/ /* Data Manipulation */ /*@(*/
799
806 function LogComment($String)
807 {
808 $this->Query("-- ".$String);
809 }
810
816 function TableExists($TableName)
817 {
818 $this->Query("SHOW TABLES LIKE '".addslashes($TableName)."'");
819 return $this->NumRowsSelected() ? TRUE : FALSE;
820 }
821
828 function FieldExists($TableName, $FieldName)
829 {
830 $this->Query("DESC ".$TableName);
831 while ($CurrentFieldName = $this->FetchField("Field"))
832 {
833 if ($CurrentFieldName == $FieldName) { return TRUE; }
834 }
835 return FALSE;
836 }
837
844 function GetFieldType($TableName, $FieldName)
845 {
846 $this->Query("DESC ".$TableName);
847 return $this->FetchField("Type");
848 }
849
855 static function QueryDebugOutput($NewSetting)
856 {
857 self::$QueryDebugOutputFlag = $NewSetting;
858 }
859
865 static function NumQueries()
866 {
867 return self::$QueryCounter;
868 }
869
876 static function NumCacheHits()
877 {
878 return self::$CachedQueryCounter;
879 }
880
886 static function CacheHitRate()
887 {
888 if (self::$QueryCounter)
889 {
890 return (self::$CachedQueryCounter / self::$QueryCounter) * 100;
891 }
892 else
893 {
894 return 0;
895 }
896 }
897
898 /*@)*/ /* Miscellaneous */
899
900 # ---- PRIVATE INTERFACE -------------------------------------------------
901
902 protected $DBUserName;
903 protected $DBPassword;
904 protected $DBHostName;
905 protected $DBName;
906
907 private $Handle;
908 private $QueryHandle;
909 private $QueryResults;
910 private $RowCounter;
911 private $NumRows;
912 private $GetResultsFromCache;
913 private $ErrorIgnored = FALSE;
914 private $ErrorsToIgnore = NULL;
915 private $ErrMsg = NULL;
916 private $ErrNo = NULL;
917
918 private static $DisplayErrors = FALSE;
919
920 private static $GlobalDBUserName;
921 private static $GlobalDBPassword;
922 private static $GlobalDBHostName;
923 private static $GlobalDBName;
924
925 # debug output flag
926 private static $QueryDebugOutputFlag = FALSE;
927 # flag for whether caching is turned on
928 private static $CachingFlag = TRUE;
929 # query result advanced caching flag
930 private static $AdvancedCachingFlag = FALSE;
931 # global cache for query results
932 private static $QueryResultCache = array();
933 # stats counters
934 private static $QueryCounter = 0;
935 private static $CachedQueryCounter = 0;
936 # database connection link handles
937 private static $ConnectionHandles = array();
938
944 private function IsReadOnlyStatement($QueryString)
945 {
946 return preg_match("/^[ ]*SELECT /i", $QueryString) ? TRUE : FALSE;
947 }
948
955 private function TableModified($QueryString)
956 {
957 # assume we're not going to be able to determine table
958 $TableName = FALSE;
959
960 # split query into pieces
961 $QueryString = trim($QueryString);
962 $Words = preg_split("/\s+/", $QueryString);
963
964 # if INSERT statement
965 $WordIndex = 1;
966 if (strtoupper($Words[0]) == "INSERT")
967 {
968 # skip over modifying keywords
969 while ((strtoupper($Words[$WordIndex]) == "LOW_PRIORITY")
970 || (strtoupper($Words[$WordIndex]) == "DELAYED")
971 || (strtoupper($Words[$WordIndex]) == "IGNORE")
972 || (strtoupper($Words[$WordIndex]) == "INTO"))
973 {
974 $WordIndex++;
975 }
976
977 # next word is table name
978 $TableName = $Words[$WordIndex];
979 }
980 # else if UPDATE statement
981 elseif (strtoupper($Words[0]) == "UPDATE")
982 {
983 # skip over modifying keywords
984 while ((strtoupper($Words[$WordIndex]) == "LOW_PRIORITY")
985 || (strtoupper($Words[$WordIndex]) == "IGNORE"))
986 {
987 $WordIndex++;
988 }
989
990 # if word following next word is SET
991 if (strtoupper($Words[$WordIndex + 1]) == "SET")
992 {
993 # next word is table name
994 $TableName = $Words[$WordIndex];
995 }
996 }
997 # else if DELETE statement
998 elseif (strtoupper($Words[0]) == "DELETE")
999 {
1000 # skip over modifying keywords
1001 while ((strtoupper($Words[$WordIndex]) == "LOW_PRIORITY")
1002 || (strtoupper($Words[$WordIndex]) == "IGNORE")
1003 || (strtoupper($Words[$WordIndex]) == "QUICK"))
1004 {
1005 $WordIndex++;
1006 }
1007
1008 # if next term is FROM
1009 if (strtoupper($Words[$WordIndex]) == "FROM")
1010 {
1011 # next word is table name
1012 $WordIndex++;
1013 $TableName = $Words[$WordIndex];
1014 }
1015 }
1016
1017 # discard table name if it looks at all suspicious
1018 if ($TableName)
1019 {
1020 if (!preg_match("/[a-zA-Z0-9]+/", $TableName))
1021 {
1022 $TableName = FALSE;
1023 }
1024 }
1025
1026 # return table name (or lack thereof) to caller
1027 return $TableName;
1028 }
1029
1036 private function TablesAccessed($QueryString)
1037 {
1038 # assume we're not going to be able to determine tables
1039 $TableNames = FALSE;
1040
1041 # split query into pieces
1042 $QueryString = trim($QueryString);
1043 $Words = preg_split("/\s+/", $QueryString);
1044 $UQueryString = strtoupper($QueryString);
1045 $UWords = preg_split("/\s+/", $UQueryString);
1046
1047 # if SELECT statement
1048 if ($UWords[0] == "SELECT")
1049 {
1050 # keep going until we hit FROM or last word
1051 $WordIndex = 1;
1052 while (($UWords[$WordIndex] != "FROM")
1053 && strlen($UWords[$WordIndex]))
1054 {
1055 $WordIndex++;
1056 }
1057
1058 # if we hit FROM
1059 if ($UWords[$WordIndex] == "FROM")
1060 {
1061 # for each word after FROM
1062 $WordIndex++;
1063 while (strlen($UWords[$WordIndex]))
1064 {
1065 # if current word ends with comma
1066 if (preg_match("/,$/", $Words[$WordIndex]))
1067 {
1068 # strip off comma and add word to table name list
1069 $TableNames[] = substr($Words[$WordIndex], 0, -1);
1070 }
1071 else
1072 {
1073 # add word to table name list
1074 $TableNames[] = $Words[$WordIndex];
1075
1076 # if next word is not comma
1077 $WordIndex++;
1078 if ($Words[$WordIndex] != ",")
1079 {
1080 # if word begins with comma
1081 if (preg_match("/^,/", $Words[$WordIndex]))
1082 {
1083 # strip off comma (NOTE: modifies $Words array!)
1084 $Words[$WordIndex] = substr($Words[$WordIndex], 1);
1085
1086 # decrement index so we start with this word next pass
1087 $WordIndex--;
1088 }
1089 else
1090 {
1091 # stop scanning words (non-basic JOINs not yet handled)
1092 break;
1093 }
1094 }
1095 }
1096
1097 # move to next word
1098 $WordIndex++;
1099 }
1100 }
1101 }
1102
1103 # discard table names if they look at all suspicious
1104 if ($TableNames)
1105 {
1106 foreach ($TableNames as $Name)
1107 {
1108 if (!preg_match("/^[a-zA-Z0-9]+$/", $Name))
1109 {
1110 $TableNames = FALSE;
1111 break;
1112 }
1113 }
1114 }
1115
1116 # return table name (or lack thereof) to caller
1117 return $TableNames;
1118 }
1119
1126 private function RunQuery($QueryString)
1127 {
1128 # log query start time if debugging output is enabled
1129 if (self::$QueryDebugOutputFlag) { $QueryStartTime = microtime(TRUE); }
1130
1131 # run query against database
1132 $this->QueryHandle = mysql_query($QueryString, $this->Handle);
1133
1134 # print query and execution time if debugging output is enabled
1135 if (self::$QueryDebugOutputFlag)
1136 {
1137 print "DB: ".$QueryString." ["
1138 .sprintf("%.2f", microtime(TRUE) - $QueryStartTime)
1139 ."s]"."<br>\n";
1140 }
1141
1142 # if query failed and there are errors that we can ignore
1143 if (($this->QueryHandle === FALSE) && $this->ErrorsToIgnore)
1144 {
1145 # for each pattern for an error that we can ignore
1146 foreach ($this->ErrorsToIgnore as $SqlPattern => $ErrMsgPattern)
1147 {
1148 # if error matches pattern
1149 $ErrorMsg = mysql_error($this->Handle);
1150 if (preg_match($SqlPattern, $QueryString)
1151 && preg_match($ErrMsgPattern, $ErrorMsg))
1152 {
1153 # set return value to indicate error was ignored
1154 $this->QueryHandle = TRUE;
1155
1156 # set internal flag to indicate that an error was ignored
1157 $this->ErrorIgnored = $ErrorMsg;
1158
1159 # stop looking at patterns
1160 break;
1161 }
1162 }
1163 }
1164
1165 # if query failed
1166 if ($this->QueryHandle === FALSE)
1167 {
1168 # clear stored value for number of rows retrieved
1169 $this->NumRows = 0;
1170
1171 # retrieve error info
1172 $this->ErrMsg = mysql_error($this->Handle);
1173 $this->ErrNo = mysql_errno($this->Handle);
1174
1175 # if we are supposed to be displaying errors
1176 if (self::$DisplayErrors)
1177 {
1178 # print error info
1179 print("<b>SQL Error:</b> <i>".$this->ErrMsg
1180 ."</i> (".$this->ErrNo.")<br/>\n");
1181 print("<b>SQL Statement:</b> <i>"
1182 .htmlspecialchars($QueryString)."</i><br/>\n");
1183
1184 # retrieve execution trace that got us to this point
1185 $Trace = debug_backtrace();
1186
1187 # remove current context from trace
1188 array_shift($Trace);
1189
1190 # make sure file name and line number are available
1191 foreach ($Trace as $Index => $Loc)
1192 {
1193 if (!array_key_exists("file", $Loc))
1194 {
1195 $Trace[$Index]["file"] = "UNKNOWN";
1196 }
1197 if (!array_key_exists("line", $Loc))
1198 {
1199 $Trace[$Index]["line"] = "??";
1200 }
1201 }
1202
1203 # determine length of leading path common to all file names in trace
1204 $LocString = "";
1205 $OurFile = __FILE__;
1206 $PrefixLen = 9999;
1207 foreach ($Trace as $Loc)
1208 {
1209 if ($Loc["file"] != "UNKNOWN")
1210 {
1211 $Index = 0;
1212 while ($Loc["file"][$Index] == $OurFile[$Index])
1213 { $Index++; }
1214 $PrefixLen = min($PrefixLen, $Index);
1215 }
1216 }
1217
1218 foreach ($Trace as $Loc)
1219 {
1220 $Sep = "";
1221 $ArgString = "";
1222 foreach ($Loc["args"] as $Arg)
1223 {
1224 $ArgString .= $Sep;
1225 switch (gettype($Arg))
1226 {
1227 case "boolean":
1228 $ArgString .= $Arg ? "TRUE" : "FALSE";
1229 break;
1230
1231 case "integer":
1232 case "double":
1233 $ArgString .= $Arg;
1234 break;
1235
1236 case "string":
1237 $ArgString .= '"<i>'.htmlspecialchars(substr($Arg, 0, 40))
1238 .((strlen($Arg) > 40) ? "..." : "").'</i>"';
1239 break;
1240
1241 case "array":
1242 case "resource":
1243 case "NULL":
1244 $ArgString .= strtoupper(gettype($Arg));
1245 break;
1246
1247 case "object":
1248 $ArgString .= get_class($Arg);
1249 break;
1250
1251 case "unknown type":
1252 $ArgString .= "UNKNOWN";
1253 break;
1254 }
1255 $Sep = ",";
1256 }
1257 $Loc["file"] = substr($Loc["file"], $PrefixLen);
1258 $LocString .= "&nbsp;&nbsp;";
1259 if (array_key_exists("class", $Loc))
1260 { $LocString .= $Loc["class"]."::"; }
1261 $LocString .= $Loc["function"]."(".$ArgString.")"
1262 ." - ".$Loc["file"].":".$Loc["line"]
1263 ."<br>\n";
1264 }
1265 print("<b>Trace:</b><br>\n".$LocString);
1266 }
1267 }
1268 return $this->QueryHandle;
1269 }
1270 }
1271
1272 # define return values (numerical values correspond to MySQL error codes)
1273 define("DB_OKAY", 0);
1274 define("DB_ERROR", 1);
1275 define("DB_ACCESSDENIED", 2);
1276 define("DB_UNKNOWNDB", 3);
1277 define("DB_UNKNOWNTABLE", 4);
1278 define("DB_SYNTAXERROR", 5);
1279 define("DB_DBALREADYEXISTS", 6);
1280 define("DB_DBDOESNOTEXIST", 7);
1281 define("DB_DISKFULL", 8);
1282
1283 # define value to designate omitted arguments (so DB values can be set to NULL)
1284 define("DB_NOVALUE", "!-_-_-DB_NOVALUE-_-_-!");
1285
1286 # MySQL error code mapping
1287 $APDBErrorCodeMappings = array(
1288 1045 => DB_ACCESSDENIED,
1289 1049 => DB_UNKNOWNDB,
1290 1046 => DB_UNKNOWNTABLE,
1291 1064 => DB_SYNTAXERROR,
1292 1007 => DB_DBALREADYEXISTS, # ? (not sure)
1293 1008 => DB_DBDOESNOTEXIST, # ? (not sure)
1294 1021 => DB_DISKFULL, # ? (not sure)
1295 );
1296
1297 # date() format for SQL dates
1298 define("DATE_SQL", "Y-m-d H:i:s");
1299
Database\QueryErrMsg
QueryErrMsg()
Get most recent error message text set by Query().
Definition: Axis--Database.php:506
Database\$DBName
$DBName
Definition: Axis--Database.php:905
Database\Caching
static Caching($NewSetting=NULL)
Get or set whether query result caching is currently enabled.
Definition: Axis--Database.php:190
DB_UNKNOWNDB
const DB_UNKNOWNDB
Definition: Axis--Database.php:1276
Database\__sleep
__sleep()
Definition: Axis--Database.php:80
Database\SetGlobalDatabaseName
static SetGlobalDatabaseName($DatabaseName)
Set default database name.
Definition: Axis--Database.php:122
Database\SetDefaultStorageEngine
SetDefaultStorageEngine($Engine)
Set default database storage engine.
Definition: Axis--Database.php:135
Database\ExecuteQueriesFromFile
ExecuteQueriesFromFile($FileName)
Execute queries from specified file.
Definition: Axis--Database.php:447
Database\$DBPassword
$DBPassword
Definition: Axis--Database.php:903
Database\$DBUserName
$DBUserName
Definition: Axis--Database.php:902
Database\UpdateIntValue
UpdateIntValue($TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
A convenience function to get or set an integer value in the database.
Definition: Axis--Database.php:765
DB_SYNTAXERROR
const DB_SYNTAXERROR
Definition: Axis--Database.php:1278
Database
SQL database abstraction object with smart query caching.
Definition: Axis--Database.php:22
Database\GetServerVersion
GetServerVersion()
Get database server version number.
Definition: Axis--Database.php:149
Database\SetQueryErrorsToIgnore
SetQueryErrorsToIgnore($ErrorsToIgnore, $NormalizeWhitespace=TRUE)
Set query errors to ignore.
Definition: Axis--Database.php:244
DB_NOVALUE
const DB_NOVALUE
Definition: Axis--Database.php:1284
Database\DBUserName
DBUserName()
Get name used to connect with database server.
Definition: Axis--Database.php:181
Database\Database
Database($UserName=NULL, $Password=NULL, $DatabaseName=NULL, $HostName=NULL)
Object constructor.
Definition: Axis--Database.php:40
Database\FetchRow
FetchRow()
Get next database row retrieved by most recent query.
Definition: Axis--Database.php:580
Database\LastInsertId
LastInsertId()
Get ID of row added by the last SQL "INSERT" statement.
Definition: Axis--Database.php:697
Database\TableExists
TableExists($TableName)
Get whether specified table exists.
Definition: Axis--Database.php:816
Database\SetGlobalServerInfo
static SetGlobalServerInfo($UserName, $Password, $HostName="localhost")
Definition: Axis--Database.php:107
DB_DBALREADYEXISTS
const DB_DBALREADYEXISTS
Definition: Axis--Database.php:1279
Database\$DBHostName
$DBHostName
Definition: Axis--Database.php:904
PHP
PHP
Definition: OAIClient.php:39
Database\GetFieldType
GetFieldType($TableName, $FieldName)
Get field (column) type.
Definition: Axis--Database.php:844
Database\NumRowsSelected
NumRowsSelected()
Get number of rows returned by last SELECT or SHOW query.
Definition: Axis--Database.php:537
Database\FetchRows
FetchRows($NumberOfRows=NULL)
Get specified number of database rows retrieved by most recent query.
Definition: Axis--Database.php:625
Database\QueryDebugOutput
static QueryDebugOutput($NewSetting)
Enable or disable debugging output for queries.
Definition: Axis--Database.php:855
Database\Query
Query($QueryString, $FieldName="")
Query database (with caching if enabled).
Definition: Axis--Database.php:279
Database\FetchField
FetchField($FieldName)
Pull next row from last DB query and get a specific value from that row.
Definition: Axis--Database.php:685
Database\FieldExists
FieldExists($TableName, $FieldName)
Get whether specified field exists in specified table.
Definition: Axis--Database.php:828
Database\NumCacheHits
static NumCacheHits()
Get the number of queries that have resulted in cache hits since program execution began...
Definition: Axis--Database.php:876
Database\FetchColumn
FetchColumn($FieldName, $IndexFieldName=NULL)
Get all available values for specified database field retrieved by most recent query.
Definition: Axis--Database.php:660
Database\DBHostName
DBHostName()
Get host name of system on which database server resides.
Definition: Axis--Database.php:167
Database\NumRowsAffected
NumRowsAffected()
Get number of rows affected by last INSERT, UPDATE, REPLACE, or DELETE query.
Definition: Axis--Database.php:563
DB_ACCESSDENIED
const DB_ACCESSDENIED
Definition: Axis--Database.php:1275
Database\UpdateFloatValue
UpdateFloatValue($TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
A convenience function to get or set a float value in the database.
Definition: Axis--Database.php:789
Database\QueryErrNo
QueryErrNo()
Get most recent error code set by Query().
Definition: Axis--Database.php:516
$APDBErrorCodeMappings
$APDBErrorCodeMappings
Definition: Axis--Database.php:1287
Database\UpdateValue
UpdateValue($TableName, $FieldName, $NewValue, $Condition, &$CachedRecord)
A convenience function to get or set a value in the database.
Definition: Axis--Database.php:718
Database\AdvancedCaching
static AdvancedCaching($NewSetting=NULL)
Get or set whether advanced query result cachine is currently enabled.
Definition: Axis--Database.php:216
Database\DisplayQueryErrors
static DisplayQueryErrors($NewValue=NULL)
Get/set whether Query() errors will be displayed.
Definition: Axis--Database.php:527
Database\CacheHitRate
static CacheHitRate()
Get the ratio of query cache hits to queries as a percentage.
Definition: Axis--Database.php:886
Database\IgnoredError
IgnoredError()
Check whether an error was ignored by the most recent query.
Definition: Axis--Database.php:264
Database\DBName
DBName()
Get current database name.
Definition: Axis--Database.php:174
Database\LogComment
LogComment($String)
Peform query that consists of SQL comment statement.
Definition: Axis--Database.php:806
Database\__wakeup
__wakeup()
Restore database connection when unserialized.
Definition: Axis--Database.php:87
Database\NumQueries
static NumQueries()
Get the number of queries that have been run since program execution began.
Definition: Axis--Database.php:865
DB_DBDOESNOTEXIST
const DB_DBDOESNOTEXIST
Definition: Axis--Database.php:1280
DB_UNKNOWNTABLE
const DB_UNKNOWNTABLE
Definition: Axis--Database.php:1277
DB_DISKFULL
const DB_DISKFULL
Definition: Axis--Database.php:1281