Passed
Push — master ( 0fe2a4...859dd1 )
by Morris
10:13
created
lib/public/IDBConnection.php 1 patch
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -46,242 +46,242 @@
 block discarded – undo
46 46
  */
47 47
 interface IDBConnection {
48 48
 
49
-	const ADD_MISSING_INDEXES_EVENT = self::class . '::ADD_MISSING_INDEXES';
50
-	const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES';
49
+    const ADD_MISSING_INDEXES_EVENT = self::class . '::ADD_MISSING_INDEXES';
50
+    const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES';
51 51
 
52
-	/**
53
-	 * Gets the QueryBuilder for the connection.
54
-	 *
55
-	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
56
-	 * @since 8.2.0
57
-	 */
58
-	public function getQueryBuilder();
52
+    /**
53
+     * Gets the QueryBuilder for the connection.
54
+     *
55
+     * @return \OCP\DB\QueryBuilder\IQueryBuilder
56
+     * @since 8.2.0
57
+     */
58
+    public function getQueryBuilder();
59 59
 
60
-	/**
61
-	 * Used to abstract the ownCloud database access away
62
-	 * @param string $sql the sql query with ? placeholder for params
63
-	 * @param int $limit the maximum number of rows
64
-	 * @param int $offset from which row we want to start
65
-	 * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
66
-	 * @since 6.0.0
67
-	 */
68
-	public function prepare($sql, $limit=null, $offset=null);
60
+    /**
61
+     * Used to abstract the ownCloud database access away
62
+     * @param string $sql the sql query with ? placeholder for params
63
+     * @param int $limit the maximum number of rows
64
+     * @param int $offset from which row we want to start
65
+     * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
66
+     * @since 6.0.0
67
+     */
68
+    public function prepare($sql, $limit=null, $offset=null);
69 69
 
70
-	/**
71
-	 * Executes an, optionally parameterized, SQL query.
72
-	 *
73
-	 * If the query is parameterized, a prepared statement is used.
74
-	 * If an SQLLogger is configured, the execution is logged.
75
-	 *
76
-	 * @param string $query The SQL query to execute.
77
-	 * @param string[] $params The parameters to bind to the query, if any.
78
-	 * @param array $types The types the previous parameters are in.
79
-	 * @return \Doctrine\DBAL\Driver\Statement The executed statement.
80
-	 * @since 8.0.0
81
-	 */
82
-	public function executeQuery($query, array $params = array(), $types = array());
70
+    /**
71
+     * Executes an, optionally parameterized, SQL query.
72
+     *
73
+     * If the query is parameterized, a prepared statement is used.
74
+     * If an SQLLogger is configured, the execution is logged.
75
+     *
76
+     * @param string $query The SQL query to execute.
77
+     * @param string[] $params The parameters to bind to the query, if any.
78
+     * @param array $types The types the previous parameters are in.
79
+     * @return \Doctrine\DBAL\Driver\Statement The executed statement.
80
+     * @since 8.0.0
81
+     */
82
+    public function executeQuery($query, array $params = array(), $types = array());
83 83
 
84
-	/**
85
-	 * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
86
-	 * and returns the number of affected rows.
87
-	 *
88
-	 * This method supports PDO binding types as well as DBAL mapping types.
89
-	 *
90
-	 * @param string $query The SQL query.
91
-	 * @param array $params The query parameters.
92
-	 * @param array $types The parameter types.
93
-	 * @return integer The number of affected rows.
94
-	 * @since 8.0.0
95
-	 */
96
-	public function executeUpdate($query, array $params = array(), array $types = array());
84
+    /**
85
+     * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
86
+     * and returns the number of affected rows.
87
+     *
88
+     * This method supports PDO binding types as well as DBAL mapping types.
89
+     *
90
+     * @param string $query The SQL query.
91
+     * @param array $params The query parameters.
92
+     * @param array $types The parameter types.
93
+     * @return integer The number of affected rows.
94
+     * @since 8.0.0
95
+     */
96
+    public function executeUpdate($query, array $params = array(), array $types = array());
97 97
 
98
-	/**
99
-	 * Used to get the id of the just inserted element
100
-	 * @param string $table the name of the table where we inserted the item
101
-	 * @return int the id of the inserted element
102
-	 * @since 6.0.0
103
-	 */
104
-	public function lastInsertId($table = null);
98
+    /**
99
+     * Used to get the id of the just inserted element
100
+     * @param string $table the name of the table where we inserted the item
101
+     * @return int the id of the inserted element
102
+     * @since 6.0.0
103
+     */
104
+    public function lastInsertId($table = null);
105 105
 
106
-	/**
107
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
108
-	 * it is needed that there is also a unique constraint on the values. Then this method will
109
-	 * catch the exception and return 0.
110
-	 *
111
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
112
-	 * @param array $input data that should be inserted into the table  (column name => value)
113
-	 * @param array|null $compare List of values that should be checked for "if not exists"
114
-	 *				If this is null or an empty array, all keys of $input will be compared
115
-	 *				Please note: text fields (clob) must not be used in the compare array
116
-	 * @return int number of inserted rows
117
-	 * @throws \Doctrine\DBAL\DBALException
118
-	 * @since 6.0.0 - parameter $compare was added in 8.1.0, return type changed from boolean in 8.1.0
119
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
120
-	 */
121
-	public function insertIfNotExist($table, $input, array $compare = null);
106
+    /**
107
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
108
+     * it is needed that there is also a unique constraint on the values. Then this method will
109
+     * catch the exception and return 0.
110
+     *
111
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
112
+     * @param array $input data that should be inserted into the table  (column name => value)
113
+     * @param array|null $compare List of values that should be checked for "if not exists"
114
+     *				If this is null or an empty array, all keys of $input will be compared
115
+     *				Please note: text fields (clob) must not be used in the compare array
116
+     * @return int number of inserted rows
117
+     * @throws \Doctrine\DBAL\DBALException
118
+     * @since 6.0.0 - parameter $compare was added in 8.1.0, return type changed from boolean in 8.1.0
119
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
120
+     */
121
+    public function insertIfNotExist($table, $input, array $compare = null);
122 122
 
123
-	/**
124
-	 * Insert or update a row value
125
-	 *
126
-	 * @param string $table
127
-	 * @param array $keys (column name => value)
128
-	 * @param array $values (column name => value)
129
-	 * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
130
-	 * @return int number of new rows
131
-	 * @throws \Doctrine\DBAL\DBALException
132
-	 * @throws PreconditionNotMetException
133
-	 * @since 9.0.0
134
-	 */
135
-	public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []);
123
+    /**
124
+     * Insert or update a row value
125
+     *
126
+     * @param string $table
127
+     * @param array $keys (column name => value)
128
+     * @param array $values (column name => value)
129
+     * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
130
+     * @return int number of new rows
131
+     * @throws \Doctrine\DBAL\DBALException
132
+     * @throws PreconditionNotMetException
133
+     * @since 9.0.0
134
+     */
135
+    public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []);
136 136
 
