From: Bart Visscher Date: Mon, 24 Jun 2013 06:27:25 +0000 (+0200) Subject: Merge branch 'master' into doctrine X-Git-Tag: v6.0.0alpha2~444^2~25 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=377e9a8677afc92bca61fb1bb055901db8457896;p=nextcloud-server.git Merge branch 'master' into doctrine --- 377e9a8677afc92bca61fb1bb055901db8457896 diff --cc 3rdparty index 40be157ee23,e312294ef62..691791a4f74 --- a/3rdparty +++ b/3rdparty @@@ -1,1 -1,1 +1,1 @@@ - Subproject commit 40be157ee23753c02481c02e1b60ae699202bf78 -Subproject commit e312294ef62873df2b8c02e774f9dfe1b7fbc38d ++Subproject commit 691791a4f743aaa83546736928e3ce18574f3c03 diff --cc lib/db.php index 7db7711b376,a6b81aaba69..8bd3964492a --- a/lib/db.php +++ b/lib/db.php @@@ -20,12 -20,11 +20,13 @@@ * */ -class DatabaseException extends Exception{ +define('MDB2_SCHEMA_DUMP_STRUCTURE', '1'); + +class DatabaseException extends Exception { private $query; - public function __construct($message, $query) { + //FIXME getQuery seems to be unused, maybe use parent constructor with $message, $code and $previous + public function __construct($message, $query = null){ parent::__construct($message); $this->query = $query; } @@@ -251,12 -392,62 +252,62 @@@ class OC_DB return $result; } + /** + * @brief execute a prepared statement, on error write log and throw exception - * @param mixed $stmt PDOStatementWrapper | MDB2_Statement_Common , ++ * @param mixed $stmt DoctrineStatementWrapperm, + * 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']); + } + self::raiseExceptionOnError($stmt, 'Could not prepare statement'); - if ($stmt instanceof PDOStatementWrapper || $stmt instanceof MDB2_Statement_Common) { ++ if ($stmt instanceof DoctrineStatementWrapper) { + $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 * @return int id + * @throws DatabaseException * - * MDB2 lastInsertID() + * \Doctrine\DBAL\Connection lastInsertId * * Call this method right after the insert command or other functions may * cause trouble! @@@ -274,7 -465,7 +325,7 @@@ $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); $table = str_replace( '*PREFIX*', $prefix, $table ); } - return self::$connection->lastInsertId($table); - $result = self::$connection->lastInsertId($table); ++ self::$connection->lastInsertId($table); } else { if($table !== null) { $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); @@@ -428,17 -714,12 +475,12 @@@ } try { - $result = self::prepare($query); + $result = self::executeAudited($query, $inserts); - } catch(PDOException $e) { + } catch(\Doctrine\DBAL\DBALException $e) { - $entry = 'DB Error: "'.$e->getMessage() . '"
'; - $entry .= 'Offending command was: ' . $query.'
'; - OC_Log::write('core', $entry, OC_Log::FATAL); - error_log('DB error: ' . $entry); - OC_Template::printErrorPage( $entry ); - return false; + OC_Template::printExceptionErrorPage( $e ); } - return $result->execute($inserts); + return $result; } /** @@@ -607,10 -927,35 +649,31 @@@ return false; } } + /** - * check if a result is an error and throws an exception, works with MDB2 and PDOException ++ * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException + * @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(); - } ++ $code = self::$connection->errorCode(); + return $code; + } /** * returns the error code and message as a string for logging - * works with MDB2 and PDOException + * works with DoctrineException * @param mixed $error * @return string */