Completed
Pull Request — master (#3089)
by Robin
30:27 queued 16:11
created

QueryBuilder::where()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Robin Appelman <[email protected]>
7
 * @author Thomas Müller <[email protected]>
8
 *
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
25
namespace OC\DB\QueryBuilder;
26
27
use Doctrine\DBAL\Platforms\MySqlPlatform;
28
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
29
use Doctrine\DBAL\Platforms\SqlitePlatform;
30
use OC\DB\OracleConnection;
31
use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
32
use OC\DB\QueryBuilder\ExpressionBuilder\MySqlExpressionBuilder;
33
use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder;
34
use OC\DB\QueryBuilder\ExpressionBuilder\PgSqlExpressionBuilder;
35
use OC\DB\QueryBuilder\ExpressionBuilder\SqliteExpressionBuilder;
36
use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder;
37
use OC\DB\QueryBuilder\FunctionBuilder\OCIFunctionBuilder;
38
use OC\DB\QueryBuilder\FunctionBuilder\PgSqlFunctionBuilder;
39
use OC\DB\QueryBuilder\FunctionBuilder\SqliteFunctionBuilder;
40
use OC\SystemConfig;
41
use OCP\DB\QueryBuilder\IQueryBuilder;
42
use OCP\DB\QueryBuilder\IQueryFunction;
43
use OCP\DB\QueryBuilder\IParameter;
44
use OCP\IDBConnection;
45
use OCP\ILogger;
46
47
class QueryBuilder implements IQueryBuilder {
48
49
	/** @var \OCP\IDBConnection */
50
	private $connection;
51
52
	/** @var SystemConfig */
53
	private $systemConfig;
54
55
	/** @var ILogger */
56
	private $logger;
57
58
	/** @var \Doctrine\DBAL\Query\QueryBuilder */
59
	private $queryBuilder;
60
61
	/** @var QuoteHelper */
62
	private $helper;
63
64
	/** @var bool */
65
	private $automaticTablePrefix = true;
66
67
	/** @var string */
68
	protected $lastInsertedTable;
69
70
	/**
71
	 * Initializes a new QueryBuilder.
72
	 *
73
	 * @param IDBConnection $connection
74
	 * @param SystemConfig $systemConfig
75
	 * @param ILogger $logger
76
	 */
77
	public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger) {
78
		$this->connection = $connection;
79
		$this->systemConfig = $systemConfig;
80
		$this->logger = $logger;
81
		$this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection);
82
		$this->helper = new QuoteHelper();
83
	}
84
85
	/**
86
	 * Enable/disable automatic prefixing of table names with the oc_ prefix
87
	 *
88
	 * @param bool $enabled If set to true table names will be prefixed with the
89
	 * owncloud database prefix automatically.
90
	 * @since 8.2.0
91
	 */
92
	public function automaticTablePrefix($enabled) {
93
		$this->automaticTablePrefix = (bool) $enabled;
94
	}
95
96
	/**
97
	 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
98
	 * This producer method is intended for convenient inline usage. Example:
99
	 *
100
	 * <code>
101
	 *     $qb = $conn->getQueryBuilder()
102
	 *         ->select('u')
103
	 *         ->from('users', 'u')
104
	 *         ->where($qb->expr()->eq('u.id', 1));
105
	 * </code>
106
	 *
107
	 * For more complex expression construction, consider storing the expression
108
	 * builder object in a local variable.
109
	 *
110
	 * @return \OCP\DB\QueryBuilder\IExpressionBuilder
111
	 */
112
	public function expr() {
113
		if ($this->connection instanceof OracleConnection) {
114
			return new OCIExpressionBuilder($this->connection);
115 View Code Duplication
		} else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\PostgreSqlPlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
116
			return new PgSqlExpressionBuilder($this->connection);
117
		} else if ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\MySqlPlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
118
			return new MySqlExpressionBuilder($this->connection);
119
		} else if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\SqlitePlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
120
			return new SqliteExpressionBuilder($this->connection);
121
		} else {
122
			return new ExpressionBuilder($this->connection);
123
		}
124
	}
125
126
	/**
127
	 * Gets an FunctionBuilder used for object-oriented construction of query functions.
128
	 * This producer method is intended for convenient inline usage. Example:
129
	 *
130
	 * <code>
131
	 *     $qb = $conn->getQueryBuilder()
132
	 *         ->select('u')
133
	 *         ->from('users', 'u')
134
	 *         ->where($qb->fun()->md5('u.id'));
135
	 * </code>
136
	 *
137
	 * For more complex function construction, consider storing the function
138
	 * builder object in a local variable.
139
	 *
140
	 * @return \OCP\DB\QueryBuilder\IFunctionBuilder
141
	 */