137
-	/**
138
-	 * Create an exclusive read+write lock on a table
139
-	 *
140
-	 * Important Note: Due to the nature how locks work on different DBs, it is
141
-	 * only possible to lock one table at a time. You should also NOT start a
142
-	 * transaction while holding a lock.
143
-	 *
144
-	 * @param string $tableName
145
-	 * @since 9.1.0
146
-	 */
147
-	public function lockTable($tableName);
137
+    /**
138
+     * Create an exclusive read+write lock on a table
139
+     *
140
+     * Important Note: Due to the nature how locks work on different DBs, it is
141
+     * only possible to lock one table at a time. You should also NOT start a
142
+     * transaction while holding a lock.
143
+     *
144
+     * @param string $tableName
145
+     * @since 9.1.0
146
+     */
147
+    public function lockTable($tableName);
148 148
 
149
-	/**
150
-	 * Release a previous acquired lock again
151
-	 *
152
-	 * @since 9.1.0
153
-	 */
154
-	public function unlockTable();
149
+    /**
150
+     * Release a previous acquired lock again
151
+     *
152
+     * @since 9.1.0
153
+     */
154
+    public function unlockTable();
155 155
 
156
-	/**
157
-	 * Start a transaction
158
-	 * @since 6.0.0
159
-	 */
160
-	public function beginTransaction();
156
+    /**
157
+     * Start a transaction
158
+     * @since 6.0.0
159
+     */
160
+    public function beginTransaction();
161 161
 
162
-	/**
163
-	 * Check if a transaction is active
164
-	 *
165
-	 * @return bool
166
-	 * @since 8.2.0
167
-	 */
168
-	public function inTransaction();
162
+    /**
163
+     * Check if a transaction is active
164
+     *
165
+     * @return bool
166
+     * @since 8.2.0
167
+     */
168
+    public function inTransaction();
169 169
 
170
-	/**
171
-	 * Commit the database changes done during a transaction that is in progress
172
-	 * @since 6.0.0
173
-	 */
174
-	public function commit();
170
+    /**
171
+     * Commit the database changes done during a transaction that is in progress
172
+     * @since 6.0.0
173
+     */
174
+    public function commit();
175 175
 
176
-	/**
177
-	 * Rollback the database changes done during a transaction that is in progress
178
-	 * @since 6.0.0
179
-	 */
180
-	public function rollBack();
176
+    /**
177
+     * Rollback the database changes done during a transaction that is in progress
178
+     * @since 6.0.0
179
+     */
180
+    public function rollBack();
181 181
 
182
-	/**
183
-	 * Gets the error code and message as a string for logging
184
-	 * @return string
185
-	 * @since 6.0.0
186
-	 */
187
-	public function getError();
182
+    /**
183
+     * Gets the error code and message as a string for logging
184
+     * @return string
185
+     * @since 6.0.0
186
+     */
187
+    public function getError();
188 188
 
189
-	/**
190
-	 * Fetch the SQLSTATE associated with the last database operation.
191
-	 *
192
-	 * @return integer The last error code.
193
-	 * @since 8.0.0
194
-	 */
195
-	public function errorCode();
189
+    /**
190
+     * Fetch the SQLSTATE associated with the last database operation.
191
+     *
192
+     * @return integer The last error code.
193
+     * @since 8.0.0
194
+     */
195
+    public function errorCode();
196 196
 
197
-	/**
198
-	 * Fetch extended error information associated with the last database operation.
199
-	 *
200
-	 * @return array The last error information.
201
-	 * @since 8.0.0
202
-	 */
203
-	public function errorInfo();
197
+    /**
198
+     * Fetch extended error information associated with the last database operation.
199
+     *
200
+     * @return array The last error information.
201
+     * @since 8.0.0
202
+     */
203
+    public function errorInfo();
204 204
 
205
-	/**
206
-	 * Establishes the connection with the database.
207
-	 *
208
-	 * @return bool
209
-	 * @since 8.0.0
210
-	 */
211
-	public function connect();
205
+    /**
206
+     * Establishes the connection with the database.
207
+     *
208
+     * @return bool
209
+     * @since 8.0.0
210
+     */
211
+    public function connect();
212 212
 
213
-	/**
214
-	 * Close the database connection
215
-	 * @since 8.0.0
216
-	 */
217
-	public function close();
213
+    /**
214
+     * Close the database connection
215
+     * @since 8.0.0
216
+     */
217
+    public function close();
218 218
 
219
-	/**
220
-	 * Quotes a given input parameter.
221
-	 *
222
-	 * @param mixed $input Parameter to be quoted.
223
-	 * @param int $type Type of the parameter.
224
-	 * @return string The quoted parameter.
225
-	 * @since 8.0.0
226
-	 */
227
-	public function quote($input, $type = IQueryBuilder::PARAM_STR);
219
+    /**
220
+     * Quotes a given input parameter.
221
+     *
222
+     * @param mixed $input Parameter to be quoted.
223
+     * @param int $type Type of the parameter.
224
+     * @return string The quoted parameter.
225
+     * @since 8.0.0
226
+     */
227
+    public function quote($input, $type = IQueryBuilder::PARAM_STR);
228 228
 
229
-	/**
230
-	 * Gets the DatabasePlatform instance that provides all the metadata about
231
-	 * the platform this driver connects to.
232
-	 *
233
-	 * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
234
-	 * @since 8.0.0
235
-	 */
236
-	public function getDatabasePlatform();
229
+    /**
230
+     * Gets the DatabasePlatform instance that provides all the metadata about
231
+     * the platform this driver connects to.
232
+     *
233
+     * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
234
+     * @since 8.0.0
235
+     */
236
+    public function getDatabasePlatform();
237 237
 
238
-	/**
239
-	 * Drop a table from the database if it exists
240
-	 *
241
-	 * @param string $table table name without the prefix
242
-	 * @since 8.0.0
243
-	 */
244
-	public function dropTable($table);
238
+    /**
239
+     * Drop a table from the database if it exists
240
+     *
241
+     * @param string $table table name without the prefix
242
+     * @since 8.0.0
243
+     */
244
+    public function dropTable($table);
245 245
 
246
-	/**
247
-	 * Check if a table exists
248
-	 *
249
-	 * @param string $table table name without the prefix
250
-	 * @return bool
251
-	 * @since 8.0.0
252
-	 */
253
-	public function tableExists($table);
246
+    /**
247
+     * Check if a table exists
248
+     *
249
+     * @param string $table table name without the prefix
250
+     * @return bool
251
+     * @since 8.0.0
252
+     */
253
+    public function tableExists($table);
254 254
 
255
-	/**
256
-	 * Escape a parameter to be used in a LIKE query
257
-	 *
258
-	 * @param string $param
259
-	 * @return string
260
-	 * @since 9.0.0
261
-	 */
262
-	public function escapeLikeParameter($param);
255
+    /**
256
+     * Escape a parameter to be used in a LIKE query
257
+     *
258
+     * @param string $param
259
+     * @return string
260
+     * @since 9.0.0
261
+     */
262
+    public function escapeLikeParameter($param);
263 263
 
