summaryrefslogtreecommitdiffstats
path: root/lib/db.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/db.php')
-rw-r--r--lib/db.php173
1 files changed, 101 insertions, 72 deletions
diff --git a/lib/db.php b/lib/db.php
index e38d464e755..d911e14804f 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -199,12 +199,13 @@ class OC_DB {
* @param string $query Query string
* @param int $limit
* @param int $offset
+ * @param bool $isManipulation
* @throws DatabaseException
* @return \Doctrine\DBAL\Statement prepared SQL query
*
* SQL query via Doctrine prepare(), needs to be execute()'d!
*/
- static public function prepare( $query , $limit=null, $offset=null ) {
+ static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
if (!is_null($limit) && $limit != -1) {
if ($limit === -1) {
@@ -225,6 +226,12 @@ class OC_DB {
OC_Log::write('core', 'DB prepare : '.$query, OC_Log::DEBUG);
}
self::connect();
+
+ if ($isManipulation === null) {
+ //try to guess, so we return the number of rows on manipulations
+ $isManipulation = self::isManipulation($query);
+ }
+
// return the result
if (self::$backend == self::BACKEND_DOCTRINE) {
try {
@@ -232,7 +239,8 @@ class OC_DB {
} catch(\Doctrine\DBAL\DBALException $e) {
throw new \DatabaseException($e->getMessage(), $query);
}
- $result=new OC_DB_StatementWrapper($result);
+ // differentiate between query and manipulation
+ $result=new OC_DB_StatementWrapper($result, $isManipulation);
}
if ((is_null($limit) || $limit == -1) and self::$cachingEnabled ) {
$type = OC_Config::getValue( "dbtype", "sqlite" );
@@ -242,7 +250,33 @@ class OC_DB {
}
return $result;
}
-
+
+ /**
+ * tries to guess the type of statement based on the first 10 characters
+ * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
+ *
+ * @param string $sql
+ */
+ static public function isManipulation( $sql ) {
+ $selectOccurence = stripos ($sql, "SELECT");
+ if ($selectOccurence !== false && $selectOccurence < 10) {
+ return false;
+ }
+ $insertOccurence = stripos ($sql, "INSERT");
+ if ($insertOccurence !== false && $insertOccurence < 10) {
+ return true;
+ }
+ $updateOccurence = stripos ($sql, "UPDATE");
+ if ($updateOccurence !== false && $updateOccurence < 10) {
+ return true;
+ }
+ $deleteOccurance = stripos ($sql, "DELETE");
+ if ($deleteOccurance !== false && $deleteOccurance < 10) {
+ return true;
+ }
+ return false;
+ }
+
/**
* @brief execute a prepared statement, on error write log and throw exception
* @param mixed $stmt OC_DB_StatementWrapper,
@@ -399,7 +433,7 @@ class OC_DB {
* @brief Insert a row if a matching row doesn't exists.
* @param string $table. The table to insert into in the form '*PREFIX*tableName'
* @param array $input. An array of fieldname/value pairs
- * @return bool return value from OC_DB_StatementWrapper->execute()
+ * @returns int number of updated rows
*/
public static function insertIfNotExist($table, $input) {
self::connect();
@@ -433,7 +467,7 @@ class OC_DB {
. implode('`,`', array_keys($input)) . '`) VALUES('
. str_repeat('?,', count($input)-1).'? ' . ')';
} else {
- return true;
+ return 0; //no rows updated
}
} elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql' || $type == 'mssql') {
$query = 'INSERT INTO `' .$table . '` (`'
@@ -497,9 +531,9 @@ class OC_DB {
$query = str_replace( 'now()', 'CURRENT_TIMESTAMP', $query );
$query = str_replace( 'LENGTH(', 'LEN(', $query );
$query = str_replace( 'SUBSTR(', 'SUBSTRING(', $query );
-
- $query = self::fixLimitClauseForMSSQL($query);
- }
+
+ $query = self::fixLimitClauseForMSSQL($query);
+ }
// replace table name prefix
$query = str_replace( '*PREFIX*', $prefix, $query );
@@ -507,60 +541,60 @@ class OC_DB {
return $query;
}
- private static function fixLimitClauseForMSSQL($query) {
- $limitLocation = stripos ($query, "LIMIT");
-
- if ( $limitLocation === false ) {
- return $query;
- }
-
- // total == 0 means all results - not zero results
- //
- // First number is either total or offset, locate it by first space
- //
- $offset = substr ($query, $limitLocation + 5);
- $offset = substr ($offset, 0, stripos ($offset, ' '));
- $offset = trim ($offset);
-
- // check for another parameter
- if (stripos ($offset, ',') === false) {
- // no more parameters
- $offset = 0;
- $total = intval ($offset);
- } else {
- // found another parameter
- $offset = intval ($offset);
-
- $total = substr ($query, $limitLocation + 5);
- $total = substr ($total, stripos ($total, ','));
-
- $total = substr ($total, 0, stripos ($total, ' '));
- $total = intval ($total);
- }
-
- $query = trim (substr ($query, 0, $limitLocation));
-
- if ($offset == 0 && $total !== 0) {
- if (strpos($query, "SELECT") === false) {
- $query = "TOP {$total} " . $query;
- } else {
- $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query);
- }
- } else if ($offset > 0) {
- $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query);
- $query = 'SELECT *
- FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3
- FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3';
-
- if ($total > 0) {
- $query .= ' WHERE line3 BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total);
- } else {
- $query .= ' WHERE line3 > ' . $offset;
- }
- }
- return $query;
- }
-
+ private static function fixLimitClauseForMSSQL($query) {
+ $limitLocation = stripos ($query, "LIMIT");
+
+ if ( $limitLocation === false ) {
+ return $query;
+ }
+
+ // total == 0 means all results - not zero results
+ //
+ // First number is either total or offset, locate it by first space
+ //
+ $offset = substr ($query, $limitLocation + 5);
+ $offset = substr ($offset, 0, stripos ($offset, ' '));
+ $offset = trim ($offset);
+
+ // check for another parameter
+ if (stripos ($offset, ',') === false) {
+ // no more parameters
+ $offset = 0;
+ $total = intval ($offset);
+ } else {
+ // found another parameter
+ $offset = intval ($offset);
+
+ $total = substr ($query, $limitLocation + 5);
+ $total = substr ($total, stripos ($total, ','));
+
+ $total = substr ($total, 0, stripos ($total, ' '));
+ $total = intval ($total);
+ }
+
+ $query = trim (substr ($query, 0, $limitLocation));
+
+ if ($offset == 0 && $total !== 0) {
+ if (strpos($query, "SELECT") === false) {
+ $query = "TOP {$total} " . $query;
+ } else {
+ $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query);
+ }
+ } else if ($offset > 0) {
+ $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query);
+ $query = 'SELECT *
+ FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3
+ FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3';
+
+ if ($total > 0) {
+ $query .= ' WHERE line3 BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total);
+ } else {
+ $query .= ' WHERE line3 > ' . $offset;
+ }
+ }
+ return $query;
+ }
+
/**
* @brief drop a table
* @param string $tableName the table to drop
@@ -619,11 +653,8 @@ class OC_DB {
* @return bool
*/
public static function isError($result) {
- if(!$result) {
- return true;
- } else {
- return false;
- }
+ //Doctrine returns false on error (and throws an exception)
+ return $result === false;
}
/**
* check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
@@ -661,13 +692,11 @@ class OC_DB {
$msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
$msg .= 'Driver Code = '.$errorInfo[1] . ', ';
$msg .= 'Driver Message = '.$errorInfo[2];
- } else {
- $msg = '';
}
- } else {
- $msg = '';
+ return $msg;
}
- return $msg;
+
+ return '';
}
/**