142
	public function func() {
143 View Code Duplication
		if ($this->connection instanceof OracleConnection) {
144
			return new OCIFunctionBuilder($this->helper);
145
		} else if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\SqlitePlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
146
			return new SqliteFunctionBuilder($this->helper);
147
		} else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\PostgreSqlPlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
148
			return new PgSqlFunctionBuilder($this->helper);
149
		} else {
150
			return new FunctionBuilder($this->helper);
151
		}
152
	}
153
154
	/**
155
	 * Gets the type of the currently built query.
156
	 *
157
	 * @return integer
158
	 */
159
	public function getType() {
160
		return $this->queryBuilder->getType();
161
	}
162
163
	/**
164
	 * Gets the associated DBAL Connection for this query builder.
165
	 *
166
	 * @return \OCP\IDBConnection
167
	 */
168
	public function getConnection() {
169
		return $this->connection;
170
	}
171
172
	/**
173
	 * Gets the state of this query builder instance.
174
	 *
175
	 * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
176
	 */
177
	public function getState() {
178
		return $this->queryBuilder->getState();
179
	}
180
181
	/**
182
	 * Executes this query using the bound parameters and their types.
183
	 *
184
	 * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate}
185
	 * for insert, update and delete statements.
186
	 *
187
	 * @return \Doctrine\DBAL\Driver\Statement|int
188
	 */
189
	public function execute() {
190
		if ($this->systemConfig->getValue('log_query', false)) {
191
			$params = [];
192
			foreach ($this->getParameters() as $placeholder => $value) {
193
				if (is_array($value)) {
194
					$params[] = $placeholder . ' => (\'' . implode('\', \'', $value) . '\')';
195
				} else {
196
					$params[] = $placeholder . ' => \'' . $value . '\'';
197
				}
198
			}
199
			if (empty($params)) {
200
				$this->logger->debug('DB QueryBuilder: \'{query}\'', [
201
					'query' => $this->getSQL(),
202
					'app' => 'core',
203
				]);
204
			} else {
205
				$this->logger->debug('DB QueryBuilder: \'{query}\' with parameters: {params}', [
206
					'query' => $this->getSQL(),
207
					'params' => implode(', ', $params),
208
					'app' => 'core',
209
				]);
210
			}
211
		}
212
213
		return $this->queryBuilder->execute();
214
	}
215
216
	/**
217
	 * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
218
	 *
219
	 * <code>
220
	 *     $qb = $conn->getQueryBuilder()
221
	 *         ->select('u')
222
	 *         ->from('User', 'u')
223
	 *     echo $qb->getSQL(); // SELECT u FROM User u
224
	 * </code>
225
	 *
226
	 * @return string The SQL query string.
227
	 */
228
	public function getSQL() {
229
		return $this->queryBuilder->getSQL();
230
	}
231
232
	/**
233
	 * Sets a query parameter for the query being constructed.
234
	 *
235
	 * <code>
236
	 *     $qb = $conn->getQueryBuilder()
237
	 *         ->select('u')
238
	 *         ->from('users', 'u')
239
	 *         ->where('u.id = :user_id')
240
	 *         ->setParameter(':user_id', 1);
241
	 * </code>
242
	 *
243
	 * @param string|integer $key The parameter position or name.
244
	 * @param mixed $value The parameter value.
245
	 * @param string|null $type One of the IQueryBuilder::PARAM_* constants.
246
	 *
247
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
248
	 */
249
	public function setParameter($key, $value, $type = null) {
250
		$this->queryBuilder->setParameter($key, $value, $type);
251
252
		return $this;
253
	}
254
255
	/**
256
	 * Sets a collection of query parameters for the query being constructed.
257
	 *
258
	 * <code>
259
	 *     $qb = $conn->getQueryBuilder()
260
	 *         ->select('u')
261
	 *         ->from('users', 'u')
262
	 *         ->where('u.id = :user_id1 OR u.id = :user_id2')
263
	 *         ->setParameters(array(
264
	 *             ':user_id1' => 1,
265
	 *             ':user_id2' => 2
266
	 *         ));
267
	 * </code>
268
	 *
269
	 * @param array $params The query parameters to set.
270
	 * @param array $types The query parameters types to set.
271
	 *
272
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
273
	 */
274
	public function setParameters(array $params, array $types = array()) {
275
		$this->queryBuilder->setParameters($params, $types);
276
277
		return $this;
278
	}
279
280
	/**
281
	 * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
282
	 *
283
	 * @return array The currently defined query parameters indexed by parameter index or name.
284
	 */