264
-	/**
265
-	 * Check whether or not the current database support 4byte wide unicode
266
-	 *
267
-	 * @return bool
268
-	 * @since 11.0.0
269
-	 */
270
-	public function supports4ByteText();
264
+    /**
265
+     * Check whether or not the current database support 4byte wide unicode
266
+     *
267
+     * @return bool
268
+     * @since 11.0.0
269
+     */
270
+    public function supports4ByteText();
271 271
 
272
-	/**
273
-	 * Create the schema of the connected database
274
-	 *
275
-	 * @return Schema
276
-	 * @since 13.0.0
277
-	 */
278
-	public function createSchema();
272
+    /**
273
+     * Create the schema of the connected database
274
+     *
275
+     * @return Schema
276
+     * @since 13.0.0
277
+     */
278
+    public function createSchema();
279 279
 
280
-	/**
281
-	 * Migrate the database to the given schema
282
-	 *
283
-	 * @param Schema $toSchema
284
-	 * @since 13.0.0
285
-	 */
286
-	public function migrateToSchema(Schema $toSchema);
280
+    /**
281
+     * Migrate the database to the given schema
282
+     *
283
+     * @param Schema $toSchema
284
+     * @since 13.0.0
285
+     */
286
+    public function migrateToSchema(Schema $toSchema);
287 287
 }
Please login to merge, or discard this patch.
lib/private/DB/AdapterSqlite.php 1 patch
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -31,70 +31,70 @@
 block discarded – undo
31 31
 
32 32
 class AdapterSqlite extends Adapter {
33 33
 
34
-	/**
35
-	 * @param string $tableName
36
-	 */
37
-	public function lockTable($tableName) {
38
-		$this->conn->executeUpdate('BEGIN EXCLUSIVE TRANSACTION');
39
-	}
34
+    /**
35
+     * @param string $tableName
36
+     */
37
+    public function lockTable($tableName) {
38
+        $this->conn->executeUpdate('BEGIN EXCLUSIVE TRANSACTION');
39
+    }
40 40
 
41
-	public function unlockTable() {
42
-		$this->conn->executeUpdate('COMMIT TRANSACTION');
43
-	}
41
+    public function unlockTable() {
42
+        $this->conn->executeUpdate('COMMIT TRANSACTION');
43
+    }
44 44
 
45
-	public function fixupStatement($statement) {
46
-		$statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
47
-		$statement = str_replace( '`', '"', $statement );
48
-		$statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement );
49
-		$statement = str_ireplace('GREATEST(', 'MAX(', $statement);
50
-		$statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement );
51
-		return $statement;
52
-	}
45
+    public function fixupStatement($statement) {
46
+        $statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
47
+        $statement = str_replace( '`', '"', $statement );
48
+        $statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement );
49
+        $statement = str_ireplace('GREATEST(', 'MAX(', $statement);
50
+        $statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement );
51
+        return $statement;
52
+    }
53 53
 
54
-	/**
55
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
56
-	 * it is needed that there is also a unique constraint on the values. Then this method will
57
-	 * catch the exception and return 0.
58
-	 *
59
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
60
-	 * @param array $input data that should be inserted into the table  (column name => value)
61
-	 * @param array|null $compare List of values that should be checked for "if not exists"
62
-	 *				If this is null or an empty array, all keys of $input will be compared
63
-	 *				Please note: text fields (clob) must not be used in the compare array
64
-	 * @return int number of inserted rows
65
-	 * @throws \Doctrine\DBAL\DBALException
66
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
67
-	 */
68
-	public function insertIfNotExist($table, $input, array $compare = null) {
69
-		if (empty($compare)) {
70
-			$compare = array_keys($input);
71
-		}
72
-		$fieldList = '`' . implode('`,`', array_keys($input)) . '`';
73
-		$query = "INSERT INTO `$table` ($fieldList) SELECT "
74
-			. str_repeat('?,', count($input)-1).'? '
75
-			. " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
54
+    /**
55
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
56
+     * it is needed that there is also a unique constraint on the values. Then this method will
57
+     * catch the exception and return 0.
58
+     *
59
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
60
+     * @param array $input data that should be inserted into the table  (column name => value)
61
+     * @param array|null $compare List of values that should be checked for "if not exists"
62
+     *				If this is null or an empty array, all keys of $input will be compared
63
+     *				Please note: text fields (clob) must not be used in the compare array
64
+     * @return int number of inserted rows
65
+     * @throws \Doctrine\DBAL\DBALException
66
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
67
+     */
68
+    public function insertIfNotExist($table, $input, array $compare = null) {
69
+        if (empty($compare)) {
70
+            $compare = array_keys($input);
71
+        }
72
+        $fieldList = '`' . implode('`,`', array_keys($input)) . '`';
73
+        $query = "INSERT INTO `$table` ($fieldList) SELECT "
74
+            . str_repeat('?,', count($input)-1).'? '
75
+            . " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
76 76
 
77
-		$inserts = array_values($input);
78
-		foreach($compare as $key) {
79
-			$query .= '`' . $key . '`';
80
-			if (is_null($input[$key])) {
81
-				$query .= ' IS NULL AND ';
82
-			} else {
83
-				$inserts[] = $input[$key];
84
-				$query .= ' = ? AND ';
85
-			}
86
-		}
87
-		$query = substr($query, 0, -5);
88
-		$query .= ')';
77
+        $inserts = array_values($input);
78
+        foreach($compare as $key) {
79
+            $query .= '`' . $key . '`';
80
+            if (is_null($input[$key])) {
81
+                $query .= ' IS NULL AND ';
82
+            } else {
83
+                $inserts[] = $input[$key];
84
+                $query .= ' = ? AND ';
85
+            }
86
+        }
87
+        $query = substr($query, 0, -5);
88
+        $query .= ')';
89 89
 
90
-		try {
91
-			return $this->conn->executeUpdate($query, $inserts);
92
-		} catch (UniqueConstraintViolationException $e) {
93
-			// if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
94
-			// it's fine to ignore this then
95
-			//
96
-			// more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
97
-			return 0;
98
-		}
99
-	}
90
+        try {
91
+            return $this->conn->executeUpdate($query, $inserts);
92
+        } catch (UniqueConstraintViolationException $e) {
93
+            // if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
94
+            // it's fine to ignore this then
95
+            //
96
+            // more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
97
+            return 0;
98
+        }
99
+    }
100 100
 }
Please login to merge, or discard this patch.
lib/private/DB/Adapter.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -35,95 +35,95 @@
 block discarded – undo
35 35
  */
