diff options
author | Jörn Friedrich Dreyer <jfd@butonic.de> | 2013-10-30 22:52:10 +0400 |
---|---|---|
committer | Jörn Friedrich Dreyer <jfd@butonic.de> | 2013-10-31 01:15:49 +0400 |
commit | 906a08a36e27b8d03a211c0fade37316dd2e3b02 (patch) | |
tree | f48577ee4154b626a9fc8151815231f2621e451d /lib/db.php | |
parent | 1a3ab036c0c4d30bc06c8a56746d3034f926913a (diff) |
backport executeAudited()
Diffstat (limited to 'lib/db.php')
-rw-r--r-- | lib/db.php | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/lib/db.php b/lib/db.php index 572cfd6d074..633bbf4d004 100644 --- a/lib/db.php +++ b/lib/db.php @@ -427,7 +427,55 @@ class OC_DB { } return false; } - + + /** + * @brief execute a prepared statement, on error write log and throw exception + * @param mixed $stmt OC_DB_StatementWrapper, + * an array with 'sql' and optionally 'limit' and 'offset' keys + * .. or a simple sql query string + * @param array $parameters + * @return result + * @throws DatabaseException + */ + static public function executeAudited( $stmt, array $parameters = null) { + if (is_string($stmt)) { + // convert to an array with 'sql' + if (stripos($stmt,'LIMIT') !== false) { //OFFSET requires LIMIT, se we only neet to check for LIMIT + // TODO try to convert LIMIT OFFSET notation to parameters, see fixLimitClauseForMSSQL + $message = 'LIMIT and OFFSET are forbidden for portability reasons,' + . ' pass an array with \'limit\' and \'offset\' instead'; + throw new DatabaseException($message); + } + $stmt = array('sql' => $stmt, 'limit' => null, 'offset' => null); + } + if (is_array($stmt)){ + // convert to prepared statement + if ( ! array_key_exists('sql', $stmt) ) { + $message = 'statement array must at least contain key \'sql\''; + throw new DatabaseException($message); + } + if ( ! array_key_exists('limit', $stmt) ) { + $stmt['limit'] = null; + } + if ( ! array_key_exists('limit', $stmt) ) { + $stmt['offset'] = null; + } + $stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']); + } + if ($stmt instanceof PDOStatementWrapper || $stmt instanceof MDB2_Statement_Common) { + $result = $stmt->execute($parameters); + self::raiseExceptionOnError($result, 'Could not execute statement'); + } else { + if (is_object($stmt)) { + $message = 'Expected a prepared statement or array got ' . get_class($stmt); + } else { + $message = 'Expected a prepared statement or array got ' . gettype($stmt); + } + throw new DatabaseException($message); + } + return $result; + } + /** * @brief gets last value of autoincrement * @param string $table The optional table name (will replace *PREFIX*) and add sequence suffix @@ -1001,6 +1049,32 @@ class OC_DB { return false; } + /** + * check if a result is an error, writes a log entry and throws an exception, works with MDB2 and PDOException + * @param mixed $result + * @param string message + * @return void + * @throws DatabaseException + */ + public static function raiseExceptionOnError($result, $message = null) { + if(self::isError($result)) { + if ($message === null) { + $message = self::getErrorMessage($result); + } else { + $message .= ', Root cause:' . self::getErrorMessage($result); + } + throw new DatabaseException($message, self::getErrorCode($result)); + } + } + + public static function getErrorCode($error) { + if ( self::$backend==self::BACKEND_MDB2 and PEAR::isError($error) ) { + $code = $error->getCode(); + } elseif ( self::$backend==self::BACKEND_PDO and self::$PDO ) { + $code = self::$PDO->errorCode(); + } + return $code; + } /** * returns the error code and message as a string for logging |