285
	public function getParameters() {
286
		return $this->queryBuilder->getParameters();
287
	}
288
289
	/**
290
	 * Gets a (previously set) query parameter of the query being constructed.
291
	 *
292
	 * @param mixed $key The key (index or name) of the bound parameter.
293
	 *
294
	 * @return mixed The value of the bound parameter.
295
	 */
296
	public function getParameter($key) {
297
		return $this->queryBuilder->getParameter($key);
298
	}
299
300
	/**
301
	 * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
302
	 *
303
	 * @return array The currently defined query parameter types indexed by parameter index or name.
304
	 */
305
	public function getParameterTypes() {
306
		return $this->queryBuilder->getParameterTypes();
307
	}
308
309
	/**
310
	 * Gets a (previously set) query parameter type of the query being constructed.
311
	 *
312
	 * @param mixed $key The key (index or name) of the bound parameter type.
313
	 *
314
	 * @return mixed The value of the bound parameter type.
315
	 */
316
	public function getParameterType($key) {
317
		return $this->queryBuilder->getParameterType($key);
318
	}
319
320
	/**
321
	 * Sets the position of the first result to retrieve (the "offset").
322
	 *
323
	 * @param integer $firstResult The first result to return.
324
	 *
325
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
326
	 */
327
	public function setFirstResult($firstResult) {
328
		$this->queryBuilder->setFirstResult($firstResult);
329
330
		return $this;
331
	}
332
333
	/**
334
	 * Gets the position of the first result the query object was set to retrieve (the "offset").
335
	 * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder.
336
	 *
337
	 * @return integer The position of the first result.
338
	 */
339
	public function getFirstResult() {
340
		return $this->queryBuilder->getFirstResult();
341
	}
342
343
	/**
344
	 * Sets the maximum number of results to retrieve (the "limit").
345
	 *
346
	 * NOTE: Setting max results to "0" will cause mixed behaviour. While most
347
	 * of the databases will just return an empty result set, Oracle will return
348
	 * all entries.
349
	 *
350
	 * @param integer $maxResults The maximum number of results to retrieve.
351
	 *
352
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
353
	 */
354
	public function setMaxResults($maxResults) {
355
		$this->queryBuilder->setMaxResults($maxResults);
356
357
		return $this;
358
	}
359
360
	/**
361
	 * Gets the maximum number of results the query object was set to retrieve (the "limit").
362
	 * Returns NULL if {@link setMaxResults} was not applied to this query builder.
363
	 *
364
	 * @return integer The maximum number of results.
365
	 */
366
	public function getMaxResults() {
367
		return $this->queryBuilder->getMaxResults();
368
	}
369
370
	/**
371
	 * Specifies an item that is to be returned in the query result.
372
	 * Replaces any previously specified selections, if any.
373
	 *
374
	 * <code>
375
	 *     $qb = $conn->getQueryBuilder()
376
	 *         ->select('u.id', 'p.id')
377
	 *         ->from('users', 'u')
378
	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
379
	 * </code>
380
	 *
381
	 * @param mixed $select The selection expressions.
382
	 *
383
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
384
	 */
385 View Code Duplication
	public function select($select = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
386
		$selects = is_array($select) ? $select : func_get_args();
387
388
		$this->queryBuilder->select(
389
			$this->helper->quoteColumnNames($selects)
390
		);
391
392
		return $this;
393
	}
394
395
	/**
396
	 * Specifies an item that is to be returned with a different name in the query result.
397
	 *
398
	 * <code>
399
	 *     $qb = $conn->getQueryBuilder()
400
	 *         ->selectAlias('u.id', 'user_id')
401
	 *         ->from('users', 'u')
402
	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
403
	 * </code>
404
	 *
405
	 * @param mixed $select The selection expressions.
406
	 * @param string $alias The column alias used in the constructed query.
407
	 *
408
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
409
	 */
410
	public function selectAlias($select, $alias) {
411
412
		$this->queryBuilder->addSelect(
413
			$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
414
		);
415
416
		return $this;
417
	}
418
419
	/**
420
	 * Specifies an item that is to be returned uniquely in the query result.
421
	 *
422
	 * <code>
423
	 *     $qb = $conn->getQueryBuilder()
424
	 *         ->selectDistinct('type')
425
	 *         ->from('users');
426
	 * </code>
427
	 *
428
	 * @param mixed $select The selection expressions.
429
	 *
430
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
431
	 */
432
	public function selectDistinct($select) {
433
434
		$this->queryBuilder->addSelect(
435
			'DISTINCT ' . $this->helper->quoteColumnName($select)
436
		);
437
438
		return $this;
439
	}
