diff options
author | Vincent Petry <pvince81@owncloud.com> | 2015-03-26 16:30:25 +0100 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2015-03-26 16:30:25 +0100 |
commit | c0bcaa49804eb82fa23f3624e68b7e62c8ac687a (patch) | |
tree | 79d3d13f668ebeadc900388f9b29d2e9c689fb6a /lib | |
parent | e12c76ed666d2646d52e68b65f89acdb6558094f (diff) | |
parent | 9ad48e0fe9377189dc3ff09a820b7dc61d31ef9f (diff) | |
download | nextcloud-server-c0bcaa49804eb82fa23f3624e68b7e62c8ac687a.tar.gz nextcloud-server-c0bcaa49804eb82fa23f3624e68b7e62c8ac687a.zip |
Merge pull request #14914 from owncloud/backport-14766-compare-array-insertifnotexists
[Stable8] Backport 14766 compare array insertifnotexists
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/allconfig.php | 15 | ||||
-rw-r--r-- | lib/private/db.php | 17 | ||||
-rw-r--r-- | lib/private/db/adapter.php | 40 | ||||
-rw-r--r-- | lib/private/db/adaptersqlite.php | 37 | ||||
-rw-r--r-- | lib/private/db/connection.php | 21 | ||||
-rw-r--r-- | lib/private/db/mdb2schemamanager.php | 2 | ||||
-rw-r--r-- | lib/private/files/cache/cache.php | 14 | ||||
-rw-r--r-- | lib/private/files/cache/storage.php | 15 | ||||
-rw-r--r-- | lib/public/db.php | 24 | ||||
-rw-r--r-- | lib/public/idbconnection.php | 27 |
10 files changed, 105 insertions, 107 deletions
diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php index d729936bc32..f591bfe3128 100644 --- a/lib/private/allconfig.php +++ b/lib/private/allconfig.php @@ -188,11 +188,18 @@ class AllConfig implements \OCP\IConfig { return; } - $data = array($value, $userId, $appName, $key); + $affectedRows = 0; if (!$exists && $preCondition === null) { - $sql = 'INSERT INTO `*PREFIX*preferences` (`configvalue`, `userid`, `appid`, `configkey`)'. - 'VALUES (?, ?, ?, ?)'; + $this->connection->insertIfNotExist('*PREFIX*preferences', [ + 'configvalue' => $value, + 'userid' => $userId, + 'appid' => $appName, + 'configkey' => $key, + ], ['configkey', 'userid', 'appid']); + $affectedRows = 1; } elseif ($exists) { + $data = array($value, $userId, $appName, $key); + $sql = 'UPDATE `*PREFIX*preferences` SET `configvalue` = ? '. 'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? '; @@ -205,8 +212,8 @@ class AllConfig implements \OCP\IConfig { } $data[] = $preCondition; } + $affectedRows = $this->connection->executeUpdate($sql, $data); } - $affectedRows = $this->connection->executeUpdate($sql, $data); // only add to the cache if we already loaded data for the user if ($affectedRows > 0 && isset($this->userCache[$userId])) { diff --git a/lib/private/db.php b/lib/private/db.php index dc25092e276..c2654926696 100644 --- a/lib/private/db.php +++ b/lib/private/db.php @@ -20,8 +20,6 @@ * */ -define('MDB2_SCHEMA_DUMP_STRUCTURE', '1'); - /** * This class manages the access to the database. It basically is a wrapper for * Doctrine with some adaptions. @@ -40,8 +38,7 @@ class OC_DB { * * @return \OC\DB\MDB2SchemaManager */ - private static function getMDB2SchemaManager() - { + private static function getMDB2SchemaManager() { return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection()); } @@ -167,16 +164,6 @@ class OC_DB { } /** - * 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 boolean number of updated rows - */ - public static function insertIfNotExist($table, $input) { - return \OC::$server->getDatabaseConnection()->insertIfNotExist($table, $input); - } - - /** * Start a transaction */ public static function beginTransaction() { @@ -205,7 +192,7 @@ class OC_DB { * * TODO: write more documentation */ - public static function getDbStructure( $file, $mode = 0) { + public static function getDbStructure($file) { $schemaManager = self::getMDB2SchemaManager(); return $schemaManager->getDbStructure($file); } diff --git a/lib/private/db/adapter.php b/lib/private/db/adapter.php index 58b3514b922..8c251c82075 100644 --- a/lib/private/db/adapter.php +++ b/lib/private/db/adapter.php @@ -40,44 +40,38 @@ class Adapter { } /** - * insert the @input values when they do not exist yet - * @param string $table name - * @param array $input key->value pair, key has to be sanitized properly - * @throws \OC\HintException - * @return int count of inserted rows + * Insert a row if the matching row does not exists. + * + * @param string $table The table name (will replace *PREFIX* with the actual prefix) + * @param array $input data that should be inserted into the table (column name => value) + * @param array|null $compare List of values that should be checked for "if not exists" + * If this is null or an empty array, all keys of $input will be compared + * Please note: text fields (clob) must not be used in the compare array + * @return int number of inserted rows + * @throws \Doctrine\DBAL\DBALException */ - public function insertIfNotExist($table, $input) { + public function insertIfNotExist($table, $input, array $compare = null) { + if (empty($compare)) { + $compare = array_keys($input); + } $query = 'INSERT INTO `' .$table . '` (`' . implode('`,`', array_keys($input)) . '`) SELECT ' . str_repeat('?,', count($input)-1).'? ' // Is there a prettier alternative? . 'FROM `' . $table . '` WHERE '; $inserts = array_values($input); - foreach($input as $key => $value) { + foreach($compare as $key) { $query .= '`' . $key . '`'; - if (is_null($value)) { + if (is_null($input[$key])) { $query .= ' IS NULL AND '; } else { - $inserts[] = $value; + $inserts[] = $input[$key]; $query .= ' = ? AND '; } } $query = substr($query, 0, strlen($query) - 5); $query .= ' HAVING COUNT(*) = 0'; - try { - return $this->conn->executeUpdate($query, $inserts); - } catch(\Doctrine\DBAL\DBALException $e) { - $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; - $entry .= 'Offending command was: ' . $query.'<br />'; - \OC_Log::write('core', $entry, \OC_Log::FATAL); - $l = \OC::$server->getL10N('lib'); - throw new \OC\HintException( - $l->t('Database Error'), - $l->t('Please contact your system administrator.'), - 0, - $e - ); - } + return $this->conn->executeUpdate($query, $inserts); } } diff --git a/lib/private/db/adaptersqlite.php b/lib/private/db/adaptersqlite.php index df4a804feb1..a9106967333 100644 --- a/lib/private/db/adaptersqlite.php +++ b/lib/private/db/adaptersqlite.php @@ -18,38 +18,39 @@ class AdapterSqlite extends Adapter { return $statement; } - public function insertIfNotExist($table, $input) { + /** + * Insert a row if the matching row does not exists. + * + * @param string $table The table name (will replace *PREFIX* with the actual prefix) + * @param array $input data that should be inserted into the table (column name => value) + * @param array|null $compare List of values that should be checked for "if not exists" + * If this is null or an empty array, all keys of $input will be compared + * Please note: text fields (clob) must not be used in the compare array + * @return int number of inserted rows + * @throws \Doctrine\DBAL\DBALException + */ + public function insertIfNotExist($table, $input, array $compare = null) { + if (empty($compare)) { + $compare = array_keys($input); + } $fieldList = '`' . implode('`,`', array_keys($input)) . '`'; $query = "INSERT INTO `$table` ($fieldList) SELECT " . str_repeat('?,', count($input)-1).'? ' . " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE "; $inserts = array_values($input); - foreach($input as $key => $value) { + foreach($compare as $key) { $query .= '`' . $key . '`'; - if (is_null($value)) { + if (is_null($input[$key])) { $query .= ' IS NULL AND '; } else { - $inserts[] = $value; + $inserts[] = $input[$key]; $query .= ' = ? AND '; } } $query = substr($query, 0, strlen($query) - 5); $query .= ')'; - try { - return $this->conn->executeUpdate($query, $inserts); - } catch(\Doctrine\DBAL\DBALException $e) { - $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; - $entry .= 'Offending command was: ' . $query.'<br />'; - \OC_Log::write('core', $entry, \OC_Log::FATAL); - $l = \OC::$server->getL10N('lib'); - throw new \OC\HintException( - $l->t('Database Error'), - $l->t('Please contact your system administrator.'), - 0, - $e - ); - } + return $this->conn->executeUpdate($query, $inserts); } } diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php index 53935c1e1ed..0da3c844f03 100644 --- a/lib/private/db/connection.php +++ b/lib/private/db/connection.php @@ -150,20 +150,23 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { } // internal use - public function realLastInsertId($seqName = null) - { + public function realLastInsertId($seqName = null) { return parent::lastInsertId($seqName); } /** - * 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 - * @throws \OC\HintException - * @return bool The return value from execute() + * Insert a row if the matching row does not exists. + * + * @param string $table The table name (will replace *PREFIX* with the actual prefix) + * @param array $input data that should be inserted into the table (column name => value) + * @param array|null $compare List of values that should be checked for "if not exists" + * If this is null or an empty array, all keys of $input will be compared + * Please note: text fields (clob) must not be used in the compare array + * @return int number of inserted rows + * @throws \Doctrine\DBAL\DBALException */ - public function insertIfNotExist($table, $input) { - return $this->adapter->insertIfNotExist($table, $input); + public function insertIfNotExist($table, $input, array $compare = null) { + return $this->adapter->insertIfNotExist($table, $input, $compare); } /** diff --git a/lib/private/db/mdb2schemamanager.php b/lib/private/db/mdb2schemamanager.php index 358360d0b46..66c97f9e3b4 100644 --- a/lib/private/db/mdb2schemamanager.php +++ b/lib/private/db/mdb2schemamanager.php @@ -35,7 +35,7 @@ class MDB2SchemaManager { * * TODO: write more documentation */ - public function getDbStructure($file, $mode = MDB2_SCHEMA_DUMP_STRUCTURE) { + public function getDbStructure($file) { return \OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $this->conn); } diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 56c9bfa3ac5..1dfa9e1dd10 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -211,6 +211,7 @@ class Cache { * @param array $data * * @return int file id + * @throws \RuntimeException */ public function put($file, array $data) { if (($id = $this->getId($file)) > -1) { @@ -248,11 +249,20 @@ class Cache { return trim($item, "`"); }, $queryParts); $values = array_combine($queryParts, $params); - if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values)) { + if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [ + 'storage', + 'path_hash', + ])) { return (int)\OC_DB::insertid('*PREFIX*filecache'); } - return $this->getId($file); + // The file was created in the mean time + if (($id = $this->getId($file)) > -1) { + $this->update($id, $data); + return $id; + } else { + throw new \RuntimeException('File entry exists when inserting and does not exist on select... go away'); + } } } diff --git a/lib/private/files/cache/storage.php b/lib/private/files/cache/storage.php index d7d57811a7d..9f2739bbedb 100644 --- a/lib/private/files/cache/storage.php +++ b/lib/private/files/cache/storage.php @@ -21,6 +21,7 @@ class Storage { /** * @param \OC\Files\Storage\Storage|string $storage + * @throws \RuntimeException */ public function __construct($storage) { if ($storage instanceof \OC\Files\Storage\Storage) { @@ -35,9 +36,17 @@ class Storage { if ($row = $result->fetchRow()) { $this->numericId = $row['numeric_id']; } else { - $sql = 'INSERT INTO `*PREFIX*storages` (`id`) VALUES(?)'; - \OC_DB::executeAudited($sql, array($this->storageId)); - $this->numericId = \OC_DB::insertid('*PREFIX*storages'); + $connection = \OC_DB::getConnection(); + if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId])) { + $this->numericId = \OC_DB::insertid('*PREFIX*storages'); + } else { + $result = \OC_DB::executeAudited($sql, array($this->storageId)); + if ($row = $result->fetchRow()) { + $this->numericId = $row['numeric_id']; + } else { + throw new \RuntimeException('Storage exists when inserting and does not exist on select... go away'); + } + } } } diff --git a/lib/public/db.php b/lib/public/db.php index e8fc817106e..595ecd66bdc 100644 --- a/lib/public/db.php +++ b/lib/public/db.php @@ -48,24 +48,18 @@ class DB { } /** - * Insert a row if a matching row doesn't exists. - * @param string $table The optional table name (will replace *PREFIX*) and add sequence suffix - * @param array $input - * - * The input array if in the form: + * Insert a row if the matching row does not exists. * - * array ( 'id' => array ( 'value' => 6, - * 'key' => true - * ), - * 'name' => array ('value' => 'Stoyan'), - * 'family' => array ('value' => 'Stefanov'), - * 'birth_date' => array ('value' => '1975-06-20') - * ); - * @return bool + * @param string $table The table name (will replace *PREFIX* with the actual prefix) + * @param array $input data that should be inserted into the table (column name => value) + * @param array|null $compare List of values that should be checked for "if not exists" + * If this is null or an empty array, all keys of $input will be compared + * @return int number of inserted rows + * @throws \Doctrine\DBAL\DBALException * */ - public static function insertIfNotExist($table, $input) { - return(\OC_DB::insertIfNotExist($table, $input)); + public static function insertIfNotExist($table, $input, array $compare = null) { + return \OC::$server->getDatabaseConnection()->insertIfNotExist($table, $input, $compare); } /** diff --git a/lib/public/idbconnection.php b/lib/public/idbconnection.php index 0d19b2cc71e..7027f52b14c 100644 --- a/lib/public/idbconnection.php +++ b/lib/public/idbconnection.php @@ -77,24 +77,17 @@ interface IDBConnection { public function lastInsertId($table = null); /** - * Insert a row if a matching row doesn't exists. - * @param string $table The table name (will replace *PREFIX*) to perform the replace on. - * @param array $input - * @throws \OC\HintException + * Insert a row if the matching row does not exists. * - * The input array if in the form: - * - * array ( 'id' => array ( 'value' => 6, - * 'key' => true - * ), - * 'name' => array ('value' => 'Stoyan'), - * 'family' => array ('value' => 'Stefanov'), - * 'birth_date' => array ('value' => '1975-06-20') - * ); - * @return bool - * - */ - public function insertIfNotExist($table, $input); + * @param string $table The table name (will replace *PREFIX* with the actual prefix) + * @param array $input data that should be inserted into the table (column name => value) + * @param array|null $compare List of values that should be checked for "if not exists" + * If this is null or an empty array, all keys of $input will be compared + * Please note: text fields (clob) must not be used in the compare array + * @return int number of inserted rows + * @throws \Doctrine\DBAL\DBALException + */ + public function insertIfNotExist($table, $input, array $compare = null); /** * Start a transaction |