Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
DAL.inc
1 <?php
13 // Matrix = Channels system not required
14 //require_once dirname(dirname(__FILE__)).'/Channels/Channels.inc';
15 require_once dirname(__FILE__).'/Exceptions/DALException.inc';
16 // We're in a different place here; we can't assume that we're starting from
17 // the root
18 //require_once 'DAL/Query.inc';
19 require_once dirname(__FILE__).'/Query.inc';
20 
41 class DAL
42 {
43 
44 
62  private static $_dbhPool = NULL;
63 
64 
75  private static $_dbStack = Array();
76 
83  private static $_currentDbConnId = '';
84 
91  private static $_dbTypes = Array();
92 
102  private static $_inTransaction = FALSE;
103 
112  private static $_dbNames = array(
113  'db2' => 'DB2',
114  'dblib' => 'SQLServer',
115  'mysql' => 'MySQL',
116  'oci' => 'Oracle',
117  'pgsql' => 'PostgreSQL',
118  );
119 
126  private static $_currentDbName = NULL;
127 
136  private static $_transactionEnabled = FALSE;
137 
144  private static $_queryLog = array();
145 
152  private static $_logQueries = FALSE;
153 
160  private static $_currentQueryLog = NULL;
161 
170  private static $_ociCommitOnSuccess = FALSE;
171 
180  private function __construct()
181  {
182 
183  }//end __construct()
184 
185 
199  public static function getQuery($systemid, $queryid, $bindValues=TRUE)
200  {
201  // Work out the class and method name to call.
202  $class = $systemid.'Queries';
203  $function = 'prepare'.$queryid.'Query';
204 
205  self::requireQueryClass($systemid);
206 
207  // Should we include the class here?
208  if (method_exists($class, $function) === FALSE) {
209  // Query not found. Throw DALException exception?
210  throw new DALException('Could not load query '.$queryid.' in system '.$systemid);
211  } else {
212  // Get the event data for the current channel.
213  $eventData = Channels::getCurrentEventBasketData();
214  return call_user_func(array($class, $function), $eventData, $bindValues);
215  }
216 
217  }//end getQuery()
218 
219 
229  public static function getAssoc(Query $dalQuery, $col=NULL)
230  {
231 
232  $query = $dalQuery->prepare();
233  $result = self::executePdoAssoc($query, $col);
234 
235  // OCI8: release any created LOB objects
236  $dalQuery->releaseLobs();
237 
238 
239  return $result;
240 
241  }//end getAssoc()
242 
243 
252  public static function getAll(Query $dalQuery)
253  {
254 
255  $query = $dalQuery->prepare();
256  $result = self::executePdoAll($query);
257 
258  // OCI8: release any created LOB objects
259  $dalQuery->releaseLobs();
260 
261 
262  return $result;
263 
264  }//end getAll()
265 
266 
275  public static function getOne(Query $dalQuery)
276  {
277 
278  $query = $dalQuery->prepare();
279  $result = self::executePdoOne($query);
280 
281  // OCI8: release any created LOB objects
282  $dalQuery->releaseLobs();
283 
284 
285  return $result;
286 
287  }//end getOne()
288 
289 
304  public static function getDALQuery($systemid, $queryid, $method)
305  {
306  $queryArray = self::getQuery($systemid, $queryid, FALSE);
307  // Add the method data to the query array, as this will allow
308  // methods that this is passed to to execute it.
309  $queryArray->setExecMethod($method);
310  return $queryArray;
311 
312  }//end getDALQuery()
313 
314 
324  public static function getGrouped(Query $dalQuery)
325  {
326 
327  $query = $dalQuery->prepare();
328  $result = self::executePdoGrouped($query);
329 
330 
331  return $result;
332 
333  }//end getGrouped()
334 
335 
346  public static function getGroupedAssoc(Query $dalQuery)
347  {
348 
349  $query = $dalQuery->prepare();
350  $result = self::executePdoGroupedAssoc($query);
351 
352 
353  return $result;
354 
355  }//end getGroupedAssoc()
356 
357 
367  public static function executeGrouped($systemid, $queryid)
368  {
369  $query = self::getQuery($systemid, $queryid);
370  $res = self::getGrouped($query);
371 
372  return $res;
373 
374  }//end executeGrouped()
375 
376 
387  public static function executeGroupedAssoc($systemid, $queryid)
388  {
389  $query = self::getQuery($systemid, $queryid);
390  $res = self::getGroupedAssoc($query);
391 
392  return $res;
393 
394  }//end executeGrouped()
395 
396 
409  public static function executeAssoc($systemid, $queryid, $col=NULL)
410  {
411  $query = self::getQuery($systemid, $queryid);
412  $res = self::getAssoc($query, $col);
413 
414  return $res;
415 
416  }//end executeAssoc()
417 
418 
430  public static function executeAll($systemid, $queryid)
431  {
432  $query = self::getQuery($systemid, $queryid);
433  $res = self::getAll($query);
434 
435  return $res;
436 
437  }//end executeAll()
438 
439 
451  public static function executeOne($systemid, $queryid)
452  {
453  $query = self::getQuery($systemid, $queryid);
454  $result = self::getOne($query);
455 
456  // Oracle returns resourceid for LOB fields.
457  // If result is a resource then retreive its contents.
458  if (is_resource($result) === TRUE) {
459  $result = stream_get_contents($result);
460  }
461 
462  return $result;
463 
464  }//end executeOne()
465 
466 
480  public static function executeQuery($systemid, $queryid=NULL)
481  {
482  $query = NULL;
483  if (($systemid instanceof Query) === TRUE) {
484  $dalQuery = $systemid;
485  $query = $dalQuery->prepare();
486  } else if ($queryid === NULL) {
487  throw new DALException('No queryid provided for executeQuery.');
488  } else {
489  $dalQuery = self::getQuery($systemid, $queryid);
490  $query = $dalQuery->prepare();
491  }
492 
493  try {
494  self::execPdoQuery($query);
495  $dalQuery->releaseLobs();
496  } catch (PDOException $e) {
497  throw new DALException($e->getMessage());
498  }
499 
500  $rows = (int)$query->rowCount();
501 
502  // DB2 returns -1 rows if no rows were affected.
503  if ($rows === -1) {
504  $rows = 0;
505  }
506 
507 
508  return $rows;
509 
510  }//end executeQuery()
511 
512 
522  public static function getExecuteQuery($systemid, $queryid=NULL)
523  {
524  return self::executeQuery($systemid, $queryid);
525 
526  }//end getExecuteQuery()
527 
528 
538  public static function getExecuteAll($systemid, $queryid)
539  {
540  return self::executeAll($systemid, $queryid);
541 
542  }//end getExecuteAll()
543 
544 
554  public static function executeDALQuery(Query $query, $execMethod=NULL)
555  {
556 
557  if ($execMethod === NULL) {
558  $execMethod = $query->getExecMethod();
559  }
560 
561  $methodArray = array(
562  'self',
563  'get'.ucfirst($execMethod),
564  );
565  $result = call_user_func($methodArray, $query);
566  return $result;
567 
568  }//end executeDALQuery()
569 
570 
580  public static function execPdoQuery($query)
581  {
582  $query_log = 'unknown query';
587  if ($query instanceof PDOStatement) {
588  $query_log = $query->queryString;
589  }
590  self::_startQueryTimer($query_log);
591 
592  $dbh = self::getDb();
593 
594  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
595  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
596  }
597 
598  if (self::getDbType() === 'oci') {
599  // OCI:
600  if(self::$_ociCommitOnSuccess){
601  $result = oci_execute($query, OCI_COMMIT_ON_SUCCESS);
602  }
603  else {
604  $result = oci_execute($query, OCI_DEFAULT);
605  }
606  if ($result === FALSE) {
607  $oci_error = oci_error($query);
608  throw new DALException('Unable to execute query: '.$oci_error['message']);
609  }
610  $rows = oci_num_rows($query);
611  } else {
612  $query->execute();
613  $rows = (int)$query->rowCount();
614  }
615 
616  self::_endQueryTimer();
617 
618  return $rows;
619 
620  }//end execPdoQuery()
621 
622 
636  public static function executePdoAssoc($query, $col=NULL)
637  {
638  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
639  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
640  }
641 
642  try {
643  self::execPdoQuery($query);
644  } catch (PDOException $e) {
645  throw new DALException($e->getMessage());
646  }
647 
648  if (self::getDbType() === 'oci') {
649  // OCI:
650  $dbh = self::getDb();
651 
652  if ($col === NULL) {
653  $result = Array();
654  while ($current_row = oci_fetch_array($query, OCI_ASSOC | OCI_RETURN_LOBS | OCI_RETURN_NULLS)) {
655  $result[] = array_change_key_case($current_row, CASE_LOWER);
656  }
657  } else {
658  $result = Array();
659  while ($current_row = oci_fetch_array($query, OCI_NUM | OCI_RETURN_LOBS | OCI_RETURN_NULLS)) {
660  $result[] = $current_row[$col];
661  }
662  }
663  } else {
664  $result = NULL;
665  if ($col !== NULL) {
666  $result = $query->fetchAll(PDO::FETCH_COLUMN, $col);
667  } else {
668  $result = $query->fetchAll(PDO::FETCH_ASSOC);
669  }
670  }
671 
672  return $result;
673 
674  }//end executePdoAssoc()
675 
676 
685  public static function executePdoAll($query)
686  {
687  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
688  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
689  }
690 
691  try {
692  self::execPdoQuery($query);
693  } catch (PDOException $e) {
694  throw $e;
695  }
696 
697  if (self::getDbType() === 'oci') {
698  // OCI:
699  $dbh = self::getDb();
700  $result = Array();
701  while ($current_row = oci_fetch_array($query, OCI_BOTH | OCI_RETURN_LOBS | OCI_RETURN_NULLS)) {
702  $result[] = array_change_key_case($current_row, CASE_LOWER);
703  }
704  } else {
705  $result = $query->fetchAll();
706  }
707 
708  return $result;
709 
710  }//end executePdoAll()
711 
712 
722  public static function executePdoGrouped($query)
723  {
724  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
725  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
726  }
727 
728  $result = array();
729  try {
730  self::execPdoQuery($query);
731  } catch (PDOException $e) {
732  throw new DALException($e->getMessage());
733  }
734 
735  while (TRUE) {
736  if (self::getDbType() === 'oci') {
737  // OCI:
738  $row = oci_fetch_array($query, OCI_NUM | OCI_RETURN_LOBS | OCI_RETURN_NULLS);
739  if (is_array($row)) {
740  $row = array_change_key_case($row, CASE_LOWER);
741  }
742  } else {
743  $row = $query->fetch(PDO::FETCH_NUM);
744  }
745 
746  if ($row === FALSE) break;
747 
748  if (isset($result[$row[0]]) === FALSE) {
749  $result[$row[0]] = array();
750  }
751 
752  $current = array();
753  $i = 1;
754  while (isset($row[$i]) === TRUE) {
755  $current[] = $row[$i];
756  $i++;
757  }
758 
759  $result[$row[0]][] = $current;
760  }
761 
762  return $result;
763 
764  }//end executePdoGrouped()
765 
766 
776  public static function executePdoGroupedAssoc($query)
777  {
778  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
779  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
780  }
781 
782  $result = array();
783 
784  try {
785  self::execPdoQuery($query);
786  } catch (PDOException $e) {
787  throw new DALException($e->getMessage());
788  }
789 
790  while (TRUE) {
791  if (self::getDbType() === 'oci') {
792  // OCI:
793  $row = oci_fetch_array($query, OCI_ASSOC | OCI_RETURN_LOBS | OCI_RETURN_NULLS);
794  if (is_array($row)) {
795  $row = array_change_key_case($row, CASE_LOWER);
796  }
797  } else {
798  $row = $query->fetch(PDO::FETCH_ASSOC);
799  }
800 
801  if ($row === FALSE) break;
802 
803  // If we don't know the first field yet, find out what it is
804  // because it should be the same for each row
805  if (isset($first_field) === FALSE) {
806  reset($row);
807  $first_field = key($row);
808  }
809  $first_value = $row[$first_field];
810 
811  if (isset($result[$first_value]) === FALSE) {
812  $result[$first_value] = array();
813  }
814 
815  $current = $row;
816  unset($current[$first_field]);
817  $result[$first_value][] = $current;
818  unset($row);
819  }
820 
821  return $result;
822 
823  }//end executePdoGroupedAssoc()
824 
825 
834  public static function executePdoOne($query)
835  {
836  if (!((gettype($query) !== 'PDOStatement') || (is_resource($query) && (get_resource_type($query) === 'oci8 statement')))) {
837  throw new Exception('Invalid parameter 1 given to '.__FUNCTION__.'()');
838  }
839 
840  try {
841  self::execPdoQuery($query);
842  } catch (PDOException $e) {
843  throw new DALException($e->getMessage());
844  }
845 
846  if (self::getDbType() === 'oci') {
847  $result_row = oci_fetch_array($query, OCI_NUM | OCI_RETURN_LOBS | OCI_RETURN_NULLS);
848  $result = $result_row[0];
849  } else {
850  $result = $query->fetchColumn();
851 
852  if (is_resource($result) === TRUE) {
853  $result = stream_get_contents($result);
854  }
855  }
856 
857  return $result;
858 
859  }//end executePdoOne()
860 
861 
872  public static function executeSql($sql)
873  {
874 
875  $dbh = self::getDb();
876 
877  if (self::getDbType() === 'oci') {
878  // OCI:
879  $query = oci_parse($dbh, $sql);
880  if ($query === FALSE) {
881  $oci_error = oci_error($query);
882  throw new DALException('Unable to prepare query :'.$oci_error['code'].' '.$oci_error['message']);
883  }
884 
885  self::execPdoQuery($query);
886  $rows = oci_num_rows($query);
887 
888  if ($rows === FALSE) {
889 
890  }
891  } else {
892  try {
893  self::_startQueryTimer($sql);
894  $rows = $dbh->exec($sql);
895  self::_endQueryTimer();
896  } catch (PDOException $e) {
897  throw new DALException('DBError!:'.$e->getMessage());
898  }
899  }
900 
901 
902  return $rows;
903 
904  }//end executeSql()
905 
906 
920  public static function executeSqlAssoc($sql, $col=NULL)
921  {
922  $dbh = self::getDb();
923 
924  if (self::getDbType() === 'oci') {
925  // OCI:
926  $query = oci_parse($dbh, $sql);
927  } else {
928  $query = $dbh->prepare($sql);
929  }
930  return self::executePdoAssoc($query, $col);
931 
932  }//end executeSqlAssoc()
933 
934 
943  public static function executeSqlAll($sql)
944  {
945  $dbh = self::getDb();
946 
947  if (self::getDbType() === 'oci') {
948  // OCI:
949  $query = oci_parse($dbh, $sql);
950  } else {
951  $query = $dbh->prepare($sql);
952  }
953  $res = self::executePdoAll($query);
954 
955  return $res;
956 
957  }//end executeSqlAll()
958 
959 
969  public static function executeSqlGrouped($sql)
970  {
971  $dbh = self::getDb();
972 
973  if (self::getDbType() === 'oci') {
974  // OCI:
975  $query = oci_parse($dbh, $sql);
976  } else {
977  $query = $dbh->prepare($sql);
978  }
979  $res = self::executePdoGrouped($query);
980 
981  return $res;
982 
983  }//end executeSqlGrouped()
984 
985 
995  public static function executeSqlGroupedAssoc($sql)
996  {
997  $dbh = self::getDb();
998 
999  if (self::getDbType() === 'oci') {
1000  // OCI:
1001  $query = oci_parse($dbh, $sql);
1002  } else {
1003  $query = $dbh->prepare($sql);
1004  }
1005  $res = self::executePdoGroupedAssoc($query);
1006 
1007  return $res;
1008 
1009  }//end executeSqlGroupedAssoc()
1010 
1011 
1020  public static function executeSqlOne($sql)
1021  {
1022  $dbh = self::getDb();
1023 
1024  if (self::getDbType() === 'oci') {
1025  // OCI:
1026  $query = oci_parse($dbh, $sql);
1027  } else {
1028  $query = $dbh->prepare($sql);
1029  }
1030  $res = self::executePdoOne($query);
1031 
1032  return $res;
1033 
1034  }//end executeSqlOne()
1035 
1036 
1050  public static function executeQueries($sql)
1051  {
1052  // Split SQL statements.
1053  $queries = explode(';', $sql);
1054  if (empty($queries) === FALSE) {
1055  foreach ($queries as $query) {
1056  if (trim($query) !== '') {
1057  self::executeSql($query);
1058  }
1059  }
1060  }
1061 
1062  }//end executeQueries()
1063 
1064 
1073  public static function query($sql)
1074  {
1075  $dbh = self::getDb();
1076  self::_startQueryTimer($sql);
1077  $result = $dbh->query($sql);
1078  self::_endQueryTimer();
1079  return $result;
1080 
1081  }//end query()
1082 
1083 
1090  public static function beginTransaction()
1091  {
1092  $currentDb = self::$_currentDbConnId;
1093  $dbInfo = self::$_dbhPool[$currentDb];
1094 
1095  if ($dbInfo['transactionSupport'] === TRUE) {
1096  $dbh = self::getDb();
1097 
1098  if (self::getDbType() === 'oci') {
1099  // OCI: Oracle does not require an explicit BEGIN statement.
1100  ;
1101  } else {
1102  $dbh->beginTransaction();
1103  }
1104  self::$_dbhPool[$currentDb]['inTransaction'] = TRUE;
1105  }
1106 
1107  }//end beginTransaction()
1108 
1109 
1116  public static function commit()
1117  {
1118  $currentDb = self::$_currentDbConnId;
1119 
1120  if (self::$_dbhPool[$currentDb]['inTransaction'] === TRUE) {
1121  $dbh = self::getDb();
1122 
1123  if (self::getDbType() === 'oci') {
1124  // OCI:
1125  $return = oci_commit($dbh);
1126  if ($return === FALSE) {
1127  $oci_error = oci_error($dbh);
1128  throw new DALException('Unable to commit on connection ID "'.$currentDb.'": '.$oci_error['code'].' '.$oci_error['message']);
1129  }
1130  } else {
1131  $dbh->commit();
1132  }
1133  self::$_dbhPool[$currentDb]['inTransaction'] = FALSE;
1134  }
1135 
1136  }//end commit()
1137 
1138 
1147  public static function rollBack()
1148  {
1149  $currentDb = self::$_currentDbConnId;
1150 
1151  if (self::$_dbhPool[$currentDb]['inTransaction'] === TRUE) {
1152  $dbh = self::getDb();
1153 
1154  if (self::getDbType() === 'oci') {
1155  // OCI:
1156  $return = oci_rollback($dbh);
1157  if ($return === FALSE) {
1158  $oci_error = oci_error($dbh);
1159  throw new DALException('Unable to roll back on connection ID "'.$currentDb.'": '.$oci_error['code'].' '.$oci_error['message']);
1160  }
1161  } else {
1162  $dbh->rollBack();
1163  }
1164  self::$_dbhPool[$currentDb]['inTransaction'] = FALSE;
1165  }
1166 
1167  }//end rollBack()
1168 
1169 
1181  public static function lastInsertId($sequenceName)
1182  {
1183  $dbh = self::getDb();
1184  return (int)$dbh->lastInsertId($sequenceName);
1185 
1186  }//end lastInsertId()
1187 
1188 
1189  /*
1190  Database Connection
1191  */
1192 
1193 
1209  public static function dbConnect(array &$dsn=NULL, $conn_id='db', $oci_force_new = FALSE)
1210  {
1211  try {
1212  if ($dsn === NULL) {
1213  // If DSN is not specified, get our DSN list; if a config entry
1214  // does not exist for this connection, there is a problem.
1215  $dsn = self::getDsnFromConfig($conn_id);
1216  }
1217 
1218  // Add the DSN which can be a single DSN or a DSN array (pool) to the DSN Manager's list
1219  require_once dirname(__FILE__).'/DSNManager.inc';
1220  DSNManager::addDSN($conn_id, $dsn);
1221 
1222  $new_dbh = FALSE;
1223  do {
1224  // Get a single DSN from the DSN Manager
1225  $dsn = DSNManager::getDSN($conn_id);
1226  // If we can not get a single DSN from the DSN Pool, throw an exception
1227  if (is_null($dsn) && DSNManager::isDSNPool($conn_id)) {
1228  throw new Exception("Unable to connect to database '$conn_id': Fail to connect to any DB in the DSN Pool.");
1229  }
1230 
1231  $user = NULL;
1232  $pass = NULL;
1233  if (isset($dsn['user']) === TRUE) {
1234  $user = $dsn['user'];
1235  }
1236 
1237  if (isset($dsn['password']) === TRUE) {
1238  $pass = $dsn['password'];
1239  }
1240 
1241  $persistent = false;
1242  if (isset($dsn['persistent']) && $dsn['persistent'] == true) {
1243  $persistent = true;
1244  }
1245 
1246  if ($dsn['type'] === 'oci') {
1247  // OCI: Oracle in PDO is far too buggy to be considered usable (tested
1248  // in 5.1.x to 5.3dev). Therefore we'll be resigned to using
1249  // legacy OCI8 extension functions.
1250  // use @ to suppress warning/error messages, it will be handled by ourself.
1251 
1252  $oci_connect_fn = 'oci_connect';
1253  if ($persistent) {
1254  $oci_connect_fn = 'oci_pconnect';
1255  }
1256  if($oci_force_new){
1257  $oci_connect_fn = 'oci_new_connect';
1258  }
1259  // Connect to the database with the specified character encoding (if supplied).
1260  if (isset($dsn['encoding'])) {
1261  $new_dbh = @$oci_connect_fn($dsn['user'], $dsn['password'], $dsn['DSN'], $dsn['encoding']);
1262  } else {
1263  $new_dbh = @$oci_connect_fn($dsn['user'], $dsn['password'], $dsn['DSN']);
1264  }
1265 
1266  if ($new_dbh === FALSE) {
1267  $oci_error = oci_error();
1268 
1269  $err_msg = 'Unable to connect to database "'.$conn_id.'": '.$oci_error['code'].' '.$oci_error['message'];
1270  // If we can not connect to the DB specified by the single DSN in the DSN pool, log the error and try another DSN
1271  if (DSNManager::isDSNPool($conn_id)) {
1272  log_error($err_msg, E_USER_WARNING);
1273  DSNManager::registerDSNFailure($conn_id); // Mark the current DSN so that it will not be selected by the DSN Pool again
1274  continue;
1275  } else {
1276  // Throw exception immediately if this connection only has a single DSN
1277  throw new Exception($err_msg);
1278  }
1279  }
1280  } else {
1281 
1282  $extra_params = array();
1283 
1284  if ($persistent) {
1285  $extra_params[PDO::ATTR_PERSISTENT] = true;
1286  }
1287 
1288  if (isset($dsn['timeout']) && is_int($dsn['timeout'])) {
1289  $extra_params[PDO::ATTR_TIMEOUT] = (int)$dsn['timeout'];
1290  }
1291 
1292  try {
1293  $new_dbh = new PDO($dsn['DSN'], $user, $pass, $extra_params);
1294  } catch (Exception $conn_e) {
1295  // If we can not connect to the DB specified by the single DSN in the DSN pool, log the error and try another DSN
1296  if (DSNManager::isDSNPool($conn_id)) {
1297  log_error("Unable to connect to database '$conn_id': ".$conn_e->getMessage(), E_USER_WARNING);
1298  DSNManager::registerDSNFailure($conn_id); // Mark the current DSN so that it will not be selected by the DSN Pool again
1299  continue;
1300  } else {
1301  // Throw exception immediately if this connection only has a single DSN
1302  throw $conn_e;
1303  }
1304  }
1305 
1306  $new_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
1307  $new_dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
1308  $new_dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
1309 
1310  if ($dsn['type'] === 'mysql') {
1311  $new_dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
1312  $new_dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, TRUE);
1313  }
1314 
1315  }
1316  } while ($new_dbh === FALSE);
1317 
1318  self::$_dbhPool[$conn_id] = array(
1319  'dbh' => $new_dbh,
1320  'dsn' => $dsn['DSN'],
1321  'dbType' => $dsn['type'],
1322  'userName' => $user,
1323  'password' => $pass,
1324  );
1325 
1326  // Check if this database supports db transactions.
1327  // We need to change first because transaction functions won't
1328  // like no current database
1329  #self::changeDb($conn_id);
1330 
1331  #if (self::transactionSupport($conn_id) === TRUE) {
1332  self::$_dbhPool[$conn_id]['transactionSupport'] = TRUE;
1333  #} else {
1334  # self::$_dbhPool[$conn_id]['transactionSupport'] = FALSE;
1335  #}
1336 
1337  #self::restoreDb();
1338 
1339  self::$_dbhPool[$conn_id]['inTransaction'] = FALSE;
1340 
1341  } catch (PDOException $e) {
1342  throw new DALException('DBError!:'.$e->getMessage());
1343  }
1344 
1345  return self::$_dbhPool[$conn_id]['dbh'];
1346 
1347  }//end dbConnect()
1348 
1349 
1359  public static function changeDb($conn_id)
1360  {
1361  if (self::dbConnected($conn_id) === FALSE) {
1362  throw new DALException('Connection "'.$conn_id.'" must be connected before it can be changed to.');
1363  }
1364 
1365  array_push(self::$_dbStack, $conn_id);
1366  self::$_currentDbConnId = $conn_id;
1367 
1368  }//end changeDb()
1369 
1370 
1378  public static function restoreDb()
1379  {
1380  if (empty(self::$_dbStack) === TRUE) {
1381  throw new DALException('The database connection stack is empty; there is no previous connection to restore.');
1382  }
1383 
1384  array_pop(self::$_dbStack);
1385 
1386  if (empty(self::$_dbStack) === TRUE) {
1387  self::$_currentDbConnId = '';
1388  } else {
1389  self::$_currentDbConnId = self::$_dbStack[count(self::$_dbStack) - 1];
1390  }
1391 
1392  }//end restoreDb()
1393 
1394 
1402  public static function getCurrentDbId()
1403  {
1404  if (empty(self::$_dbStack) === TRUE) {
1405  throw new DALException('The database connection stack is empty.');
1406  }
1407 
1408  return self::$_currentDbConnId;
1409 
1410  }//end getCurrentDbId()
1411 
1412 
1424  public static function transactionSupport($conn_id=NULL)
1425  {
1426  try {
1427  // Test if db transactions work.
1428  $dbh = self::getDb($conn_id);
1429  $dbh->beginTransaction();
1430  self::$_dbhPool[$conn_id]['inTransaction'] = TRUE;
1431  } catch (PDOException $e) {
1432  return FALSE;
1433  }
1434 
1435  // Close dbt.
1436  self::rollBack();
1437  return TRUE;
1438 
1439  }//end transactionSupport()
1440 
1441 
1451  public static function dbClose($conn_id)
1452  {
1453  if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
1454  // Can't close a connection that isn't open...
1455  throw new DALException('Connection with ID "'.$conn_id.'" cannot be closed because a connection of that ID is not open.');
1456  } else if (array_search($conn_id, self::$_dbStack) !== FALSE) {
1457  // If this connection is still in the database stack, we should not
1458  // allow them to close the connection.
1459  throw new DALException('Connection with ID "'.$conn_id.'" cannot be closed because it still exists in the stack.');
1460  } else {
1461  if (self::getDbType(FALSE, $conn_id) === 'oci') {
1462  // OCI: Must close Oracle connections first
1463  $return = oci_close(self::$_dbhPool[$conn_id]['dbh']);
1464  if ($return === FALSE) {
1465  $oci_error = oci_error(self::$_dbhPool[$conn_id]['dbh']);
1466  throw new DALException('Unable to close connection ID "'.$currentDb.'": '.$oci_error['code'].' '.$oci_error['message']);
1467  }
1468  }
1469 
1470  unset(self::$_dbhPool[$conn_id]);
1471  }
1472 
1473  }//end dbClose()
1474 
1475 
1488  public static function dbConnected($conn_id=NULL)
1489  {
1490  if ($conn_id === NULL) {
1491  return !empty(self::$_dbhPool);
1492  } else {
1493  return isset(self::$_dbhPool[$conn_id]);
1494  }
1495 
1496  }//end dbConnected()
1497 
1498 
1508  public static function getDsn($conn_id=NULL)
1509  {
1510  if ($conn_id === NULL) {
1511  $conn_id = self::$_currentDbConnId;
1512  }
1513 
1514  if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
1515  $error = 'DAL configuration not defined for connection ID "'.$conn_id.'".';
1516  throw new DALException($error);
1517  } else {
1518  $dsn = self::$_dbhPool[$conn_id];
1519  }
1520 
1521  return $dsn;
1522 
1523  }//end getDsn()
1524 
1525 
1526 
1536  public static function getDsnFromConfig($conn_id)
1537  {
1538  $dsn = include dirname(__FILE__).'/DALConf.inc';
1539  if (isset($dsn[$conn_id]) === FALSE) {
1540  $error = 'DAL configuration not defined for connection ID "'.$conn_id.'".';
1541  throw new DALException($error);
1542  } else if (isset($dsn[$conn_id]['DSN']) === FALSE) {
1543  $error = 'DAL configuration for connection ID "'.$conn_id.'" does not define a DSN.';
1544  throw new DALException($error);
1545  }
1546 
1547  return $dsn[$conn_id];
1548 
1549  }//end getDsnFromConfig()
1550 
1551 
1558  public static function getDbName($conn_id)
1559  {
1560  if (self::$_[$conn_id] === NULL) {
1561  // Try to get the database name from DSN string.
1562  $dsn = self::getDsn();
1563  if (isset($dsn['DSN']) === TRUE) {
1564  $matches = array();
1565  $reg = '/.*dbname=([a-zA-Z0-9_]+)[;]?/i';
1566  preg_match($reg, $dsn['DSN'], $matches);
1567  if (isset($matches[1]) === TRUE) {
1568  self::$_currentDbName = $matches[1];
1569  }
1570  }
1571  }
1572 
1573  return self::$_currentDbName;
1574 
1575  }//end getDbName()
1576 
1577 
1587  public static function getDb($conn_id=NULL)
1588  {
1589  if ($conn_id === NULL) {
1590  if (empty(self::$_dbStack) === TRUE) {
1591  throw new DALException('Cannot get current database because no current database exists.');
1592  } else {
1593  $conn_id = self::$_currentDbConnId;
1594  }
1595  }
1596 
1597  // If we were provided a connection ID and it doesn't exist, try
1598  // connecting to it using DALConf settings; otherwise, fail.
1599  if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
1600  try {
1601  $dsn = NULL;
1602  self::dbConnect($dsn, $conn_id);
1603  } catch (DALException $e) {
1604  throw new DALException($e->getMessage());
1605  }
1606  }
1607 
1608  return self::$_dbhPool[$conn_id]['dbh'];
1609 
1610  }//end getDb()
1611 
1612 
1625  public static function getDbType($readable=FALSE, $conn_id=NULL)
1626  {
1627  if ($conn_id === NULL) {
1628  $conn_id = self::$_currentDbConnId;
1629  }
1630 
1631  if (isset(self::$_dbTypes[$conn_id]) === FALSE) {
1632  //$conf = include dirname(__FILE__).'/DALConf.inc';
1633  $dbInfo = self::$_dbhPool[$conn_id];
1634  $dbh = $dbInfo['dbh'];
1635 
1636  $oci_connection_types = array (
1637  'oci8 connection',
1638  'oci8 persistent connection'
1639  );
1640 
1641  if (is_resource($dbh) && in_array(get_resource_type($dbh), $oci_connection_types, true)) {
1642  // OCI: The connection handle for OCI is a resource and not an object
1643  $dbType = 'oci';
1644  } else {
1645  $dbType = $dbh->getAttribute(PDO::ATTR_DRIVER_NAME);
1646  }
1647 
1648  self::$_dbTypes[$conn_id] = $dbType;
1649  } else {
1650  $dbType = self::$_dbTypes[$conn_id];
1651  }
1652 
1653  if ($readable === TRUE) {
1654  return self::$_dbNames[$dbType];
1655  } else {
1656  return $dbType;
1657  }
1658 
1659  }//end getDbType()
1660 
1661 
1670  public static function requireQueryClass($systemid)
1671  {
1672  $classFile = $systemid.'Queries.inc';
1673  $path = self::getOvenPath($systemid).'/'.$classFile;
1674 
1675  require_once($path);
1676 
1677  }//end requireQueryClass()
1678 
1679 
1690  public static function getOvenPath($system=NULL)
1691  {
1692  $path = dirname(__FILE__).'/Oven';
1693 
1694  if ($system !== '') {
1695  $path .= '/'.$system;
1696  }
1697 
1698  return $path;
1699 
1700  }//end getOvenPath()
1701 
1702 
1709  public static function getQueryStorePath()
1710  {
1711  $path = dirname(__FILE__).'/QueryStore';
1712  return $path;
1713 
1714  }//end getQueryStorePath()
1715 
1716 
1726  public static function getQueryObject($id)
1727  {
1728  $queryStore = self::getQueryStorePath();
1729  $path = $queryStore.'/'.$id.'.qob';
1730  if (file_exists($path) === FALSE) {
1731  $msg = 'Query object doesn\'t exist';
1732  throw new DALException($msg);
1733  }
1734 
1735  $content = file_get_contents($path);
1736  $queryObj = unserialize($content);
1737  return $queryObj;
1738 
1739  }//end getQueryObject()
1740 
1741 
1750  public static function getSqlQueriesFromFile($path)
1751  {
1752  $queries = array();
1753  if (file_exists($path) === TRUE) {
1754  $fileContents = file_get_contents($path);
1755  $queries = explode('--$$', $fileContents);
1756  }
1757 
1758  return $queries;
1759 
1760  }//end getSqlQueriesFromFile()
1761 
1762 
1771  public static function isDALQuery($query)
1772  {
1773  if (($query instanceof Query) === TRUE) {
1774  return TRUE;
1775  }
1776 
1777  return FALSE;
1778 
1779  }//end isDALQuery()
1780 
1781 
1790  protected static function _startQueryTimer($query)
1791  {
1792  if (self::$_logQueries === TRUE || defined('SQ_IN_PERFORMANCE_TIMING')) {
1793  self::$_currentQueryLog = array();
1794  if (is_string($query) === true) {
1795  self::$_currentQueryLog['id'] = 'sql';
1796  self::$_currentQueryLog['sql'] = $query;
1797  } else {
1798  self::$_currentQueryLog['id'] = $query->getQueryid();
1799  self::$_currentQueryLog['sql'] = $query->getSql();
1800  }
1801  self::$_currentQueryLog['start'] = microtime(TRUE);
1802  }
1803 
1804  }//end _startQueryTimer()
1805 
1806 
1813  protected static function _endQueryTimer()
1814  {
1815  if (self::$_currentQueryLog !== NULL || defined('SQ_IN_PERFORMANCE_TIMING')) {
1816  self::$_queryLog[] = (microtime(TRUE) - self::$_currentQueryLog['start']);
1817  if (isset($GLOBALS['THE_CONSTRUCT']) === TRUE) {
1818  $GLOBALS['THE_CONSTRUCT']->recordDatabaseQuery(self::$_currentQueryLog['sql'], self::$_currentQueryLog['start'], microtime(TRUE));
1819  }
1820  }
1821  self::$_currentQueryLog = NULL;
1822 
1823  }//end _endQueryTimer()
1824 
1825 
1832  public static function getLoggedQueries()
1833  {
1834  return self::$_queryLog;
1835 
1836  }//end getLoggedQueries()
1837 
1843  public static function clearLoggedQueries()
1844  {
1845  self::$_queryLog = Array();
1846  return;
1847 
1848  }//end getLoggedQueries()
1849 
1850 
1861  public static function setOciCommitOnSuccess ($switch) {
1862  self::$_ociCommitOnSuccess = $switch;
1863  }
1864 
1865 }//end class
1866 
1867 
1868 ?>