440
441
	/**
442
	 * Adds an item that is to be returned in the query result.
443
	 *
444
	 * <code>
445
	 *     $qb = $conn->getQueryBuilder()
446
	 *         ->select('u.id')
447
	 *         ->addSelect('p.id')
448
	 *         ->from('users', 'u')
449
	 *         ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
450
	 * </code>
451
	 *
452
	 * @param mixed $select The selection expression.
453
	 *
454
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
455
	 */
456 View Code Duplication
	public function addSelect($select = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
457
		$selects = is_array($select) ? $select : func_get_args();
458
459
		$this->queryBuilder->addSelect(
460
			$this->helper->quoteColumnNames($selects)
461
		);
462
463
		return $this;
464
	}
465
466
	/**
467
	 * Turns the query being built into a bulk delete query that ranges over
468
	 * a certain table.
469
	 *
470
	 * <code>
471
	 *     $qb = $conn->getQueryBuilder()
472
	 *         ->delete('users', 'u')
473
	 *         ->where('u.id = :user_id');
474
	 *         ->setParameter(':user_id', 1);
475
	 * </code>
476
	 *
477
	 * @param string $delete The table whose rows are subject to the deletion.
478
	 * @param string $alias The table alias used in the constructed query.
479
	 *
480
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
481
	 */
482
	public function delete($delete = null, $alias = null) {
483
		$this->queryBuilder->delete(
484
			$this->getTableName($delete),
485
			$alias
486
		);
487
488
		return $this;
489
	}
490
491
	/**
492
	 * Turns the query being built into a bulk update query that ranges over
493
	 * a certain table
494
	 *
495
	 * <code>
496
	 *     $qb = $conn->getQueryBuilder()
497
	 *         ->update('users', 'u')
498
	 *         ->set('u.password', md5('password'))
499
	 *         ->where('u.id = ?');
500
	 * </code>
501
	 *
502
	 * @param string $update The table whose rows are subject to the update.
503
	 * @param string $alias The table alias used in the constructed query.
504
	 *
505
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
506
	 */
507
	public function update($update = null, $alias = null) {
508
		$this->queryBuilder->update(
509
			$this->getTableName($update),
510
			$alias
511
		);
512
513
		return $this;
514
	}
515
516
	/**
517
	 * Turns the query being built into an insert query that inserts into
518
	 * a certain table
519
	 *
520
	 * <code>
521
	 *     $qb = $conn->getQueryBuilder()
522
	 *         ->insert('users')
523
	 *         ->values(
524
	 *             array(
525
	 *                 'name' => '?',
526
	 *                 'password' => '?'
527
	 *             )
528
	 *         );
529
	 * </code>
530
	 *
531
	 * @param string $insert The table into which the rows should be inserted.
532
	 *
533
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
534
	 */
535
	public function insert($insert = null) {
536
		$this->queryBuilder->insert(
537
			$this->getTableName($insert)
538
		);
539
540
		$this->lastInsertedTable = $insert;
541
542
		return $this;
543
	}
544
545
	/**
546
	 * Creates and adds a query root corresponding to the table identified by the
547
	 * given alias, forming a cartesian product with any existing query roots.
548
	 *
549
	 * <code>
550
	 *     $qb = $conn->getQueryBuilder()
551
	 *         ->select('u.id')
552
	 *         ->from('users', 'u')
553
	 * </code>
554
	 *
555
	 * @param string $from The table.
556
	 * @param string|null $alias The alias of the table.
557
	 *
558
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
559
	 */
560
	public function from($from, $alias = null) {
561
		$this->queryBuilder->from(
562
			$this->getTableName($from),
563
			$alias
564
		);
565
566
		return $this;
567
	}
568
569
	/**
570
	 * Creates and adds a join to the query.
571
	 *
572
	 * <code>
573
	 *     $qb = $conn->getQueryBuilder()
574
	 *         ->select('u.name')
575
	 *         ->from('users', 'u')
576
	 *         ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
577
	 * </code>
578
	 *
579
	 * @param string $fromAlias The alias that points to a from clause.
580
	 * @param string $join The table name to join.
581
	 * @param string $alias The alias of the join table.
582
	 * @param string $condition The condition for the join.
583
	 *
584
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
585
	 */
586
	public function join($fromAlias, $join, $alias, $condition = null) {
587
		$this->queryBuilder->join(
588
			$fromAlias,
589
			$this->getTableName($join),
590
			$alias,
591
			$condition
592
		);
593
594
		return $this;
595
	}