36 36
 class Adapter {
37 37
 
38
-	/**
39
-	 * @var \OC\DB\Connection $conn
40
-	 */
41
-	protected $conn;
38
+    /**
39
+     * @var \OC\DB\Connection $conn
40
+     */
41
+    protected $conn;
42 42
 
43
-	public function __construct($conn) {
44
-		$this->conn = $conn;
45
-	}
43
+    public function __construct($conn) {
44
+        $this->conn = $conn;
45
+    }
46 46
 
47
-	/**
48
-	 * @param string $table name
49
-	 * @return int id of last insert statement
50
-	 */
51
-	public function lastInsertId($table) {
52
-		return $this->conn->realLastInsertId($table);
53
-	}
47
+    /**
48
+     * @param string $table name
49
+     * @return int id of last insert statement
50
+     */
51
+    public function lastInsertId($table) {
52
+        return $this->conn->realLastInsertId($table);
53
+    }
54 54
 
55
-	/**
56
-	 * @param string $statement that needs to be changed so the db can handle it
57
-	 * @return string changed statement
58
-	 */
59
-	public function fixupStatement($statement) {
60
-		return $statement;
61
-	}
55
+    /**
56
+     * @param string $statement that needs to be changed so the db can handle it
57
+     * @return string changed statement
58
+     */
59
+    public function fixupStatement($statement) {
60
+        return $statement;
61
+    }
62 62
 
63
-	/**
64
-	 * Create an exclusive read+write lock on a table
65
-	 *
66
-	 * @param string $tableName
67
-	 * @since 9.1.0
68
-	 */
69
-	public function lockTable($tableName) {
70
-		$this->conn->beginTransaction();
71
-		$this->conn->executeUpdate('LOCK TABLE `' .$tableName . '` IN EXCLUSIVE MODE');
72
-	}
63
+    /**
64
+     * Create an exclusive read+write lock on a table
65
+     *
66
+     * @param string $tableName
67
+     * @since 9.1.0
68
+     */
69
+    public function lockTable($tableName) {
70
+        $this->conn->beginTransaction();
71
+        $this->conn->executeUpdate('LOCK TABLE `' .$tableName . '` IN EXCLUSIVE MODE');
72
+    }
73 73
 
74
-	/**
75
-	 * Release a previous acquired lock again
76
-	 *
77
-	 * @since 9.1.0
78
-	 */
79
-	public function unlockTable() {
80
-		$this->conn->commit();
81
-	}
74
+    /**
75
+     * Release a previous acquired lock again
76
+     *
77
+     * @since 9.1.0
78
+     */
79
+    public function unlockTable() {
80
+        $this->conn->commit();
81
+    }
82 82
 
83
-	/**
84
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
85
-	 * it is needed that there is also a unique constraint on the values. Then this method will
86
-	 * catch the exception and return 0.
87
-	 *
88
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
89
-	 * @param array $input data that should be inserted into the table  (column name => value)
90
-	 * @param array|null $compare List of values that should be checked for "if not exists"
91
-	 *				If this is null or an empty array, all keys of $input will be compared
92
-	 *				Please note: text fields (clob) must not be used in the compare array
93
-	 * @return int number of inserted rows
94
-	 * @throws \Doctrine\DBAL\DBALException
95
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
96
-	 */
97
-	public function insertIfNotExist($table, $input, array $compare = null) {
98
-		if (empty($compare)) {
99
-			$compare = array_keys($input);
100
-		}
101
-		$query = 'INSERT INTO `' .$table . '` (`'
102
-			. implode('`,`', array_keys($input)) . '`) SELECT '
103
-			. str_repeat('?,', count($input)-1).'? ' // Is there a prettier alternative?
104
-			. 'FROM `' . $table . '` WHERE ';
83
+    /**
84
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
85
+     * it is needed that there is also a unique constraint on the values. Then this method will
86
+     * catch the exception and return 0.
87
+     *
88
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
89
+     * @param array $input data that should be inserted into the table  (column name => value)
90
+     * @param array|null $compare List of values that should be checked for "if not exists"
91
+     *				If this is null or an empty array, all keys of $input will be compared
92
+     *				Please note: text fields (clob) must not be used in the compare array
93
+     * @return int number of inserted rows
94
+     * @throws \Doctrine\DBAL\DBALException
95
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
96
+     */
97
+    public function insertIfNotExist($table, $input, array $compare = null) {
98
+        if (empty($compare)) {
99
+            $compare = array_keys($input);
100
+        }
101
+        $query = 'INSERT INTO `' .$table . '` (`'
102
+            . implode('`,`', array_keys($input)) . '`) SELECT '
103
+            . str_repeat('?,', count($input)-1).'? ' // Is there a prettier alternative?
104
+            . 'FROM `' . $table . '` WHERE ';
105 105
 
106
-		$inserts = array_values($input);
107
-		foreach($compare as $key) {
108
-			$query .= '`' . $key . '`';
109
-			if (is_null($input[$key])) {
110
-				$query .= ' IS NULL AND ';
111
-			} else {
112
-				$inserts[] = $input[$key];
113
-				$query .= ' = ? AND ';
114
-			}
115
-		}
116
-		$query = substr($query, 0, -5);
117
-		$query .= ' HAVING COUNT(*) = 0';
106
+        $inserts = array_values($input);
107
+        foreach($compare as $key) {
108
+            $query .= '`' . $key . '`';
109
+            if (is_null($input[$key])) {
110
+                $query .= ' IS NULL AND ';
111
+            } else {
112
+                $inserts[] = $input[$key];
113
+                $query .= ' = ? AND ';
114
+            }
115
+        }
116
+        $query = substr($query, 0, -5);
117
+        $query .= ' HAVING COUNT(*) = 0';
118 118
 
119
-		try {
120
-			return $this->conn->executeUpdate($query, $inserts);
121
-		} catch (UniqueConstraintViolationException $e) {
122
-			// if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
123
-			// it's fine to ignore this then
124
-			//
125
-			// more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
126
-			return 0;
127
-		}
128
-	}
119
+        try {
120
+            return $this->conn->executeUpdate($query, $inserts);
121
+        } catch (UniqueConstraintViolationException $e) {
122
+            // if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
123
+            // it's fine to ignore this then
124
+            //
125
+            // more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
126
+            return 0;
127
+        }
128
+    }
129 129
 }
Please login to merge, or discard this patch.
lib/private/DB/Connection.php 1 patch
Indentation   +404 added lines, -404 removed lines patch added patch discarded remove patch
@@ -44,408 +44,408 @@
 block discarded – undo
44 44
 use OCP\PreConditionNotMetException;
45 45
 
