9 namespace Fossology\Lib\Db;
19 protected $preparedStatements;
23 protected $cumulatedTime = array();
25 protected $queryCount = array();
27 private $transactionDepth = 0;
29 function __construct(Logger $logger)
31 $this->preparedStatements = array();
32 $this->logger = $logger;
38 $this->dbDriver = $dbDriver;
44 return $this->dbDriver;
47 public function begin()
49 if ($this->transactionDepth==0) {
50 $this->dbDriver->begin();
52 $this->transactionDepth++;
55 public function commit()
57 $this->transactionDepth--;
58 if ($this->transactionDepth==0) {
59 $this->dbDriver->commit();
60 }
else if ($this->transactionDepth < 0) {
61 throw new \Exception(
'too much transaction commits');
65 public function rollback()
67 if ($this->transactionDepth > 0) {
68 $this->transactionDepth--;
69 $this->dbDriver->rollback();
70 }
else if ($this->transactionDepth == 0) {
71 throw new \Exception(
'too much transaction rollbacks');
80 abstract public function prepare($statementName, $sqlStatement);
94 $sqlStatement .=
" RETURNING $returning";
95 $statementName .=
".returning:$returning";
96 $this->
prepare($statementName,$sqlStatement);
97 $res = $this->
execute($statementName,$params);
100 return $return[$returning];
109 abstract public function execute($statementName, $params = array());
118 if ($result !==
false) {
122 if ($this->dbDriver->isConnected()) {
123 $lastError = $this->dbDriver->getLastError();
124 $this->logger->critical($lastError);
125 if ($this->transactionDepth>0) {
126 $this->dbDriver->rollback();
129 $this->logger->critical(
"DB connection lost.");
132 $message =
"error executing: $sqlStatement\n\n$lastError";
142 public function getSingleRow($sqlStatement, $params = array(), $statementName =
"")
144 if (empty($statementName)) {
145 $backtrace = debug_backtrace();
146 $caller = $backtrace[1];
147 $statementName = (array_key_exists(
'class', $caller) ?
"$caller[class]::" :
'') .
"$caller[function]";
149 if (!array_key_exists($statementName, $this->preparedStatements)) {
150 $this->
prepare($statementName, $sqlStatement);
152 $res = $this->
execute($statementName, $params);
153 $row = $this->dbDriver->fetchArray($res);
154 $this->dbDriver->freeResult($res);
164 public function getRows($sqlStatement, $params = array(), $statementName =
"")
166 if (empty($statementName)) {
167 $backtrace = debug_backtrace();
168 $caller = $backtrace[1];
169 $statementName = (array_key_exists(
'class', $caller) ?
"$caller[class]::" :
'') .
"$caller[function]";
171 if (!array_key_exists($statementName, $this->preparedStatements)) {
172 $this->
prepare($statementName, $sqlStatement);
174 $res = $this->
execute($statementName, $params);
175 $rows = $this->dbDriver->fetchAll($res);
176 $this->dbDriver->freeResult($res);
187 if (empty($sqlLog)) {
188 $sqlLog = $sqlStatement;
190 $startTime = microtime($get_as_float =
true);
191 $res = $this->dbDriver->query($sqlStatement);
194 $execTime = microtime($get_as_float =
true) - $startTime;
204 return $this->dbDriver->freeResult($res);
213 return $this->dbDriver->fetchArray($res);
222 return $this->dbDriver->fetchAll($res);
232 public function createMap($tableName,$keyColumn,$valueColumn,$sqlLog=
'')
234 if (empty($sqlLog)) {
235 $sqlLog = __METHOD__ .
".$tableName.$keyColumn,$valueColumn";
237 $this->
prepare($sqlLog,
"select $keyColumn,$valueColumn from $tableName");
238 $res = $this->
execute($sqlLog);
241 $map[$row[$keyColumn]] = $row[$valueColumn];
247 public function flushStats()
249 foreach ($this->cumulatedTime as $statementName => $seconds) {
250 $queryCount = $this->queryCount[$statementName];
251 $this->logger->debug(
"executing '$statementName' took "
253 .
" ($queryCount queries" . ($queryCount > 0 ?
", avg " . $this->
formatMilliseconds($seconds / $queryCount) :
"") .
")");
256 if ($this->transactionDepth != 0) {
257 throw new \Fossology\Lib\Exception(
"you have not committed enough");
267 return sprintf(
"%0.3fms", 1000 * $seconds);
276 $this->cumulatedTime[$statementName] += $execTime;
277 $this->queryCount[$statementName]++;
280 public function booleanFromDb($booleanValue)
282 return $this->dbDriver->booleanFromDb($booleanValue);
285 public function booleanToDb($booleanValue)
287 return $this->dbDriver->booleanToDb($booleanValue);
290 private function cleanupParamsArray($params)
292 $nParams =
sizeof($params);
293 for ($i = 0; $i<$nParams; $i++) {
294 if (is_bool($params[$i])) {
295 $params[$i] = $this->dbDriver->booleanToDb($params[$i]);
309 public function insertInto($tableName, $keys, $params, $sqlLog=
'', $returning=
'')
311 if (empty($sqlLog)) {
312 $sqlLog = __METHOD__ .
".$tableName.$keys" . (empty($returning) ?
"" : md5($returning));
314 $sql =
"INSERT INTO $tableName ($keys) VALUES (";
315 $nKeys = substr_count($keys,
',')+1;
316 for ($i = 1; $i < $nKeys; $i++) {
319 $sql .=
'$'.$nKeys.
')';
320 $params = $this->cleanupParamsArray($params);
321 if (!empty($returning)) {
325 $res = $this->
execute($sqlLog,$params);
338 $params = array_values($assocParams);
339 $keys = implode(
',',array_keys($assocParams));
340 if (empty($sqlLog)) {
341 $sqlLog = __METHOD__ .
".$tableName.$keys" . (empty($returning) ?
"" : md5($returning));
343 return $this->
insertInto($tableName, $keys, $params, $sqlLog, $returning);
346 public function updateTableRow($tableName, $assocParams, $idColName, $id, $sqlLog=
'')
348 $params = array_values($assocParams);
349 $keys = array_keys($assocParams);
350 $nKeys =
sizeof($keys);
352 if (empty($sqlLog)) {
353 $sqlLog = __METHOD__ .
".$tableName." . implode(
",", $keys);
356 $sql =
"UPDATE $tableName SET";
357 for ($i = 1; $i < $nKeys; $i++) {
358 $sql .=
" ".$keys[$i - 1].
' = $'.$i.
",";
360 $sql .=
" ".$keys[$nKeys - 1].
' = $'.$nKeys;
361 $sql .=
" WHERE $idColName = \$".($nKeys + 1);
364 $params = $this->cleanupParamsArray($params);
367 $res = $this->
execute($sqlLog,$params);
378 if (! preg_match(
'/^[a-z0-9_]+$/i',$tableName)) {
379 throw new \Exception(
"invalid table name '$tableName'");
381 return $this->dbDriver->existsTable($tableName);
392 if (! preg_match(
'/^[a-z0-9_]+$/i',$columnName)) {
393 throw new \Exception(
"invalid column name '$columnName'");
395 return $this->
existsTable($tableName) && $this->dbDriver->existsColumn($tableName, $columnName);
execute($statementName, $params=array())
insertPreparedAndReturn($statementName, $sqlStatement, $params, $returning)
getRows($sqlStatement, $params=array(), $statementName="")
createMap($tableName, $keyColumn, $valueColumn, $sqlLog='')
checkResult($result, $sqlStatement="")
Check the result for unexpected errors. If found, treat them as fatal.
existsColumn($tableName, $columnName)
queryOnce($sqlStatement, $sqlLog='')
formatMilliseconds($seconds)
collectStatistics($statementName, $execTime)
getSingleRow($sqlStatement, $params=array(), $statementName="")
insertTableRow($tableName, $assocParams, $sqlLog='', $returning='')
prepare($statementName, $sqlStatement)
setDriver(Driver &$dbDriver)
insertInto($tableName, $keys, $params, $sqlLog='', $returning='')