596
597
	/**
598
	 * Creates and adds a join to the query.
599
	 *
600
	 * <code>
601
	 *     $qb = $conn->getQueryBuilder()
602
	 *         ->select('u.name')
603
	 *         ->from('users', 'u')
604
	 *         ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
605
	 * </code>
606
	 *
607
	 * @param string $fromAlias The alias that points to a from clause.
608
	 * @param string $join The table name to join.
609
	 * @param string $alias The alias of the join table.
610
	 * @param string $condition The condition for the join.
611
	 *
612
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
613
	 */
614
	public function innerJoin($fromAlias, $join, $alias, $condition = null) {
615
		$this->queryBuilder->innerJoin(
616
			$fromAlias,
617
			$this->getTableName($join),
618
			$alias,
619
			$condition
620
		);
621
622
		return $this;
623
	}
624
625
	/**
626
	 * Creates and adds a left join to the query.
627
	 *
628
	 * <code>
629
	 *     $qb = $conn->getQueryBuilder()
630
	 *         ->select('u.name')
631
	 *         ->from('users', 'u')
632
	 *         ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
633
	 * </code>
634
	 *
635
	 * @param string $fromAlias The alias that points to a from clause.
636
	 * @param string $join The table name to join.
637
	 * @param string $alias The alias of the join table.
638
	 * @param string $condition The condition for the join.
639
	 *
640
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
641
	 */
642
	public function leftJoin($fromAlias, $join, $alias, $condition = null) {
643
		$this->queryBuilder->leftJoin(
644
			$fromAlias,
645
			$this->getTableName($join),
646
			$alias,
647
			$condition
648
		);
649
650
		return $this;
651
	}
652
653
	/**
654
	 * Creates and adds a right join to the query.
655
	 *
656
	 * <code>
657
	 *     $qb = $conn->getQueryBuilder()
658
	 *         ->select('u.name')
659
	 *         ->from('users', 'u')
660
	 *         ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
661
	 * </code>
662
	 *
663
	 * @param string $fromAlias The alias that points to a from clause.
664
	 * @param string $join The table name to join.
665
	 * @param string $alias The alias of the join table.
666
	 * @param string $condition The condition for the join.
667
	 *
668
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
669
	 */
670
	public function rightJoin($fromAlias, $join, $alias, $condition = null) {
671
		$this->queryBuilder->rightJoin(
672
			$fromAlias,
673
			$this->getTableName($join),
674
			$alias,
675
			$condition
676
		);
677
678
		return $this;
679
	}
680
681
	/**
682
	 * Sets a new value for a column in a bulk update query.
683
	 *
684
	 * <code>
685
	 *     $qb = $conn->getQueryBuilder()
686
	 *         ->update('users', 'u')
687
	 *         ->set('u.password', md5('password'))
688
	 *         ->where('u.id = ?');
689
	 * </code>
690
	 *
691
	 * @param string $key The column to set.
692
	 * @param string $value The value, expression, placeholder, etc.
693
	 *
694
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
695
	 */
696
	public function set($key, $value) {
697
		$this->queryBuilder->set(
698
			$this->helper->quoteColumnName($key),
699
			$this->helper->quoteColumnName($value)
700
		);
701
702
		return $this;
703
	}
704
705
	/**
706
	 * Specifies one or more restrictions to the query result.
707
	 * Replaces any previously specified restrictions, if any.
708
	 *
709
	 * <code>
710
	 *     $qb = $conn->getQueryBuilder()
711
	 *         ->select('u.name')
712
	 *         ->from('users', 'u')
713
	 *         ->where('u.id = ?');
714
	 *
715
	 *     // You can optionally programatically build and/or expressions
716
	 *     $qb = $conn->getQueryBuilder();
717
	 *
718
	 *     $or = $qb->expr()->orx();
719
	 *     $or->add($qb->expr()->eq('u.id', 1));
720
	 *     $or->add($qb->expr()->eq('u.id', 2));
721
	 *
722
	 *     $qb->update('users', 'u')
723
	 *         ->set('u.password', md5('password'))
724
	 *         ->where($or);
725
	 * </code>
726
	 *
727
	 * @param mixed $predicates The restriction predicates.
728
	 *
729
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
730
	 */
731
	public function where($predicates) {
732
		call_user_func_array(
733
			[$this->queryBuilder, 'where'],
734
			func_get_args()
735
		);
736
737
		return $this;
738
	}