46 46
 class Connection extends ReconnectWrapper implements IDBConnection {
47
-	/**
48
-	 * @var string $tablePrefix
49
-	 */
50
-	protected $tablePrefix;
51
-
52
-	/**
53
-	 * @var \OC\DB\Adapter $adapter
54
-	 */
55
-	protected $adapter;
56
-
57
-	protected $lockedTable = null;
58
-
59
-	public function connect() {
60
-		try {
61
-			return parent::connect();
62
-		} catch (DBALException $e) {
63
-			// throw a new exception to prevent leaking info from the stacktrace
64
-			throw new DBALException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
65
-		}
66
-	}
67
-
68
-	/**
69
-	 * Returns a QueryBuilder for the connection.
70
-	 *
71
-	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
72
-	 */
73
-	public function getQueryBuilder() {
74
-		return new QueryBuilder(
75
-			$this,
76
-			\OC::$server->getSystemConfig(),
77
-			\OC::$server->getLogger()
78
-		);
79
-	}
80
-
81
-	/**
82
-	 * Gets the QueryBuilder for the connection.
83
-	 *
84
-	 * @return \Doctrine\DBAL\Query\QueryBuilder
85
-	 * @deprecated please use $this->getQueryBuilder() instead
86
-	 */
87
-	public function createQueryBuilder() {
88
-		$backtrace = $this->getCallerBacktrace();
89
-		\OC::$server->getLogger()->debug('Doctrine QueryBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
90
-		return parent::createQueryBuilder();
91
-	}
92
-
93
-	/**
94
-	 * Gets the ExpressionBuilder for the connection.
95
-	 *
96
-	 * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
97
-	 * @deprecated please use $this->getQueryBuilder()->expr() instead
98
-	 */
99
-	public function getExpressionBuilder() {
100
-		$backtrace = $this->getCallerBacktrace();
101
-		\OC::$server->getLogger()->debug('Doctrine ExpressionBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
102
-		return parent::getExpressionBuilder();
103
-	}
104
-
105
-	/**
106
-	 * Get the file and line that called the method where `getCallerBacktrace()` was used
107
-	 *
108
-	 * @return string
109
-	 */
110
-	protected function getCallerBacktrace() {
111
-		$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
112
-
113
-		// 0 is the method where we use `getCallerBacktrace`
114
-		// 1 is the target method which uses the method we want to log
115
-		if (isset($traces[1])) {
116
-			return $traces[1]['file'] . ':' . $traces[1]['line'];
117
-		}
118
-
119
-		return '';
120
-	}
121
-
122
-	/**
123
-	 * @return string
124
-	 */
125
-	public function getPrefix() {
126
-		return $this->tablePrefix;
127
-	}
128
-
129
-	/**
130
-	 * Initializes a new instance of the Connection class.
131
-	 *
132
-	 * @param array $params  The connection parameters.
133
-	 * @param \Doctrine\DBAL\Driver $driver
134
-	 * @param \Doctrine\DBAL\Configuration $config
135
-	 * @param \Doctrine\Common\EventManager $eventManager
136
-	 * @throws \Exception
137
-	 */
138
-	public function __construct(array $params, Driver $driver, Configuration $config = null,
139
-		EventManager $eventManager = null)
140
-	{
141
-		if (!isset($params['adapter'])) {
142
-			throw new \Exception('adapter not set');
143
-		}
144
-		if (!isset($params['tablePrefix'])) {
145
-			throw new \Exception('tablePrefix not set');
146
-		}
147
-		parent::__construct($params, $driver, $config, $eventManager);
148
-		$this->adapter = new $params['adapter']($this);
149
-		$this->tablePrefix = $params['tablePrefix'];
150
-
151
-		parent::setTransactionIsolation(parent::TRANSACTION_READ_COMMITTED);
152
-	}
153
-
154
-	/**
155
-	 * Prepares an SQL statement.
156
-	 *
157
-	 * @param string $statement The SQL statement to prepare.
158
-	 * @param int $limit
159
-	 * @param int $offset
160
-	 * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
161
-	 */
162
-	public function prepare( $statement, $limit=null, $offset=null ) {
163
-		if ($limit === -1) {
164
-			$limit = null;
165
-		}
166
-		if (!is_null($limit)) {
167
-			$platform = $this->getDatabasePlatform();
168
-			$statement = $platform->modifyLimitQuery($statement, $limit, $offset);
169
-		}
170
-		$statement = $this->replaceTablePrefix($statement);
171
-		$statement = $this->adapter->fixupStatement($statement);
172
-
173
-		return parent::prepare($statement);
174
-	}
175
-
176
-	/**
177
-	 * Executes an, optionally parametrized, SQL query.
178
-	 *
179
-	 * If the query is parametrized, a prepared statement is used.
180
-	 * If an SQLLogger is configured, the execution is logged.
181
-	 *
182
-	 * @param string                                      $query  The SQL query to execute.
183
-	 * @param array                                       $params The parameters to bind to the query, if any.
184
-	 * @param array                                       $types  The types the previous parameters are in.
185
-	 * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp    The query cache profile, optional.
186
-	 *
187
-	 * @return \Doctrine\DBAL\Driver\Statement The executed statement.
188
-	 *
189
-	 * @throws \Doctrine\DBAL\DBALException
190
-	 */
191
-	public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null)
192
-	{
193
-		$query = $this->replaceTablePrefix($query);
194
-		$query = $this->adapter->fixupStatement($query);
195
-		return parent::executeQuery($query, $params, $types, $qcp);
196
-	}
197
-
198
-	/**
199
-	 * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
200
-	 * and returns the number of affected rows.
201
-	 *
202
-	 * This method supports PDO binding types as well as DBAL mapping types.
203
-	 *
204
-	 * @param string $query  The SQL query.
205
-	 * @param array  $params The query parameters.
206
-	 * @param array  $types  The parameter types.
207
-	 *
208
-	 * @return integer The number of affected rows.
209
-	 *
210
-	 * @throws \Doctrine\DBAL\DBALException
211
-	 */
212
-	public function executeUpdate($query, array $params = array(), array $types = array())
213
-	{
214
-		$query = $this->replaceTablePrefix($query);
215
-		$query = $this->adapter->fixupStatement($query);
216
-		return parent::executeUpdate($query, $params, $types);
217
-	}
218
-
219
-	/**
220
-	 * Returns the ID of the last inserted row, or the last value from a sequence object,
221
-	 * depending on the underlying driver.
222
-	 *
223
-	 * Note: This method may not return a meaningful or consistent result across different drivers,
224
-	 * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
225
-	 * columns or sequences.
226
-	 *
227
-	 * @param string $seqName Name of the sequence object from which the ID should be returned.
228
-	 * @return string A string representation of the last inserted ID.
229
-	 */
230
-	public function lastInsertId($seqName = null) {
231
-		if ($seqName) {
232
-			$seqName = $this->replaceTablePrefix($seqName);
233
-		}
234
-		return $this->adapter->lastInsertId($seqName);
235
-	}
236
-
237
-	// internal use
238
-	public function realLastInsertId($seqName = null) {
239
-		return parent::lastInsertId($seqName);
240
-	}
241
-
242
-	/**
243
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
244
-	 * it is needed that there is also a unique constraint on the values. Then this method will
245
-	 * catch the exception and return 0.
246
-	 *
247
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
248
-	 * @param array $input data that should be inserted into the table  (column name => value)
249
-	 * @param array|null $compare List of values that should be checked for "if not exists"
250
-	 *				If this is null or an empty array, all keys of $input will be compared
251
-	 *				Please note: text fields (clob) must not be used in the compare array
252
-	 * @return int number of inserted rows
253
-	 * @throws \Doctrine\DBAL\DBALException
254
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
255
-	 */
256
-	public function insertIfNotExist($table, $input, array $compare = null) {
257
-		return $this->adapter->insertIfNotExist($table, $input, $compare);
258
-	}
259
-
260
-	private function getType($value) {
261
-		if (is_bool($value)) {
262
-			return IQueryBuilder::PARAM_BOOL;
263
-		} else if (is_int($value)) {
264
-			return IQueryBuilder::PARAM_INT;
265
-		} else {
266
-			return IQueryBuilder::PARAM_STR;
267
-		}
268
-	}
269
-
270
-	/**
271
-	 * Insert or update a row value
272
-	 *
273
-	 * @param string $table
274
-	 * @param array $keys (column name => value)
275
-	 * @param array $values (column name => value)
276
-	 * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
277
-	 * @return int number of new rows
278
-	 * @throws \Doctrine\DBAL\DBALException
279
-	 * @throws PreConditionNotMetException
280
-	 * @suppress SqlInjectionChecker
281
-	 */
282
-	public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) {
283
-		try {
284
-			$insertQb = $this->getQueryBuilder();
285
-			$insertQb->insert($table)
286
-				->values(
287
-					array_map(function($value) use ($insertQb) {
288
-						return $insertQb->createNamedParameter($value, $this->getType($value));
289
-					}, array_merge($keys, $values))
290
-				);
291
-			return $insertQb->execute();
292
-		} catch (ConstraintViolationException $e) {
293
-			// value already exists, try update
294
-			$updateQb = $this->getQueryBuilder();
295
-			$updateQb->update($table);
296
-			foreach ($values as $name => $value) {
297
-				$updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value)));
298
-			}
299
-			$where = $updateQb->expr()->andX();
300
-			$whereValues = array_merge($keys, $updatePreconditionValues);
301
-			foreach ($whereValues as $name => $value) {
302
-				$where->add($updateQb->expr()->eq(
303
-					$name,
304
-					$updateQb->createNamedParameter($value, $this->getType($value)),
305
-					$this->getType($value)
306
-				));
307
-			}
308
-			$updateQb->where($where);
309
-			$affected = $updateQb->execute();
310
-
311
-			if ($affected === 0 && !empty($updatePreconditionValues)) {
312
-				throw new PreConditionNotMetException();
313
-			}
314
-
315
-			return 0;
316
-		}
317
-	}
318
-
319
-	/**
320
-	 * Create an exclusive read+write lock on a table
321
-	 *
322
-	 * @param string $tableName
323
-	 * @throws \BadMethodCallException When trying to acquire a second lock
324
-	 * @since 9.1.0
325
-	 */
326
-	public function lockTable($tableName) {
327
-		if ($this->lockedTable !== null) {
328
-			throw new \BadMethodCallException('Can not lock a new table until the previous lock is released.');
329
-		}
330
-
331
-		$tableName = $this->tablePrefix . $tableName;
332
-		$this->lockedTable = $tableName;
333
-		$this->adapter->lockTable($tableName);
334
-	}
335
-
336
-	/**
337
-	 * Release a previous acquired lock again
338
-	 *
339
-	 * @since 9.1.0
340
-	 */
341
-	public function unlockTable() {
342
-		$this->adapter->unlockTable();
343
-		$this->lockedTable = null;
344
-	}
345
-
346
-	/**
347
-	 * returns the error code and message as a string for logging
348
-	 * works with DoctrineException
349
-	 * @return string
350
-	 */
351
-	public function getError() {
352
-		$msg = $this->errorCode() . ': ';
353
-		$errorInfo = $this->errorInfo();
354
-		if (is_array($errorInfo)) {
355
-			$msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
356
-			$msg .= 'Driver Code = '.$errorInfo[1] . ', ';
357
-			$msg .= 'Driver Message = '.$errorInfo[2];
358
-		}
359
-		return $msg;
360
-	}
361
-
362
-	/**
363
-	 * Drop a table from the database if it exists
364
-	 *
365
-	 * @param string $table table name without the prefix
366
-	 */
367
-	public function dropTable($table) {
368
-		$table = $this->tablePrefix . trim($table);
369
-		$schema = $this->getSchemaManager();
370
-		if($schema->tablesExist(array($table))) {
371
-			$schema->dropTable($table);
372
-		}
373
-	}
374
-
375
-	/**
376
-	 * Check if a table exists
377
-	 *
378
-	 * @param string $table table name without the prefix
379
-	 * @return bool
380
-	 */
381
-	public function tableExists($table){
382
-		$table = $this->tablePrefix . trim($table);
383
-		$schema = $this->getSchemaManager();
384
-		return $schema->tablesExist(array($table));
385
-	}
386
-
387
-	// internal use
388
-	/**
389
-	 * @param string $statement
390
-	 * @return string
391
-	 */
392
-	protected function replaceTablePrefix($statement) {
393
-		return str_replace( '*PREFIX*', $this->tablePrefix, $statement );
394
-	}
395
-
396
-	/**
397
-	 * Check if a transaction is active
398
-	 *
399
-	 * @return bool
400
-	 * @since 8.2.0
401
-	 */
402
-	public function inTransaction() {
403
-		return $this->getTransactionNestingLevel() > 0;
404
-	}
405
-
406
-	/**
407
-	 * Escape a parameter to be used in a LIKE query
408
-	 *
409
-	 * @param string $param
410
-	 * @return string
411
-	 */
412
-	public function escapeLikeParameter($param) {
413
-		return addcslashes($param, '\\_%');
414
-	}
415
-
416
-	/**
417
-	 * Check whether or not the current database support 4byte wide unicode
418
-	 *
419
-	 * @return bool
420
-	 * @since 11.0.0
421
-	 */
422
-	public function supports4ByteText() {
423
-		if (!$this->getDatabasePlatform() instanceof MySqlPlatform) {
424
-			return true;
425
-		}
426
-		return $this->getParams()['charset'] === 'utf8mb4';
427
-	}
428
-
429
-
430
-	/**
431
-	 * Create the schema of the connected database
432
-	 *
433
-	 * @return Schema
434
-	 */
435
-	public function createSchema() {
436
-		$schemaManager = new MDB2SchemaManager($this);
437
-		$migrator = $schemaManager->getMigrator();
438
-		return $migrator->createSchema();
439
-	}
440
-
441
-	/**
442
-	 * Migrate the database to the given schema
443
-	 *
444
-	 * @param Schema $toSchema
445
-	 */
446
-	public function migrateToSchema(Schema $toSchema) {
447
-		$schemaManager = new MDB2SchemaManager($this);
448
-		$migrator = $schemaManager->getMigrator();
449
-		$migrator->migrate($toSchema);
450
-	}
47
+    /**
48
+     * @var string $tablePrefix
49
+     */
50
+    protected $tablePrefix;
51
+
52
+    /**
53
+     * @var \OC\DB\Adapter $adapter
54
+     */
55
+    protected $adapter;
56
+
57
+    protected $lockedTable = null;
58
+
59
+    public function connect() {
60
+        try {
61
+            return parent::connect();
62
+        } catch (DBALException $e) {
63
+            // throw a new exception to prevent leaking info from the stacktrace
64
+            throw new DBALException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
65
+        }
66
+    }
67
+
68
+    /**
69
+     * Returns a QueryBuilder for the connection.
70
+     *
71
+     * @return \OCP\DB\QueryBuilder\IQueryBuilder
72
+     */
73
+    public function getQueryBuilder() {
74
+        return new QueryBuilder(
75
+            $this,
76
+            \OC::$server->getSystemConfig(),
77
+            \OC::$server->getLogger()
78
+        );
79
+    }
80
+
81
+    /**
82
+     * Gets the QueryBuilder for the connection.
83
+     *
84
+     * @return \Doctrine\DBAL\Query\QueryBuilder
85
+     * @deprecated please use $this->getQueryBuilder() instead
86
+     */
87
+    public function createQueryBuilder() {
88
+        $backtrace = $this->getCallerBacktrace();
89
+        \OC::$server->getLogger()->debug('Doctrine QueryBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
90
+        return parent::createQueryBuilder();
91
+    }
92
+
93
+    /**
94
+     * Gets the ExpressionBuilder for the connection.
95
+     *
96
+     * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
97
+     * @deprecated please use $this->getQueryBuilder()->expr() instead
98
+     */
99
+    public function getExpressionBuilder() {
100
+        $backtrace = $this->getCallerBacktrace();
101
+        \OC::$server->getLogger()->debug('Doctrine ExpressionBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
102
+        return parent::getExpressionBuilder();
103
+    }
104
+
105
+    /**
106
+     * Get the file and line that called the method where `getCallerBacktrace()` was used
107
+     *
108
+     * @return string
109
+     */
110
+    protected function getCallerBacktrace() {
111
+        $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
112
+
113
+        // 0 is the method where we use `getCallerBacktrace`
114
+        // 1 is the target method which uses the method we want to log
115
+        if (isset($traces[1])) {
116
+            return $traces[1]['file'] . ':' . $traces[1]['line'];
117
+        }
118
+
119
+        return '';
120
+    }
121
+
122
+    /**
123
+     * @return string
124
+     */
125
+    public function getPrefix() {
126
+        return $this->tablePrefix;
127
+    }
128
+
129
+    /**
130
+     * Initializes a new instance of the Connection class.
131
+     *
132
+     * @param array $params  The connection parameters.
133
+     * @param \Doctrine\DBAL\Driver $driver
134
+     * @param \Doctrine\DBAL\Configuration $config
135
+     * @param \Doctrine\Common\EventManager $eventManager
136
+     * @throws \Exception
137
+     */
138
+    public function __construct(array $params, Driver $driver, Configuration $config = null,
139
+        EventManager $eventManager = null)
140
+    {
141
+        if (!isset($params['adapter'])) {
142
+            throw new \Exception('adapter not set');
143
+        }
144
+        if (!isset($params['tablePrefix'])) {
145
+            throw new \Exception('tablePrefix not set');
146
+        }
147
+        parent::__construct($params, $driver, $config, $eventManager);
148
+        $this->adapter = new $params['adapter']($this);
149
+        $this->tablePrefix = $params['tablePrefix'];
150
+
151
+        parent::setTransactionIsolation(parent::TRANSACTION_READ_COMMITTED);
152
+    }
153
+
154
+    /**
155
+     * Prepares an SQL statement.
156
+     *
157
+     * @param string $statement The SQL statement to prepare.
158
+     * @param int $limit
159
+     * @param int $offset
160
+     * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
161
+     */
162
+    public function prepare( $statement, $limit=null, $offset=null ) {
163
+        if ($limit === -1) {
164
+            $limit = null;
165
+        }
166
+        if (!is_null($limit)) {
167
+            $platform = $this->getDatabasePlatform();
168
+            $statement = $platform->modifyLimitQuery($statement, $limit, $offset);
169
+        }
170
+        $statement = $this->replaceTablePrefix($statement);
171
+        $statement = $this->adapter->fixupStatement($statement);
172
+
173
+        return parent::prepare($statement);
174
+    }
175
+
176
+    /**
177
+     * Executes an, optionally parametrized, SQL query.
178
+     *
179
+     * If the query is parametrized, a prepared statement is used.
180
+     * If an SQLLogger is configured, the execution is logged.
181
+     *
182
+     * @param string                                      $query  The SQL query to execute.
183
+     * @param array                                       $params The parameters to bind to the query, if any.
184
+     * @param array                                       $types  The types the previous parameters are in.
185
+     * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp    The query cache profile, optional.
186
+     *
187
+     * @return \Doctrine\DBAL\Driver\Statement The executed statement.
188
+     *
189
+     * @throws \Doctrine\DBAL\DBALException
190
+     */
191
+    public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null)
192
+    {
193
+        $query = $this->replaceTablePrefix($query);
194
+        $query = $this->adapter->fixupStatement($query);
195
+        return parent::executeQuery($query, $params, $types, $qcp);
196
+    }
197
+
198
+    /**
199
+     * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
200
+     * and returns the number of affected rows.
201
+     *
202
+     * This method supports PDO binding types as well as DBAL mapping types.
203
+     *
204
+     * @param string $query  The SQL query.
205
+     * @param array  $params The query parameters.
206
+     * @param array  $types  The parameter types.
207
+     *
208
+     * @return integer The number of affected rows.
209
+     *
210
+     * @throws \Doctrine\DBAL\DBALException
211
+     */
212
+    public function executeUpdate($query, array $params = array(), array $types = array())
213
+    {
214
+        $query = $this->replaceTablePrefix($query);
215
+        $query = $this->adapter->fixupStatement($query);
216
+        return parent::executeUpdate($query, $params, $types);
217
+    }
218
+
219
+    /**
220
+     * Returns the ID of the last inserted row, or the last value from a sequence object,
221
+     * depending on the underlying driver.
222
+     *
223
+     * Note: This method may not return a meaningful or consistent result across different drivers,
224
+     * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
225
+     * columns or sequences.
226
+     *
227
+     * @param string $seqName Name of the sequence object from which the ID should be returned.
228
+     * @return string A string representation of the last inserted ID.
229
+     */
230
+    public function lastInsertId($seqName = null) {
231
+        if ($seqName) {
232
+            $seqName = $this->replaceTablePrefix($seqName);
233
+        }
234
+        return $this->adapter->lastInsertId($seqName);
235
+    }
236
+
237
+    // internal use
238
+    public function realLastInsertId($seqName = null) {
239
+        return parent::lastInsertId($seqName);
240
+    }
241
+
242
+    /**
243
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
244
+     * it is needed that there is also a unique constraint on the values. Then this method will
245
+     * catch the exception and return 0.
246
+     *
247
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
248
+     * @param array $input data that should be inserted into the table  (column name => value)
249
+     * @param array|null $compare List of values that should be checked for "if not exists"
250
+     *				If this is null or an empty array, all keys of $input will be compared
251
+     *				Please note: text fields (clob) must not be used in the compare array
252
+     * @return int number of inserted rows
253
+     * @throws \Doctrine\DBAL\DBALException
254
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
255
+     */
256
+    public function insertIfNotExist($table, $input, array $compare = null) {
257
+        return $this->adapter->insertIfNotExist($table, $input, $compare);
258
+    }
259
+
260
+    private function getType($value) {
261
+        if (is_bool($value)) {
262
+            return IQueryBuilder::PARAM_BOOL;
263
+        } else if (is_int($value)) {
264
+            return IQueryBuilder::PARAM_INT;
265
+        } else {
266
+            return IQueryBuilder::PARAM_STR;
267
+        }
268
+    }
269
+
270
+    /**
271
+     * Insert or update a row value
272
+     *
273
+     * @param string $table
274
+     * @param array $keys (column name => value)
275
+     * @param array $values (column name => value)
276
+     * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
277
+     * @return int number of new rows
278
+     * @throws \Doctrine\DBAL\DBALException
279
+     * @throws PreConditionNotMetException
280
+     * @suppress SqlInjectionChecker
281
+     */
282
+    public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) {
283
+        try {
284
+            $insertQb = $this->getQueryBuilder();
285
+            $insertQb->insert($table)
286
+                ->values(
287
+                    array_map(function($value) use ($insertQb) {
288
+                        return $insertQb->createNamedParameter($value, $this->getType($value));
289
+                    }, array_merge($keys, $values))
290
+                );
291
+            return $insertQb->execute();
292
+        } catch (ConstraintViolationException $e) {
293
+            // value already exists, try update
294
+            $updateQb = $this->getQueryBuilder();
295
+            $updateQb->update($table);
296
+            foreach ($values as $name => $value) {
297
+                $updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value)));
298
+            }
299
+            $where = $updateQb->expr()->andX();
300
+            $whereValues = array_merge($keys, $updatePreconditionValues);
301
+            foreach ($whereValues as $name => $value) {
302
+                $where->add($updateQb->expr()->eq(
303
+                    $name,
304
+                    $updateQb->createNamedParameter($value, $this->getType($value)),
305
+                    $this->getType($value)
306
+                ));
307
+            }
308
+            $updateQb->where($where);
309
+            $affected = $updateQb->execute();
310
+
311
+            if ($affected === 0 && !empty($updatePreconditionValues)) {
312
+                throw new PreConditionNotMetException();
313
+            }
314
+
315
+            return 0;
316
+        }
317
+    }
318
+
319
+    /**
320
+     * Create an exclusive read+write lock on a table
321
+     *
322
+     * @param string $tableName
323
+     * @throws \BadMethodCallException When trying to acquire a second lock
324
+     * @since 9.1.0
325
+     */
326
+    public function lockTable($tableName) {
327
+        if ($this->lockedTable !== null) {
328
+            throw new \BadMethodCallException('Can not lock a new table until the previous lock is released.');
329
+        }
330
+
331
+        $tableName = $this->tablePrefix . $tableName;
332
+        $this->lockedTable = $tableName;
333
+        $this->adapter->lockTable($tableName);
334
+    }
335
+
336
+    /**
337
+     * Release a previous acquired lock again
338
+     *
339
+     * @since 9.1.0
340
+     */
341
+    public function unlockTable() {
342
+        $this->adapter->unlockTable();
343
+        $this->lockedTable = null;
344
+    }
345
+
346
+    /**
347
+     * returns the error code and message as a string for logging
348
+     * works with DoctrineException
349
+     * @return string
350
+     */
351
+    public function getError() {
352
+        $msg = $this->errorCode() . ': ';
353
+        $errorInfo = $this->errorInfo();
354
+        if (is_array($errorInfo)) {
355
+            $msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
356
+            $msg .= 'Driver Code = '.$errorInfo[1] . ', ';
357
+            $msg .= 'Driver Message = '.$errorInfo[2];
358
+        }
359
+        return $msg;
360
+    }
361
+
362
+    /**
363
+     * Drop a table from the database if it exists
364
+     *
365
+     * @param string $table table name without the prefix
366
+     */
367
+    public function dropTable($table) {
368
+        $table = $this->tablePrefix . trim($table);
369
+        $schema = $this->getSchemaManager();
370
+        if($schema->tablesExist(array($table))) {
371
+            $schema->dropTable($table);
372
+        }
373
+    }
374
+
375
+    /**
376
+     * Check if a table exists
377
+     *
378
+     * @param string $table table name without the prefix
379
+     * @return bool
380
+     */
381
+    public function tableExists($table){
382
+        $table = $this->tablePrefix . trim($table);
383
+        $schema = $this->getSchemaManager();
384
+        return $schema->tablesExist(array($table));
385
+    }
386
+
387
+    // internal use
388
+    /**
389
+     * @param string $statement
390
+     * @return string
391
+     */
392
+    protected function replaceTablePrefix($statement) {
393
+        return str_replace( '*PREFIX*', $this->tablePrefix, $statement );
394
+    }
395
+
396
+    /**
397
+     * Check if a transaction is active
398
+     *
399
+     * @return bool
400
+     * @since 8.2.0
401
+     */
402
+    public function inTransaction() {
403
+        return $this->getTransactionNestingLevel() > 0;
404
+    }
405
+
406
+    /**
407
+     * Escape a parameter to be used in a LIKE query
408
+     *
409
+     * @param string $param
410
+     * @return string
411
+     */
412
+    public function escapeLikeParameter($param) {
413
+        return addcslashes($param, '\\_%');
414
+    }
415
+
416
+    /**
417
+     * Check whether or not the current database support 4byte wide unicode
418
+     *
419
+     * @return bool
420
+     * @since 11.0.0
421
+     */
422
+    public function supports4ByteText() {
423
+        if (!$this->getDatabasePlatform() instanceof MySqlPlatform) {
424
+            return true;
425
+        }
426
+        return $this->getParams()['charset'] === 'utf8mb4';
427
+    }
428
+
429
+
430
+    /**
431
+     * Create the schema of the connected database
432
+     *
433
+     * @return Schema
434
+     */
435
+    public function createSchema() {
436
+        $schemaManager = new MDB2SchemaManager($this);
437
+        $migrator = $schemaManager->getMigrator();
438
+        return $migrator->createSchema();
439
+    }
440
+
441
+    /**
442
+     * Migrate the database to the given schema
443
+     *
444
+     * @param Schema $toSchema
445
+     */
446
+    public function migrateToSchema(Schema $toSchema) {
447
+        $schemaManager = new MDB2SchemaManager($this);
448
+        $migrator = $schemaManager->getMigrator();
449
+        $migrator->migrate($toSchema);
450
+    }
451 451
 }
Please login to merge, or discard this patch.