15 require_once dirname(__FILE__).
'/Exceptions/DALException.inc';
19 require_once dirname(__FILE__).
'/Query.inc';
62 private static $_dbhPool = NULL;
75 private static $_dbStack = Array();
83 private static $_currentDbConnId =
'';
91 private static $_dbTypes = Array();
102 private static $_inTransaction = FALSE;
112 private static $_dbNames = array(
114 'dblib' =>
'SQLServer',
117 'pgsql' =>
'PostgreSQL',
126 private static $_currentDbName = NULL;
136 private static $_transactionEnabled = FALSE;
144 private static $_queryLog = array();
152 private static $_logQueries = FALSE;
160 private static $_currentQueryLog = NULL;
170 private static $_ociCommitOnSuccess = FALSE;
180 private function __construct()
199 public static function getQuery($systemid, $queryid, $bindValues=TRUE)
202 $class = $systemid.
'Queries';
203 $function =
'prepare'.$queryid.
'Query';
205 self::requireQueryClass($systemid);
208 if (method_exists($class, $function) === FALSE) {
210 throw new DALException(
'Could not load query '.$queryid.
' in system '.$systemid);
213 $eventData = Channels::getCurrentEventBasketData();
214 return call_user_func(array($class, $function), $eventData, $bindValues);
233 $result = self::executePdoAssoc($query, $col);
256 $result = self::executePdoAll($query);
279 $result = self::executePdoOne($query);
306 $queryArray = self::getQuery($systemid, $queryid, FALSE);
309 $queryArray->setExecMethod($method);
328 $result = self::executePdoGrouped($query);
350 $result = self::executePdoGroupedAssoc($query);
369 $query = self::getQuery($systemid, $queryid);
370 $res = self::getGrouped($query);
389 $query = self::getQuery($systemid, $queryid);
390 $res = self::getGroupedAssoc($query);
411 $query = self::getQuery($systemid, $queryid);
412 $res = self::getAssoc($query, $col);
432 $query = self::getQuery($systemid, $queryid);
433 $res = self::getAll($query);
453 $query = self::getQuery($systemid, $queryid);
454 $result = self::getOne($query);
458 if (is_resource($result) === TRUE) {
459 $result = stream_get_contents($result);
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.');
489 $dalQuery = self::getQuery($systemid, $queryid);
490 $query = $dalQuery->prepare();
494 self::execPdoQuery($query);
495 $dalQuery->releaseLobs();
496 }
catch (PDOException $e) {
500 $rows = (int)$query->rowCount();
524 return self::executeQuery($systemid, $queryid);
540 return self::executeAll($systemid, $queryid);
557 if ($execMethod === NULL) {
561 $methodArray = array(
563 'get'.ucfirst($execMethod),
565 $result = call_user_func($methodArray, $query);
582 $query_log =
'unknown query';
587 if ($query instanceof PDOStatement) {
588 $query_log = $query->queryString;
590 self::_startQueryTimer($query_log);
592 $dbh = self::getDb();
594 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
595 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
598 if (self::getDbType() ===
'oci') {
600 if(self::$_ociCommitOnSuccess){
601 $result = oci_execute($query, OCI_COMMIT_ON_SUCCESS);
604 $result = oci_execute($query, OCI_DEFAULT);
606 if ($result === FALSE) {
607 $oci_error = oci_error($query);
608 throw new DALException(
'Unable to execute query: '.$oci_error[
'message']);
610 $rows = oci_num_rows($query);
613 $rows = (int)$query->rowCount();
616 self::_endQueryTimer();
638 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
639 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
643 self::execPdoQuery($query);
644 }
catch (PDOException $e) {
648 if (self::getDbType() ===
'oci') {
650 $dbh = self::getDb();
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);
659 while ($current_row = oci_fetch_array($query, OCI_NUM | OCI_RETURN_LOBS | OCI_RETURN_NULLS)) {
660 $result[] = $current_row[$col];
666 $result = $query->fetchAll(PDO::FETCH_COLUMN, $col);
668 $result = $query->fetchAll(PDO::FETCH_ASSOC);
687 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
688 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
692 self::execPdoQuery($query);
693 }
catch (PDOException $e) {
697 if (self::getDbType() ===
'oci') {
699 $dbh = self::getDb();
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);
705 $result = $query->fetchAll();
724 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
725 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
730 self::execPdoQuery($query);
731 }
catch (PDOException $e) {
736 if (self::getDbType() ===
'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);
743 $row = $query->fetch(PDO::FETCH_NUM);
746 if ($row === FALSE)
break;
748 if (isset($result[$row[0]]) === FALSE) {
749 $result[$row[0]] = array();
754 while (isset($row[$i]) === TRUE) {
755 $current[] = $row[$i];
759 $result[$row[0]][] = $current;
778 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
779 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
785 self::execPdoQuery($query);
786 }
catch (PDOException $e) {
791 if (self::getDbType() ===
'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);
798 $row = $query->fetch(PDO::FETCH_ASSOC);
801 if ($row === FALSE)
break;
805 if (isset($first_field) === FALSE) {
807 $first_field = key($row);
809 $first_value = $row[$first_field];
811 if (isset($result[$first_value]) === FALSE) {
812 $result[$first_value] = array();
816 unset($current[$first_field]);
817 $result[$first_value][] = $current;
836 if (!((gettype($query) !==
'PDOStatement') || (is_resource($query) && (get_resource_type($query) ===
'oci8 statement')))) {
837 throw new Exception(
'Invalid parameter 1 given to '.__FUNCTION__.
'()');
841 self::execPdoQuery($query);
842 }
catch (PDOException $e) {
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];
850 $result = $query->fetchColumn();
852 if (is_resource($result) === TRUE) {
853 $result = stream_get_contents($result);
875 $dbh = self::getDb();
877 if (self::getDbType() ===
'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']);
885 self::execPdoQuery($query);
886 $rows = oci_num_rows($query);
888 if ($rows === FALSE) {
893 self::_startQueryTimer($sql);
894 $rows = $dbh->exec($sql);
895 self::_endQueryTimer();
896 }
catch (PDOException $e) {
922 $dbh = self::getDb();
924 if (self::getDbType() ===
'oci') {
926 $query = oci_parse($dbh, $sql);
928 $query = $dbh->prepare($sql);
930 return self::executePdoAssoc($query, $col);
945 $dbh = self::getDb();
947 if (self::getDbType() ===
'oci') {
949 $query = oci_parse($dbh, $sql);
951 $query = $dbh->prepare($sql);
953 $res = self::executePdoAll($query);
971 $dbh = self::getDb();
973 if (self::getDbType() ===
'oci') {
975 $query = oci_parse($dbh, $sql);
977 $query = $dbh->prepare($sql);
979 $res = self::executePdoGrouped($query);
997 $dbh = self::getDb();
999 if (self::getDbType() ===
'oci') {
1001 $query = oci_parse($dbh, $sql);
1003 $query = $dbh->prepare($sql);
1005 $res = self::executePdoGroupedAssoc($query);
1022 $dbh = self::getDb();
1024 if (self::getDbType() ===
'oci') {
1026 $query = oci_parse($dbh, $sql);
1028 $query = $dbh->prepare($sql);
1030 $res = self::executePdoOne($query);
1053 $queries = explode(
';', $sql);
1054 if (empty($queries) === FALSE) {
1055 foreach ($queries as $query) {
1056 if (trim($query) !==
'') {
1057 self::executeSql($query);
1075 $dbh = self::getDb();
1076 self::_startQueryTimer($sql);
1077 $result = $dbh->query($sql);
1078 self::_endQueryTimer();
1092 $currentDb = self::$_currentDbConnId;
1093 $dbInfo = self::$_dbhPool[$currentDb];
1095 if ($dbInfo[
'transactionSupport'] === TRUE) {
1096 $dbh = self::getDb();
1098 if (self::getDbType() ===
'oci') {
1102 $dbh->beginTransaction();
1104 self::$_dbhPool[$currentDb][
'inTransaction'] = TRUE;
1118 $currentDb = self::$_currentDbConnId;
1120 if (self::$_dbhPool[$currentDb][
'inTransaction'] === TRUE) {
1121 $dbh = self::getDb();
1123 if (self::getDbType() ===
'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']);
1133 self::$_dbhPool[$currentDb][
'inTransaction'] = FALSE;
1149 $currentDb = self::$_currentDbConnId;
1151 if (self::$_dbhPool[$currentDb][
'inTransaction'] === TRUE) {
1152 $dbh = self::getDb();
1154 if (self::getDbType() ===
'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']);
1164 self::$_dbhPool[$currentDb][
'inTransaction'] = FALSE;
1183 $dbh = self::getDb();
1184 return (
int)$dbh->lastInsertId($sequenceName);
1209 public static function dbConnect(array &$dsn=NULL, $conn_id=
'db', $oci_force_new = FALSE)
1212 if ($dsn === NULL) {
1215 $dsn = self::getDsnFromConfig($conn_id);
1219 require_once dirname(__FILE__).
'/DSNManager.inc';
1228 throw new Exception(
"Unable to connect to database '$conn_id': Fail to connect to any DB in the DSN Pool.");
1233 if (isset($dsn[
'user']) === TRUE) {
1234 $user = $dsn[
'user'];
1237 if (isset($dsn[
'password']) === TRUE) {
1238 $pass = $dsn[
'password'];
1241 $persistent =
false;
1242 if (isset($dsn[
'persistent']) && $dsn[
'persistent'] ==
true) {
1246 if ($dsn[
'type'] ===
'oci') {
1252 $oci_connect_fn =
'oci_connect';
1254 $oci_connect_fn =
'oci_pconnect';
1257 $oci_connect_fn =
'oci_new_connect';
1260 if (isset($dsn[
'encoding'])) {
1261 $new_dbh = @$oci_connect_fn($dsn[
'user'], $dsn[
'password'], $dsn[
'DSN'], $dsn[
'encoding']);
1263 $new_dbh = @$oci_connect_fn($dsn[
'user'], $dsn[
'password'], $dsn[
'DSN']);
1266 if ($new_dbh === FALSE) {
1267 $oci_error = oci_error();
1269 $err_msg =
'Unable to connect to database "'.$conn_id.
'": '.$oci_error[
'code'].
' '.$oci_error[
'message'];
1272 log_error($err_msg, E_USER_WARNING);
1277 throw new Exception($err_msg);
1282 $extra_params = array();
1285 $extra_params[PDO::ATTR_PERSISTENT] =
true;
1288 if (isset($dsn[
'timeout']) && is_int($dsn[
'timeout'])) {
1289 $extra_params[PDO::ATTR_TIMEOUT] = (int)$dsn[
'timeout'];
1293 $new_dbh =
new PDO($dsn[
'DSN'], $user, $pass, $extra_params);
1294 }
catch (Exception $conn_e) {
1297 log_error(
"Unable to connect to database '$conn_id': ".$conn_e->getMessage(), E_USER_WARNING);
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);
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);
1316 }
while ($new_dbh === FALSE);
1318 self::$_dbhPool[$conn_id] = array(
1320 'dsn' => $dsn[
'DSN'],
1321 'dbType' => $dsn[
'type'],
1322 'userName' => $user,
1323 'password' => $pass,
1329 #self::changeDb($conn_id);
1331 #if (self::transactionSupport($conn_id) === TRUE) {
1332 self::$_dbhPool[$conn_id][
'transactionSupport'] = TRUE;
1334 # self::$_dbhPool[$conn_id]['transactionSupport'] = FALSE;
1339 self::$_dbhPool[$conn_id][
'inTransaction'] = FALSE;
1341 }
catch (PDOException $e) {
1345 return self::$_dbhPool[$conn_id][
'dbh'];
1361 if (self::dbConnected($conn_id) === FALSE) {
1362 throw new DALException(
'Connection "'.$conn_id.
'" must be connected before it can be changed to.');
1365 array_push(self::$_dbStack, $conn_id);
1366 self::$_currentDbConnId = $conn_id;
1380 if (empty(self::$_dbStack) === TRUE) {
1381 throw new DALException(
'The database connection stack is empty; there is no previous connection to restore.');
1384 array_pop(self::$_dbStack);
1386 if (empty(self::$_dbStack) === TRUE) {
1387 self::$_currentDbConnId =
'';
1389 self::$_currentDbConnId = self::$_dbStack[count(self::$_dbStack) - 1];
1404 if (empty(self::$_dbStack) === TRUE) {
1405 throw new DALException(
'The database connection stack is empty.');
1408 return self::$_currentDbConnId;
1428 $dbh = self::getDb($conn_id);
1429 $dbh->beginTransaction();
1430 self::$_dbhPool[$conn_id][
'inTransaction'] = TRUE;
1431 }
catch (PDOException $e) {
1453 if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
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) {
1459 throw new DALException(
'Connection with ID "'.$conn_id.
'" cannot be closed because it still exists in the stack.');
1461 if (self::getDbType(FALSE, $conn_id) ===
'oci') {
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']);
1470 unset(self::$_dbhPool[$conn_id]);
1490 if ($conn_id === NULL) {
1491 return !empty(self::$_dbhPool);
1493 return isset(self::$_dbhPool[$conn_id]);
1510 if ($conn_id === NULL) {
1511 $conn_id = self::$_currentDbConnId;
1514 if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
1515 $error =
'DAL configuration not defined for connection ID "'.$conn_id.
'".';
1518 $dsn = self::$_dbhPool[$conn_id];
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.
'".';
1542 }
else if (isset($dsn[$conn_id][
'DSN']) === FALSE) {
1543 $error =
'DAL configuration for connection ID "'.$conn_id.
'" does not define a DSN.';
1547 return $dsn[$conn_id];
1560 if (self::$_[$conn_id] === NULL) {
1562 $dsn = self::getDsn();
1563 if (isset($dsn[
'DSN']) === TRUE) {
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];
1573 return self::$_currentDbName;
1587 public static function getDb($conn_id=NULL)
1589 if ($conn_id === NULL) {
1590 if (empty(self::$_dbStack) === TRUE) {
1591 throw new DALException(
'Cannot get current database because no current database exists.');
1593 $conn_id = self::$_currentDbConnId;
1599 if (isset(self::$_dbhPool[$conn_id]) === FALSE) {
1602 self::dbConnect($dsn, $conn_id);
1608 return self::$_dbhPool[$conn_id][
'dbh'];
1625 public static function getDbType($readable=FALSE, $conn_id=NULL)
1627 if ($conn_id === NULL) {
1628 $conn_id = self::$_currentDbConnId;
1631 if (isset(self::$_dbTypes[$conn_id]) === FALSE) {
1633 $dbInfo = self::$_dbhPool[$conn_id];
1634 $dbh = $dbInfo[
'dbh'];
1636 $oci_connection_types = array (
1638 'oci8 persistent connection'
1641 if (is_resource($dbh) && in_array(get_resource_type($dbh), $oci_connection_types,
true)) {
1645 $dbType = $dbh->getAttribute(PDO::ATTR_DRIVER_NAME);
1648 self::$_dbTypes[$conn_id] = $dbType;
1650 $dbType = self::$_dbTypes[$conn_id];
1653 if ($readable === TRUE) {
1654 return self::$_dbNames[$dbType];
1672 $classFile = $systemid.
'Queries.inc';
1673 $path = self::getOvenPath($systemid).
'/'.$classFile;
1675 require_once($path);
1692 $path = dirname(__FILE__).
'/Oven';
1694 if ($system !==
'') {
1695 $path .=
'/'.$system;
1711 $path = dirname(__FILE__).
'/QueryStore';
1728 $queryStore = self::getQueryStorePath();
1729 $path = $queryStore.
'/'.$id.
'.qob';
1730 if (file_exists($path) === FALSE) {
1731 $msg =
'Query object doesn\'t exist';
1735 $content = file_get_contents($path);
1736 $queryObj = unserialize($content);
1753 if (file_exists($path) === TRUE) {
1754 $fileContents = file_get_contents($path);
1755 $queries = explode(
'--$$', $fileContents);
1773 if (($query instanceof
Query) === TRUE) {
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;
1798 self::$_currentQueryLog[
'id'] = $query->getQueryid();
1799 self::$_currentQueryLog[
'sql'] = $query->getSql();
1801 self::$_currentQueryLog[
'start'] = microtime(TRUE);
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));
1821 self::$_currentQueryLog = NULL;
1834 return self::$_queryLog;
1845 self::$_queryLog = Array();
1862 self::$_ociCommitOnSuccess = $switch;