739
740
	/**
741
	 * Adds one or more restrictions to the query results, forming a logical
742
	 * conjunction with any previously specified restrictions.
743
	 *
744
	 * <code>
745
	 *     $qb = $conn->getQueryBuilder()
746
	 *         ->select('u')
747
	 *         ->from('users', 'u')
748
	 *         ->where('u.username LIKE ?')
749
	 *         ->andWhere('u.is_active = 1');
750
	 * </code>
751
	 *
752
	 * @param mixed $where The query restrictions.
753
	 *
754
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
755
	 *
756
	 * @see where()
757
	 */
758
	public function andWhere($where) {
759
		call_user_func_array(
760
			[$this->queryBuilder, 'andWhere'],
761
			func_get_args()
762
		);
763
764
		return $this;
765
	}
766
767
	/**
768
	 * Adds one or more restrictions to the query results, forming a logical
769
	 * disjunction with any previously specified restrictions.
770
	 *
771
	 * <code>
772
	 *     $qb = $conn->getQueryBuilder()
773
	 *         ->select('u.name')
774
	 *         ->from('users', 'u')
775
	 *         ->where('u.id = 1')
776
	 *         ->orWhere('u.id = 2');
777
	 * </code>
778
	 *
779
	 * @param mixed $where The WHERE statement.
780
	 *
781
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
782
	 *
783
	 * @see where()
784
	 */
785
	public function orWhere($where) {
786
		call_user_func_array(
787
			[$this->queryBuilder, 'orWhere'],
788
			func_get_args()
789
		);
790
791
		return $this;
792
	}
793
794
	/**
795
	 * Specifies a grouping over the results of the query.
796
	 * Replaces any previously specified groupings, if any.
797
	 *
798
	 * <code>
799
	 *     $qb = $conn->getQueryBuilder()
800
	 *         ->select('u.name')
801
	 *         ->from('users', 'u')
802
	 *         ->groupBy('u.id');
803
	 * </code>
804
	 *
805
	 * @param mixed $groupBy The grouping expression.
806
	 *
807
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
808
	 */
809 View Code Duplication
	public function groupBy($groupBy) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
810
		$groupBys = is_array($groupBy) ? $groupBy : func_get_args();
811
812
		call_user_func_array(
813
			[$this->queryBuilder, 'groupBy'],
814
			$this->helper->quoteColumnNames($groupBys)
815
		);
816
817
		return $this;
818
	}
819
820
	/**
821
	 * Adds a grouping expression to the query.
822
	 *
823
	 * <code>
824
	 *     $qb = $conn->getQueryBuilder()
825
	 *         ->select('u.name')
826
	 *         ->from('users', 'u')
827
	 *         ->groupBy('u.lastLogin');
828
	 *         ->addGroupBy('u.createdAt')
829
	 * </code>
830
	 *
831
	 * @param mixed $groupBy The grouping expression.
832
	 *
833
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
834
	 */
835 View Code Duplication
	public function addGroupBy($groupBy) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
836
		$groupBys = is_array($groupBy) ? $groupBy : func_get_args();
837
838
		call_user_func_array(
839
			[$this->queryBuilder, 'addGroupBy'],
840
			$this->helper->quoteColumnNames($groupBys)
841
		);
842
843
		return $this;
844
	}
845
846
	/**
847
	 * Sets a value for a column in an insert query.
848
	 *
849
	 * <code>
850
	 *     $qb = $conn->getQueryBuilder()
851
	 *         ->insert('users')
852
	 *         ->values(
853
	 *             array(
854
	 *                 'name' => '?'
855
	 *             )
856
	 *         )
857
	 *         ->setValue('password', '?');
858
	 * </code>
859
	 *
860
	 * @param string $column The column into which the value should be inserted.
861
	 * @param string $value The value that should be inserted into the column.
862
	 *
863
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
864
	 */
865
	public function setValue($column, $value) {
866
		$this->queryBuilder->setValue(
867
			$this->helper->quoteColumnName($column),
868
			$value
869
		);
870
871
		return $this;
872
	}
873
874
	/**
875
	 * Specifies values for an insert query indexed by column names.
876
	 * Replaces any previous values, if any.
877
	 *
878
	 * <code>
879
	 *     $qb = $conn->getQueryBuilder()
880
	 *         ->insert('users')
881
	 *         ->values(
882
	 *             array(
883
	 *                 'name' => '?',
884
	 *                 'password' => '?'
885
	 *             )
886
	 *         );
887
	 * </code>
888
	 *
889
	 * @param array $values The values to specify for the insert query indexed by column names.
890
	 *
891
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
892
	 */
893
	public function values(array $values) {
894
		$quotedValues = [];
895
		foreach ($values as $key => $value) {
896
			$quotedValues[$this->helper->quoteColumnName($key)] = $value;
897
		}
898
899
		$this->queryBuilder->values($quotedValues);
900
901
		return $this;
902
	}
903
904
	/**
905
	 * Specifies a restriction over the groups of the query.
906
	 * Replaces any previous having restrictions, if any.
907
	 *
908
	 * @param mixed $having The restriction over the groups.
909
	 *
910
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
911
	 */
912
	public function having($having) {
913
		call_user_func_array(
914
			[$this->queryBuilder, 'having'],
915
			func_get_args()
916
		);
917
918
		return $this;
919
	}
920
921
	/**
922
	 * Adds a restriction over the groups of the query, forming a logical
923
	 * conjunction with any existing having restrictions.
924
	 *
925
	 * @param mixed $having The restriction to append.
926
	 *
927
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
928
	 */
929
	public function andHaving($having) {
930
		call_user_func_array(
931
			[$this->queryBuilder, 'andHaving'],
932
			func_get_args()
933
		);
934
935
		return $this;
936
	}
937
938
	/**
939
	 * Adds a restriction over the groups of the query, forming a logical
940
	 * disjunction with any existing having restrictions.
941
	 *
942
	 * @param mixed $having The restriction to add.
943
	 *
944
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
945
	 */
946
	public function orHaving($having) {
947
		call_user_func_array(
948
			[$this->queryBuilder, 'orHaving'],
949
			func_get_args()
950
		);
951
952
		return $this;
953
	}
954
955
	/**
956
	 * Specifies an ordering for the query results.
957
	 * Replaces any previously specified orderings, if any.
958
	 *
959
	 * @param string $sort The ordering expression.
960
	 * @param string $order The ordering direction.
961
	 *
962
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
963
	 */
964
	public function orderBy($sort, $order = null) {
965
		$this->queryBuilder->orderBy(
966
			$this->helper->quoteColumnName($sort),
967
			$order
968
		);
969
970
		return $this;
971
	}
972
973
	/**
974
	 * Adds an ordering to the query results.
975
	 *
976
	 * @param string $sort The ordering expression.
977
	 * @param string $order The ordering direction.
978
	 *
979
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
980
	 */
981
	public function addOrderBy($sort, $order = null) {
982
		$this->queryBuilder->addOrderBy(
983
			$this->helper->quoteColumnName($sort),
984
			$order
985
		);
986
987
		return $this;
988
	}
989
990
	/**
991
	 * Gets a query part by its name.
992
	 *
993
	 * @param string $queryPartName
994
	 *
995
	 * @return mixed
996
	 */
997
	public function getQueryPart($queryPartName) {
998
		return $this->queryBuilder->getQueryPart($queryPartName);
999
	}
1000
1001
	/**
1002
	 * Gets all query parts.
1003
	 *
1004
	 * @return array
1005
	 */
1006
	public function getQueryParts() {
1007
		return $this->queryBuilder->getQueryParts();
1008
	}
1009
1010
	/**
1011
	 * Resets SQL parts.
1012
	 *
1013
	 * @param array|null $queryPartNames
1014
	 *
1015
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
1016
	 */
1017
	public function resetQueryParts($queryPartNames = null) {
1018
		$this->queryBuilder->resetQueryParts($queryPartNames);
1019
1020
		return $this;
1021
	}
1022
1023
	/**
1024
	 * Resets a single SQL part.
1025
	 *
1026
	 * @param string $queryPartName
1027
	 *
1028
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
1029
	 */
1030
	public function resetQueryPart($queryPartName) {
1031
		$this->queryBuilder->resetQueryPart($queryPartName);
1032
1033
		return $this;
1034
	}
1035
1036
	/**
1037
	 * Creates a new named parameter and bind the value $value to it.
1038
	 *
1039
	 * This method provides a shortcut for PDOStatement::bindValue
1040
	 * when using prepared statements.
1041
	 *
1042
	 * The parameter $value specifies the value that you want to bind. If
1043
	 * $placeholder is not provided bindValue() will automatically create a
1044
	 * placeholder for you. An automatic placeholder will be of the name
1045
	 * ':dcValue1', ':dcValue2' etc.
1046
	 *
1047
	 * For more information see {@link http://php.net/pdostatement-bindparam}
1048
	 *
1049
	 * Example:
1050
	 * <code>
1051
	 * $value = 2;
1052
	 * $q->eq( 'id', $q->bindValue( $value ) );
1053
	 * $stmt = $q->executeQuery(); // executed with 'id = 2'
1054
	 * </code>
1055
	 *
1056
	 * @license New BSD License
1057
	 * @link http://www.zetacomponents.org
1058
	 *
1059
	 * @param mixed $value
1060
	 * @param mixed $type
1061
	 * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
1062
	 *
1063
	 * @return IParameter the placeholder name used.
1064
	 */
1065
	public function createNamedParameter($value, $type = IQueryBuilder::PARAM_STR, $placeHolder = null) {
1066
		return new Parameter($this->queryBuilder->createNamedParameter($value, $type, $placeHolder));
1067
	}
1068
1069
	/**
1070
	 * Creates a new positional parameter and bind the given value to it.
1071
	 *
1072
	 * Attention: If you are using positional parameters with the query builder you have
1073
	 * to be very careful to bind all parameters in the order they appear in the SQL
1074
	 * statement , otherwise they get bound in the wrong order which can lead to serious
1075
	 * bugs in your code.
1076
	 *
1077
	 * Example:
1078
	 * <code>
1079
	 *  $qb = $conn->getQueryBuilder();
1080
	 *  $qb->select('u.*')
1081
	 *     ->from('users', 'u')
1082
	 *     ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
1083
	 *     ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
1084
	 * </code>
1085
	 *
1086
	 * @param mixed $value
1087
	 * @param integer $type
1088
	 *
1089
	 * @return IParameter
1090
	 */
1091
	public function createPositionalParameter($value, $type = IQueryBuilder::PARAM_STR) {
1092
		return new Parameter($this->queryBuilder->createPositionalParameter($value, $type));
1093
	}
1094
1095
	/**
1096
	 * Creates a new parameter
1097
	 *
1098
	 * Example:
1099
	 * <code>
1100
	 *  $qb = $conn->getQueryBuilder();
1101
	 *  $qb->select('u.*')
1102
	 *     ->from('users', 'u')
1103
	 *     ->where('u.username = ' . $qb->createParameter('name'))
1104
	 *     ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
1105
	 * </code>
1106
	 *
1107
	 * @param string $name
1108
	 *
1109
	 * @return IParameter
1110
	 */
1111
	public function createParameter($name) {
1112
		return new Parameter(':' . $name);
1113
	}
1114
1115
	/**
1116
	 * Creates a new function
1117
	 *
1118
	 * Attention: Column names inside the call have to be quoted before hand
1119
	 *
1120
	 * Example:
1121
	 * <code>
1122
	 *  $qb = $conn->getQueryBuilder();
1123
	 *  $qb->select($qb->createFunction('COUNT(*)'))
1124
	 *     ->from('users', 'u')
1125
	 *  echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
1126
	 * </code>
1127
	 * <code>
1128
	 *  $qb = $conn->getQueryBuilder();
1129
	 *  $qb->select($qb->createFunction('COUNT(`column`)'))
1130
	 *     ->from('users', 'u')
1131
	 *  echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
1132
	 * </code>
1133
	 *
1134
	 * @param string $call
1135
	 *
1136
	 * @return IQueryFunction
1137
	 */
1138
	public function createFunction($call) {
1139
		return new QueryFunction($call);
1140
	}
1141
1142
	/**
1143
	 * Used to get the id of the last inserted element
1144
	 * @return int
1145
	 * @throws \BadMethodCallException When being called before an insert query has been run.
1146
	 */
1147
	public function getLastInsertId() {
1148
		if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) {
1149
			// lastInsertId() needs the prefix but no quotes
1150
			$table = $this->prefixTableName($this->lastInsertedTable);
1151
			return (int) $this->connection->lastInsertId($table);
1152
		}
1153
1154
		throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.');
1155
	}
1156
1157
	/**
1158
	 * Returns the table name quoted and with database prefix as needed by the implementation
1159
	 *
1160
	 * @param string $table
1161
	 * @return string
1162
	 */
1163
	public function getTableName($table) {
1164
		$table = $this->prefixTableName($table);
1165
		return $this->helper->quoteColumnName($table);
1166
	}
1167
1168
	/**
1169
	 * Returns the table name with database prefix as needed by the implementation
1170
	 *
1171
	 * @param string $table
1172
	 * @return string
1173
	 */
1174
	protected function prefixTableName($table) {
1175
		if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) {
1176
			return $table;
1177
		}
1178
1179
		return '*PREFIX*' . $table;
1180
	}
1181
1182
	/**
1183
	 * Returns the column name quoted and with table alias prefix as needed by the implementation
1184
	 *
1185
	 * @param string $column
1186
	 * @param string $tableAlias
1187
	 * @return string
1188
	 */
1189
	public function getColumnName($column, $tableAlias = '') {
1190
		if ($tableAlias !== '') {
1191
			$tableAlias .= '.';
1192
		}
1193
1194
		return $this->helper->quoteColumnName($tableAlias . $column);
1195
	}
1196
}
1197