Completed
Push — master ( 4ec76c...04a216 )
by
unknown
30:28
created
lib/public/DB/QueryBuilder/IQueryBuilder.php 1 patch
Indentation   +1068 added lines, -1068 removed lines patch added patch discarded remove patch
@@ -22,1072 +22,1072 @@
 block discarded – undo
22 22
  * @psalm-taint-specialize
23 23
  */
24 24
 interface IQueryBuilder {
25
-	/**
26
-	 * @since 9.0.0
27
-	 */
28
-	public const PARAM_NULL = ParameterType::NULL;
29
-	/**
30
-	 * @since 9.0.0
31
-	 */
32
-	public const PARAM_BOOL = Types::BOOLEAN;
33
-	/**
34
-	 * @since 9.0.0
35
-	 */
36
-	public const PARAM_INT = ParameterType::INTEGER;
37
-	/**
38
-	 * @since 9.0.0
39
-	 */
40
-	public const PARAM_STR = ParameterType::STRING;
41
-	/**
42
-	 * @since 9.0.0
43
-	 */
44
-	public const PARAM_LOB = ParameterType::LARGE_OBJECT;
45
-
46
-	/**
47
-	 * @since 9.0.0
48
-	 * @deprecated 31.0.0 - use PARAM_DATETIME_MUTABLE instead
49
-	 */
50
-	public const PARAM_DATE = Types::DATETIME_MUTABLE;
51
-
52
-	/**
53
-	 * For passing a \DateTime instance when only interested in the time part (without timezone support)
54
-	 * @since 31.0.0
55
-	 */
56
-	public const PARAM_TIME_MUTABLE = Types::TIME_MUTABLE;
57
-
58
-	/**
59
-	 * For passing a \DateTime instance when only interested in the date part (without timezone support)
60
-	 * @since 31.0.0
61
-	 */
62
-	public const PARAM_DATE_MUTABLE = Types::DATE_MUTABLE;
63
-
64
-	/**
65
-	 * For passing a \DateTime instance (without timezone support)
66
-	 * @since 31.0.0
67
-	 */
68
-	public const PARAM_DATETIME_MUTABLE = Types::DATETIME_MUTABLE;
69
-
70
-	/**
71
-	 * For passing a \DateTime instance with timezone support
72
-	 * @since 31.0.0
73
-	 */
74
-	public const PARAM_DATETIME_TZ_MUTABLE = Types::DATETIMETZ_MUTABLE;
75
-
76
-	/**
77
-	 * For passing a \DateTimeImmutable instance when only interested in the time part (without timezone support)
78
-	 * @since 31.0.0
79
-	 */
80
-	public const PARAM_TIME_IMMUTABLE = Types::TIME_MUTABLE;
81
-
82
-	/**
83
-	 * For passing a \DateTime instance when only interested in the date part (without timezone support)
84
-	 * @since 9.0.0
85
-	 */
86
-	public const PARAM_DATE_IMMUTABLE = Types::DATE_IMMUTABLE;
87
-
88
-	/**
89
-	 * For passing a \DateTime instance (without timezone support)
90
-	 * @since 31.0.0
91
-	 */
92
-	public const PARAM_DATETIME_IMMUTABLE = Types::DATETIME_IMMUTABLE;
93
-
94
-	/**
95
-	 * For passing a \DateTime instance with timezone support
96
-	 * @since 31.0.0
97
-	 */
98
-	public const PARAM_DATETIME_TZ_IMMUTABLE = Types::DATETIMETZ_IMMUTABLE;
99
-
100
-	/**
101
-	 * @since 24.0.0
102
-	 */
103
-	public const PARAM_JSON = 'json';
104
-
105
-	/**
106
-	 * @since 9.0.0
107
-	 */
108
-	public const PARAM_INT_ARRAY = ArrayParameterType::INTEGER;
109
-	/**
110
-	 * @since 9.0.0
111
-	 */
112
-	public const PARAM_STR_ARRAY = ArrayParameterType::STRING;
113
-
114
-	/**
115
-	 * @since 24.0.0 Indicates how many rows can be deleted at once with MySQL
116
-	 * database server.
117
-	 */
118
-	public const MAX_ROW_DELETION = 100000;
119
-
120
-	/**
121
-	 * Enable/disable automatic prefixing of table names with the oc_ prefix
122
-	 *
123
-	 * @param bool $enabled If set to true table names will be prefixed with the
124
-	 *                      owncloud database prefix automatically.
125
-	 * @since 8.2.0
126
-	 */
127
-	public function automaticTablePrefix($enabled);
128
-
129
-	/**
130
-	 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
131
-	 * This producer method is intended for convenient inline usage. Example:
132
-	 *
133
-	 * <code>
134
-	 *     $qb = $conn->getQueryBuilder()
135
-	 *         ->select('u')
136
-	 *         ->from('users', 'u')
137
-	 *         ->where($qb->expr()->eq('u.id', 1));
138
-	 * </code>
139
-	 *
140
-	 * For more complex expression construction, consider storing the expression
141
-	 * builder object in a local variable.
142
-	 *
143
-	 * @return \OCP\DB\QueryBuilder\IExpressionBuilder
144
-	 * @since 8.2.0
145
-	 */
146
-	public function expr();
147
-
148
-	/**
149
-	 * Gets an FunctionBuilder used for object-oriented construction of query functions.
150
-	 * This producer method is intended for convenient inline usage. Example:
151
-	 *
152
-	 * <code>
153
-	 *     $qb = $conn->getQueryBuilder()
154
-	 *         ->select('u')
155
-	 *         ->from('users', 'u')
156
-	 *         ->where($qb->fun()->md5('u.id'));
157
-	 * </code>
158
-	 *
159
-	 * For more complex function construction, consider storing the function
160
-	 * builder object in a local variable.
161
-	 *
162
-	 * @return \OCP\DB\QueryBuilder\IFunctionBuilder
163
-	 * @since 12.0.0
164
-	 */
165
-	public function func();
166
-
167
-	/**
168
-	 * Gets the type of the currently built query.
169
-	 *
170
-	 * @return integer
171
-	 * @since 8.2.0
172
-	 */
173
-	public function getType();
174
-
175
-	/**
176
-	 * Gets the associated DBAL Connection for this query builder.
177
-	 *
178
-	 * @return \OCP\IDBConnection
179
-	 * @since 8.2.0
180
-	 */
181
-	public function getConnection();
182
-
183
-	/**
184
-	 * Gets the state of this query builder instance.
185
-	 *
186
-	 * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
187
-	 * @since 8.2.0
188
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
189
-	 *    and we can not fix this in our wrapper.
190
-	 */
191
-	public function getState();
192
-
193
-	/**
194
-	 * Execute for select statements
195
-	 *
196
-	 * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0
197
-	 * @return IResult
198
-	 * @since 22.0.0
199
-	 *
200
-	 * @throws Exception
201
-	 * @throws \RuntimeException in case of usage with non select query
202
-	 */
203
-	public function executeQuery(?IDBConnection $connection = null): IResult;
204
-
205
-	/**
206
-	 * Execute insert, update and delete statements
207
-	 *
208
-	 * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0
209
-	 * @return int the number of affected rows
210
-	 * @since 22.0.0
211
-	 *
212
-	 * @throws Exception
213
-	 * @throws \RuntimeException in case of usage with select query
214
-	 */
215
-	public function executeStatement(?IDBConnection $connection = null): int;
216
-
217
-	/**
218
-	 * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
219
-	 *
220
-	 * <code>
221
-	 *     $qb = $conn->getQueryBuilder()
222
-	 *         ->select('u')
223
-	 *         ->from('User', 'u')
224
-	 *     echo $qb->getSQL(); // SELECT u FROM User u
225
-	 * </code>
226
-	 *
227
-	 * @return string The SQL query string.
228
-	 * @since 8.2.0
229
-	 */
230
-	public function getSQL();
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|int $type One of the IQueryBuilder::PARAM_* constants.
246
-	 *
247
-	 * @return $this This QueryBuilder instance.
248
-	 * @since 8.2.0
249
-	 */
250
-	public function setParameter($key, $value, $type = null);
251
-
252
-	/**
253
-	 * Sets a collection of query parameters for the query being constructed.
254
-	 *
255
-	 * <code>
256
-	 *     $qb = $conn->getQueryBuilder()
257
-	 *         ->select('u')
258
-	 *         ->from('users', 'u')
259
-	 *         ->where('u.id = :user_id1 OR u.id = :user_id2')
260
-	 *         ->setParameters(array(
261
-	 *             ':user_id1' => 1,
262
-	 *             ':user_id2' => 2
263
-	 *         ));
264
-	 * </code>
265
-	 *
266
-	 * @param array $params The query parameters to set.
267
-	 * @param array $types The query parameters types to set.
268
-	 *
269
-	 * @return $this This QueryBuilder instance.
270
-	 * @since 8.2.0
271
-	 */
272
-	public function setParameters(array $params, array $types = []);
273
-
274
-	/**
275
-	 * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
276
-	 *
277
-	 * @return array The currently defined query parameters indexed by parameter index or name.
278
-	 * @since 8.2.0
279
-	 */
280
-	public function getParameters();
281
-
282
-	/**
283
-	 * Gets a (previously set) query parameter of the query being constructed.
284
-	 *
285
-	 * @param mixed $key The key (index or name) of the bound parameter.
286
-	 *
287
-	 * @return mixed The value of the bound parameter.
288
-	 * @since 8.2.0
289
-	 */
290
-	public function getParameter($key);
291
-
292
-	/**
293
-	 * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
294
-	 *
295
-	 * @return array The currently defined query parameter types indexed by parameter index or name.
296
-	 * @since 8.2.0
297
-	 */
298
-	public function getParameterTypes();
299
-
300
-	/**
301
-	 * Gets a (previously set) query parameter type of the query being constructed.
302
-	 *
303
-	 * @param mixed $key The key (index or name) of the bound parameter type.
304
-	 *
305
-	 * @return mixed The value of the bound parameter type.
306
-	 * @since 8.2.0
307
-	 */
308
-	public function getParameterType($key);
309
-
310
-	/**
311
-	 * Sets the position of the first result to retrieve (the "offset").
312
-	 *
313
-	 * @param int $firstResult The first result to return.
314
-	 *
315
-	 * @return $this This QueryBuilder instance.
316
-	 * @since 8.2.0
317
-	 */
318
-	public function setFirstResult($firstResult);
319
-
320
-	/**
321
-	 * Gets the position of the first result the query object was set to retrieve (the "offset").
322
-	 * Returns 0 if {@link setFirstResult} was not applied to this QueryBuilder.
323
-	 *
324
-	 * @return int The position of the first result.
325
-	 * @since 8.2.0
326
-	 */
327
-	public function getFirstResult();
328
-
329
-	/**
330
-	 * Sets the maximum number of results to retrieve (the "limit").
331
-	 *
332
-	 * @param int|null $maxResults The maximum number of results to retrieve.
333
-	 *
334
-	 * @return $this This QueryBuilder instance.
335
-	 * @since 8.2.0
336
-	 */
337
-	public function setMaxResults($maxResults);
338
-
339
-	/**
340
-	 * Gets the maximum number of results the query object was set to retrieve (the "limit").
341
-	 * Returns NULL if {@link setMaxResults} was not applied to this query builder.
342
-	 *
343
-	 * @return int|null The maximum number of results.
344
-	 * @since 8.2.0
345
-	 */
346
-	public function getMaxResults();
347
-
348
-	/**
349
-	 * Specifies an item that is to be returned in the query result.
350
-	 * Replaces any previously specified selections, if any.
351
-	 *
352
-	 * <code>
353
-	 *     $qb = $conn->getQueryBuilder()
354
-	 *         ->select('u.id', 'p.id')
355
-	 *         ->from('users', 'u')
356
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
357
-	 * </code>
358
-	 *
359
-	 * @param mixed ...$selects The selection expressions.
360
-	 *
361
-	 * @return $this This QueryBuilder instance.
362
-	 * @since 8.2.0
363
-	 *
364
-	 * @psalm-taint-sink sql $selects
365
-	 */
366
-	public function select(...$selects);
367
-
368
-	/**
369
-	 * Specifies an item that is to be returned with a different name in the query result.
370
-	 *
371
-	 * <code>
372
-	 *     $qb = $conn->getQueryBuilder()
373
-	 *         ->selectAlias('u.id', 'user_id')
374
-	 *         ->from('users', 'u')
375
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
376
-	 * </code>
377
-	 *
378
-	 * @param mixed $select The selection expressions.
379
-	 * @param string $alias The column alias used in the constructed query.
380
-	 *
381
-	 * @return $this This QueryBuilder instance.
382
-	 * @since 8.2.1
383
-	 *
384
-	 * @psalm-taint-sink sql $select
385
-	 * @psalm-taint-sink sql $alias
386
-	 */
387
-	public function selectAlias($select, $alias);
388
-
389
-	/**
390
-	 * Specifies an item that is to be returned uniquely in the query result.
391
-	 *
392
-	 * <code>
393
-	 *     $qb = $conn->getQueryBuilder()
394
-	 *         ->selectDistinct('type')
395
-	 *         ->from('users');
396
-	 * </code>
397
-	 *
398
-	 * @param mixed $select The selection expressions.
399
-	 *
400
-	 * @return $this This QueryBuilder instance.
401
-	 * @since 9.0.0
402
-	 *
403
-	 * @psalm-taint-sink sql $select
404
-	 */
405
-	public function selectDistinct($select);
406
-
407
-	/**
408
-	 * Adds an item that is to be returned in the query result.
409
-	 *
410
-	 * <code>
411
-	 *     $qb = $conn->getQueryBuilder()
412
-	 *         ->select('u.id')
413
-	 *         ->addSelect('p.id')
414
-	 *         ->from('users', 'u')
415
-	 *         ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
416
-	 * </code>
417
-	 *
418
-	 * @param mixed ...$select The selection expression.
419
-	 *
420
-	 * @return $this This QueryBuilder instance.
421
-	 * @since 8.2.0
422
-	 *
423
-	 * @psalm-taint-sink sql $select
424
-	 */
425
-	public function addSelect(...$select);
426
-
427
-	/**
428
-	 * Turns the query being built into a bulk delete query that ranges over
429
-	 * a certain table.
430
-	 *
431
-	 * <code>
432
-	 *     $qb = $conn->getQueryBuilder()
433
-	 *         ->delete('users')
434
-	 *         ->where('id = :user_id');
435
-	 *         ->setParameter(':user_id', 1);
436
-	 * </code>
437
-	 *
438
-	 * @param string $delete The table whose rows are subject to the deletion.
439
-	 * @param string $alias The table alias used in the constructed query.
440
-	 *
441
-	 * @return $this This QueryBuilder instance.
442
-	 * @since 8.2.0
443
-	 * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
444
-	 *
445
-	 * @psalm-taint-sink sql $delete
446
-	 */
447
-	public function delete($delete = null, $alias = null);
448
-
449
-	/**
450
-	 * Turns the query being built into a bulk update query that ranges over
451
-	 * a certain table
452
-	 *
453
-	 * <code>
454
-	 *     $qb = $conn->getQueryBuilder()
455
-	 *         ->update('users')
456
-	 *         ->set('email', ':email')
457
-	 *         ->where('id = :user_id');
458
-	 *         ->setParameter(':user_id', 1);
459
-	 * </code>
460
-	 *
461
-	 * @param string $update The table whose rows are subject to the update.
462
-	 * @param string $alias The table alias used in the constructed query.
463
-	 *
464
-	 * @return $this This QueryBuilder instance.
465
-	 * @since 8.2.0
466
-	 * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
467
-	 *
468
-	 * @psalm-taint-sink sql $update
469
-	 */
470
-	public function update($update = null, $alias = null);
471
-
472
-	/**
473
-	 * Turns the query being built into an insert query that inserts into
474
-	 * a certain table
475
-	 *
476
-	 * <code>
477
-	 *     $qb = $conn->getQueryBuilder()
478
-	 *         ->insert('users')
479
-	 *         ->values(
480
-	 *             array(
481
-	 *                 'name' => '?',
482
-	 *                 'password' => '?'
483
-	 *             )
484
-	 *         );
485
-	 * </code>
486
-	 *
487
-	 * @param string $insert The table into which the rows should be inserted.
488
-	 *
489
-	 * @return $this This QueryBuilder instance.
490
-	 * @since 8.2.0
491
-	 *
492
-	 * @psalm-taint-sink sql $insert
493
-	 */
494
-	public function insert($insert = null);
495
-
496
-	/**
497
-	 * Creates and adds a query root corresponding to the table identified by the
498
-	 * given alias, forming a cartesian product with any existing query roots.
499
-	 *
500
-	 * <code>
501
-	 *     $qb = $conn->getQueryBuilder()
502
-	 *         ->select('u.id')
503
-	 *         ->from('users', 'u')
504
-	 * </code>
505
-	 *
506
-	 * @param string|IQueryFunction $from The table.
507
-	 * @param string|null $alias The alias of the table.
508
-	 *
509
-	 * @return $this This QueryBuilder instance.
510
-	 * @since 8.2.0
511
-	 *
512
-	 * @psalm-taint-sink sql $from
513
-	 */
514
-	public function from($from, $alias = null);
515
-
516
-	/**
517
-	 * Creates and adds a join to the query.
518
-	 *
519
-	 * <code>
520
-	 *     $qb = $conn->getQueryBuilder()
521
-	 *         ->select('u.name')
522
-	 *         ->from('users', 'u')
523
-	 *         ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
524
-	 * </code>
525
-	 *
526
-	 * @param string $fromAlias The alias that points to a from clause.
527
-	 * @param string $join The table name to join.
528
-	 * @param string $alias The alias of the join table.
529
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
530
-	 *
531
-	 * @return $this This QueryBuilder instance.
532
-	 * @since 8.2.0
533
-	 *
534
-	 * @psalm-taint-sink sql $fromAlias
535
-	 * @psalm-taint-sink sql $join
536
-	 * @psalm-taint-sink sql $alias
537
-	 * @psalm-taint-sink sql $condition
538
-	 */
539
-	public function join($fromAlias, $join, $alias, $condition = null);
540
-
541
-	/**
542
-	 * Creates and adds a join to the query.
543
-	 *
544
-	 * <code>
545
-	 *     $qb = $conn->getQueryBuilder()
546
-	 *         ->select('u.name')
547
-	 *         ->from('users', 'u')
548
-	 *         ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
549
-	 * </code>
550
-	 *
551
-	 * @param string $fromAlias The alias that points to a from clause.
552
-	 * @param string $join The table name to join.
553
-	 * @param string $alias The alias of the join table.
554
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
555
-	 *
556
-	 * @return $this This QueryBuilder instance.
557
-	 * @since 8.2.0
558
-	 *
559
-	 * @psalm-taint-sink sql $fromAlias
560
-	 * @psalm-taint-sink sql $join
561
-	 * @psalm-taint-sink sql $alias
562
-	 * @psalm-taint-sink sql $condition
563
-	 */
564
-	public function innerJoin($fromAlias, $join, $alias, $condition = null);
565
-
566
-	/**
567
-	 * Creates and adds a left join to the query.
568
-	 *
569
-	 * <code>
570
-	 *     $qb = $conn->getQueryBuilder()
571
-	 *         ->select('u.name')
572
-	 *         ->from('users', 'u')
573
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
574
-	 * </code>
575
-	 *
576
-	 * @param string $fromAlias The alias that points to a from clause.
577
-	 * @param string|IQueryFunction $join The table name to join.
578
-	 * @param string $alias The alias of the join table.
579
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
580
-	 *
581
-	 * @return $this This QueryBuilder instance.
582
-	 * @since 8.2.0
583
-	 * @since 30.0.0 Allow passing IQueryFunction as parameter for `$join` to allow join with a sub-query.
584
-	 *
585
-	 * @psalm-taint-sink sql $fromAlias
586
-	 * @psalm-taint-sink sql $join
587
-	 * @psalm-taint-sink sql $alias
588
-	 * @psalm-taint-sink sql $condition
589
-	 */
590
-	public function leftJoin($fromAlias, $join, $alias, $condition = null);
591
-
592
-	/**
593
-	 * Creates and adds a right join to the query.
594
-	 *
595
-	 * <code>
596
-	 *     $qb = $conn->getQueryBuilder()
597
-	 *         ->select('u.name')
598
-	 *         ->from('users', 'u')
599
-	 *         ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
600
-	 * </code>
601
-	 *
602
-	 * @param string $fromAlias The alias that points to a from clause.
603
-	 * @param string $join The table name to join.
604
-	 * @param string $alias The alias of the join table.
605
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
606
-	 *
607
-	 * @return $this This QueryBuilder instance.
608
-	 * @since 8.2.0
609
-	 *
610
-	 * @psalm-taint-sink sql $fromAlias
611
-	 * @psalm-taint-sink sql $join
612
-	 * @psalm-taint-sink sql $alias
613
-	 * @psalm-taint-sink sql $condition
614
-	 */
615
-	public function rightJoin($fromAlias, $join, $alias, $condition = null);
616
-
617
-	/**
618
-	 * Sets a new value for a column in a bulk update query.
619
-	 *
620
-	 * <code>
621
-	 *     $qb = $conn->getQueryBuilder()
622
-	 *         ->update('users', 'u')
623
-	 *         ->set('u.password', md5('password'))
624
-	 *         ->where('u.id = ?');
625
-	 * </code>
626
-	 *
627
-	 * @param string $key The column to set.
628
-	 * @param ILiteral|IParameter|IQueryFunction|string $value The value, expression, placeholder, etc.
629
-	 *
630
-	 * @return $this This QueryBuilder instance.
631
-	 * @since 8.2.0
632
-	 *
633
-	 * @psalm-taint-sink sql $key
634
-	 * @psalm-taint-sink sql $value
635
-	 */
636
-	public function set($key, $value);
637
-
638
-	/**
639
-	 * Specifies one or more restrictions to the query result.
640
-	 * Replaces any previously specified restrictions, if any.
641
-	 *
642
-	 * <code>
643
-	 *     $qb = $conn->getQueryBuilder()
644
-	 *         ->select('u.name')
645
-	 *         ->from('users', 'u')
646
-	 *         ->where('u.id = ?');
647
-	 *
648
-	 *     // You can optionally programmatically build and/or expressions
649
-	 *     $qb = $conn->getQueryBuilder();
650
-	 *
651
-	 *     $or = $qb->expr()->orx(
652
-	 *         $qb->expr()->eq('u.id', 1),
653
-	 *         $qb->expr()->eq('u.id', 2),
654
-	 *     );
655
-	 *
656
-	 *     $qb->update('users', 'u')
657
-	 *         ->set('u.password', md5('password'))
658
-	 *         ->where($or);
659
-	 * </code>
660
-	 *
661
-	 * @param mixed $predicates The restriction predicates.
662
-	 *
663
-	 * @return $this This QueryBuilder instance.
664
-	 * @since 8.2.0
665
-	 *
666
-	 * @psalm-taint-sink sql $predicates
667
-	 */
668
-	public function where(...$predicates);
669
-
670
-	/**
671
-	 * Adds one or more restrictions to the query results, forming a logical
672
-	 * conjunction with any previously specified restrictions.
673
-	 *
674
-	 * <code>
675
-	 *     $qb = $conn->getQueryBuilder()
676
-	 *         ->select('u')
677
-	 *         ->from('users', 'u')
678
-	 *         ->where('u.username LIKE ?')
679
-	 *         ->andWhere('u.is_active = 1');
680
-	 * </code>
681
-	 *
682
-	 * @param mixed ...$where The query restrictions.
683
-	 *
684
-	 * @return $this This QueryBuilder instance.
685
-	 *
686
-	 * @see where()
687
-	 * @since 8.2.0
688
-	 *
689
-	 * @psalm-taint-sink sql $where
690
-	 */
691
-	public function andWhere(...$where);
692
-
693
-	/**
694
-	 * Adds one or more restrictions to the query results, forming a logical
695
-	 * disjunction with any previously specified restrictions.
696
-	 *
697
-	 * <code>
698
-	 *     $qb = $conn->getQueryBuilder()
699
-	 *         ->select('u.name')
700
-	 *         ->from('users', 'u')
701
-	 *         ->where('u.id = 1')
702
-	 *         ->orWhere('u.id = 2');
703
-	 * </code>
704
-	 *
705
-	 * @param mixed ...$where The WHERE statement.
706
-	 *
707
-	 * @return $this This QueryBuilder instance.
708
-	 *
709
-	 * @see where()
710
-	 * @since 8.2.0
711
-	 *
712
-	 * @psalm-taint-sink sql $where
713
-	 */
714
-	public function orWhere(...$where);
715
-
716
-	/**
717
-	 * Specifies a grouping over the results of the query.
718
-	 * Replaces any previously specified groupings, if any.
719
-	 *
720
-	 * <code>
721
-	 *     $qb = $conn->getQueryBuilder()
722
-	 *         ->select('u.name')
723
-	 *         ->from('users', 'u')
724
-	 *         ->groupBy('u.id');
725
-	 * </code>
726
-	 *
727
-	 * @param mixed ...$groupBys The grouping expression.
728
-	 *
729
-	 * @return $this This QueryBuilder instance.
730
-	 * @since 8.2.0
731
-	 *
732
-	 * @psalm-taint-sink sql $groupBys
733
-	 */
734
-	public function groupBy(...$groupBys);
735
-
736
-	/**
737
-	 * Adds a grouping expression to the query.
738
-	 *
739
-	 * <code>
740
-	 *     $qb = $conn->getQueryBuilder()
741
-	 *         ->select('u.name')
742
-	 *         ->from('users', 'u')
743
-	 *         ->groupBy('u.lastLogin');
744
-	 *         ->addGroupBy('u.createdAt')
745
-	 * </code>
746
-	 *
747
-	 * @param mixed ...$groupBy The grouping expression.
748
-	 *
749
-	 * @return $this This QueryBuilder instance.
750
-	 * @since 8.2.0
751
-	 *
752
-	 * @psalm-taint-sink sql $groupby
753
-	 */
754
-	public function addGroupBy(...$groupBy);
755
-
756
-	/**
757
-	 * Sets a value for a column in an insert query.
758
-	 *
759
-	 * <code>
760
-	 *     $qb = $conn->getQueryBuilder()
761
-	 *         ->insert('users')
762
-	 *         ->values(
763
-	 *             array(
764
-	 *                 'name' => '?'
765
-	 *             )
766
-	 *         )
767
-	 *         ->setValue('password', '?');
768
-	 * </code>
769
-	 *
770
-	 * @param string $column The column into which the value should be inserted.
771
-	 * @param IParameter|string $value The value that should be inserted into the column.
772
-	 *
773
-	 * @return $this This QueryBuilder instance.
774
-	 * @since 8.2.0
775
-	 *
776
-	 * @psalm-taint-sink sql $column
777
-	 * @psalm-taint-sink sql $value
778
-	 */
779
-	public function setValue($column, $value);
780
-
781
-	/**
782
-	 * Specifies values for an insert query indexed by column names.
783
-	 * Replaces any previous values, if any.
784
-	 *
785
-	 * <code>
786
-	 *     $qb = $conn->getQueryBuilder()
787
-	 *         ->insert('users')
788
-	 *         ->values(
789
-	 *             array(
790
-	 *                 'name' => '?',
791
-	 *                 'password' => '?'
792
-	 *             )
793
-	 *         );
794
-	 * </code>
795
-	 *
796
-	 * @param array $values The values to specify for the insert query indexed by column names.
797
-	 *
798
-	 * @return $this This QueryBuilder instance.
799
-	 * @since 8.2.0
800
-	 *
801
-	 * @psalm-taint-sink sql $values
802
-	 */
803
-	public function values(array $values);
804
-
805
-	/**
806
-	 * Specifies a restriction over the groups of the query.
807
-	 * Replaces any previous having restrictions, if any.
808
-	 *
809
-	 * @param mixed ...$having The restriction over the groups.
810
-	 *
811
-	 * @return $this This QueryBuilder instance.
812
-	 * @since 8.2.0
813
-	 *
814
-	 * @psalm-taint-sink sql $having
815
-	 */
816
-	public function having(...$having);
817
-
818
-	/**
819
-	 * Adds a restriction over the groups of the query, forming a logical
820
-	 * conjunction with any existing having restrictions.
821
-	 *
822
-	 * @param mixed ...$having The restriction to append.
823
-	 *
824
-	 * @return $this This QueryBuilder instance.
825
-	 * @since 8.2.0
826
-	 *
827
-	 * @psalm-taint-sink sql $andHaving
828
-	 */
829
-	public function andHaving(...$having);
830
-
831
-	/**
832
-	 * Adds a restriction over the groups of the query, forming a logical
833
-	 * disjunction with any existing having restrictions.
834
-	 *
835
-	 * @param mixed ...$having The restriction to add.
836
-	 *
837
-	 * @return $this This QueryBuilder instance.
838
-	 * @since 8.2.0
839
-	 *
840
-	 * @psalm-taint-sink sql $having
841
-	 */
842
-	public function orHaving(...$having);
843
-
844
-	/**
845
-	 * Specifies an ordering for the query results.
846
-	 * Replaces any previously specified orderings, if any.
847
-	 *
848
-	 * @param string|IQueryFunction|ILiteral|IParameter $sort The ordering expression.
849
-	 * @param string $order The ordering direction.
850
-	 *
851
-	 * @return $this This QueryBuilder instance.
852
-	 * @since 8.2.0
853
-	 *
854
-	 * @psalm-taint-sink sql $sort
855
-	 * @psalm-taint-sink sql $order
856
-	 */
857
-	public function orderBy($sort, $order = null);
858
-
859
-	/**
860
-	 * Adds an ordering to the query results.
861
-	 *
862
-	 * @param string|ILiteral|IParameter|IQueryFunction $sort The ordering expression.
863
-	 * @param string $order The ordering direction.
864
-	 *
865
-	 * @return $this This QueryBuilder instance.
866
-	 * @since 8.2.0
867
-	 *
868
-	 * @psalm-taint-sink sql $sort
869
-	 * @psalm-taint-sink sql $order
870
-	 */
871
-	public function addOrderBy($sort, $order = null);
872
-
873
-	/**
874
-	 * Gets a query part by its name.
875
-	 *
876
-	 * @param string $queryPartName
877
-	 *
878
-	 * @return mixed
879
-	 * @since 8.2.0
880
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
881
-	 *  and we can not fix this in our wrapper. Please track the details you need, outside the object.
882
-	 */
883
-	public function getQueryPart($queryPartName);
884
-
885
-	/**
886
-	 * Gets all query parts.
887
-	 *
888
-	 * @return array
889
-	 * @since 8.2.0
890
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
891
-	 *  and we can not fix this in our wrapper. Please track the details you need, outside the object.
892
-	 */
893
-	public function getQueryParts();
894
-
895
-	/**
896
-	 * Resets SQL parts.
897
-	 *
898
-	 * @param array|null $queryPartNames
899
-	 *
900
-	 * @return $this This QueryBuilder instance.
901
-	 * @since 8.2.0
902
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
903
-	 * and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
904
-	 */
905
-	public function resetQueryParts($queryPartNames = null);
906
-
907
-	/**
908
-	 * Resets a single SQL part.
909
-	 *
910
-	 * @param string $queryPartName
911
-	 *
912
-	 * @return $this This QueryBuilder instance.
913
-	 * @since 8.2.0
914
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
915
-	 *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
916
-	 */
917
-	public function resetQueryPart($queryPartName);
918
-
919
-	/**
920
-	 * Creates a new named parameter and bind the value $value to it.
921
-	 *
922
-	 * This method provides a shortcut for PDOStatement::bindValue
923
-	 * when using prepared statements.
924
-	 *
925
-	 * The parameter $value specifies the value that you want to bind. If
926
-	 * $placeholder is not provided bindValue() will automatically create a
927
-	 * placeholder for you. An automatic placeholder will be of the name
928
-	 * ':dcValue1', ':dcValue2' etc.
929
-	 *
930
-	 * For more information see {@link https://www.php.net/pdostatement-bindparam}
931
-	 *
932
-	 * Example:
933
-	 * <code>
934
-	 * $value = 2;
935
-	 * $q->eq( 'id', $q->bindValue( $value ) );
936
-	 * $stmt = $q->executeQuery(); // executed with 'id = 2'
937
-	 * </code>
938
-	 *
939
-	 * @license New BSD License
940
-	 * @link http://www.zetacomponents.org
941
-	 *
942
-	 * @param mixed $value
943
-	 * @param self::PARAM_* $type
944
-	 * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
945
-	 *
946
-	 * @return IParameter
947
-	 * @since 8.2.0
948
-	 *
949
-	 * @psalm-taint-escape sql
950
-	 */
951
-	public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null);
952
-
953
-	/**
954
-	 * Creates a new positional parameter and bind the given value to it.
955
-	 *
956
-	 * Attention: If you are using positional parameters with the query builder you have
957
-	 * to be very careful to bind all parameters in the order they appear in the SQL
958
-	 * statement , otherwise they get bound in the wrong order which can lead to serious
959
-	 * bugs in your code.
960
-	 *
961
-	 * Example:
962
-	 * <code>
963
-	 *  $qb = $conn->getQueryBuilder();
964
-	 *  $qb->select('u.*')
965
-	 *     ->from('users', 'u')
966
-	 *     ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
967
-	 *     ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
968
-	 * </code>
969
-	 *
970
-	 * @param mixed $value
971
-	 * @param self::PARAM_* $type
972
-	 *
973
-	 * @return IParameter
974
-	 * @since 8.2.0
975
-	 *
976
-	 * @psalm-taint-escape sql
977
-	 */
978
-	public function createPositionalParameter($value, $type = self::PARAM_STR);
979
-
980
-	/**
981
-	 * Creates a new parameter
982
-	 *
983
-	 * Example:
984
-	 * <code>
985
-	 *  $qb = $conn->getQueryBuilder();
986
-	 *  $qb->select('u.*')
987
-	 *     ->from('users', 'u')
988
-	 *     ->where('u.username = ' . $qb->createParameter('name'))
989
-	 *     ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
990
-	 * </code>
991
-	 *
992
-	 * @param string $name
993
-	 *
994
-	 * @return IParameter
995
-	 * @since 8.2.0
996
-	 *
997
-	 * @psalm-taint-escape sql
998
-	 */
999
-	public function createParameter($name);
1000
-
1001
-	/**
1002
-	 * Creates a new function
1003
-	 *
1004
-	 * Attention: Column names inside the call have to be quoted before hand
1005
-	 *
1006
-	 * Example:
1007
-	 * <code>
1008
-	 *  $qb = $conn->getQueryBuilder();
1009
-	 *  $qb->select($qb->createFunction('COUNT(*)'))
1010
-	 *     ->from('users', 'u')
1011
-	 *  echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
1012
-	 * </code>
1013
-	 * <code>
1014
-	 *  $qb = $conn->getQueryBuilder();
1015
-	 *  $qb->select($qb->createFunction('COUNT(`column`)'))
1016
-	 *     ->from('users', 'u')
1017
-	 *  echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
1018
-	 * </code>
1019
-	 *
1020
-	 * @param string $call
1021
-	 *
1022
-	 * @return IQueryFunction
1023
-	 * @since 8.2.0
1024
-	 *
1025
-	 * @psalm-taint-sink sql $call
1026
-	 */
1027
-	public function createFunction($call);
1028
-
1029
-	/**
1030
-	 * Used to get the id of the last inserted element
1031
-	 * @return int
1032
-	 * @throws \BadMethodCallException When being called before an insert query has been run.
1033
-	 * @since 9.0.0
1034
-	 */
1035
-	public function getLastInsertId(): int;
1036
-
1037
-	/**
1038
-	 * Returns the table name quoted and with database prefix as needed by the implementation.
1039
-	 * If a query function is passed the function is casted to string,
1040
-	 * this allows passing functions as sub-queries for join expression.
1041
-	 *
1042
-	 * @param string|IQueryFunction $table
1043
-	 * @return string
1044
-	 * @since 9.0.0
1045
-	 * @since 24.0.0 accepts IQueryFunction as parameter
1046
-	 */
1047
-	public function getTableName($table);
1048
-
1049
-	/**
1050
-	 * Returns the table name with database prefix as needed by the implementation
1051
-	 *
1052
-	 * @param string $table
1053
-	 * @return string
1054
-	 * @since 30.0.0
1055
-	 */
1056
-	public function prefixTableName(string $table): string;
1057
-
1058
-	/**
1059
-	 * Returns the column name quoted and with table alias prefix as needed by the implementation
1060
-	 *
1061
-	 * @param string $column
1062
-	 * @param string $tableAlias
1063
-	 * @return string
1064
-	 * @since 9.0.0
1065
-	 */
1066
-	public function getColumnName($column, $tableAlias = '');
1067
-
1068
-	/**
1069
-	 * Provide a hint for the shard key for queries where this can't be detected otherwise
1070
-	 *
1071
-	 * @param string $column
1072
-	 * @param mixed $value
1073
-	 * @return $this
1074
-	 * @since 30.0.0
1075
-	 */
1076
-	public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self;
1077
-
1078
-	/**
1079
-	 * Set the query to run across all shards if sharding is enabled.
1080
-	 *
1081
-	 * @return $this
1082
-	 * @since 30.0.0
1083
-	 */
1084
-	public function runAcrossAllShards(): self;
1085
-
1086
-	/**
1087
-	 * Get a list of column names that are expected in the query output
1088
-	 *
1089
-	 * @return array
1090
-	 * @since 30.0.0
1091
-	 */
1092
-	public function getOutputColumns(): array;
25
+    /**
26
+     * @since 9.0.0
27
+     */
28
+    public const PARAM_NULL = ParameterType::NULL;
29
+    /**
30
+     * @since 9.0.0
31
+     */
32
+    public const PARAM_BOOL = Types::BOOLEAN;
33
+    /**
34
+     * @since 9.0.0
35
+     */
36
+    public const PARAM_INT = ParameterType::INTEGER;
37
+    /**
38
+     * @since 9.0.0
39
+     */
40
+    public const PARAM_STR = ParameterType::STRING;
41
+    /**
42
+     * @since 9.0.0
43
+     */
44
+    public const PARAM_LOB = ParameterType::LARGE_OBJECT;
45
+
46
+    /**
47
+     * @since 9.0.0
48
+     * @deprecated 31.0.0 - use PARAM_DATETIME_MUTABLE instead
49
+     */
50
+    public const PARAM_DATE = Types::DATETIME_MUTABLE;
51
+
52
+    /**
53
+     * For passing a \DateTime instance when only interested in the time part (without timezone support)
54
+     * @since 31.0.0
55
+     */
56
+    public const PARAM_TIME_MUTABLE = Types::TIME_MUTABLE;
57
+
58
+    /**
59
+     * For passing a \DateTime instance when only interested in the date part (without timezone support)
60
+     * @since 31.0.0
61
+     */
62
+    public const PARAM_DATE_MUTABLE = Types::DATE_MUTABLE;
63
+
64
+    /**
65
+     * For passing a \DateTime instance (without timezone support)
66
+     * @since 31.0.0
67
+     */
68
+    public const PARAM_DATETIME_MUTABLE = Types::DATETIME_MUTABLE;
69
+
70
+    /**
71
+     * For passing a \DateTime instance with timezone support
72
+     * @since 31.0.0
73
+     */
74
+    public const PARAM_DATETIME_TZ_MUTABLE = Types::DATETIMETZ_MUTABLE;
75
+
76
+    /**
77
+     * For passing a \DateTimeImmutable instance when only interested in the time part (without timezone support)
78
+     * @since 31.0.0
79
+     */
80
+    public const PARAM_TIME_IMMUTABLE = Types::TIME_MUTABLE;
81
+
82
+    /**
83
+     * For passing a \DateTime instance when only interested in the date part (without timezone support)
84
+     * @since 9.0.0
85
+     */
86
+    public const PARAM_DATE_IMMUTABLE = Types::DATE_IMMUTABLE;
87
+
88
+    /**
89
+     * For passing a \DateTime instance (without timezone support)
90
+     * @since 31.0.0
91
+     */
92
+    public const PARAM_DATETIME_IMMUTABLE = Types::DATETIME_IMMUTABLE;
93
+
94
+    /**
95
+     * For passing a \DateTime instance with timezone support
96
+     * @since 31.0.0
97
+     */
98
+    public const PARAM_DATETIME_TZ_IMMUTABLE = Types::DATETIMETZ_IMMUTABLE;
99
+
100
+    /**
101
+     * @since 24.0.0
102
+     */
103
+    public const PARAM_JSON = 'json';
104
+
105
+    /**
106
+     * @since 9.0.0
107
+     */
108
+    public const PARAM_INT_ARRAY = ArrayParameterType::INTEGER;
109
+    /**
110
+     * @since 9.0.0
111
+     */
112
+    public const PARAM_STR_ARRAY = ArrayParameterType::STRING;
113
+
114
+    /**
115
+     * @since 24.0.0 Indicates how many rows can be deleted at once with MySQL
116
+     * database server.
117
+     */
118
+    public const MAX_ROW_DELETION = 100000;
119
+
120
+    /**
121
+     * Enable/disable automatic prefixing of table names with the oc_ prefix
122
+     *
123
+     * @param bool $enabled If set to true table names will be prefixed with the
124
+     *                      owncloud database prefix automatically.
125
+     * @since 8.2.0
126
+     */
127
+    public function automaticTablePrefix($enabled);
128
+
129
+    /**
130
+     * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
131
+     * This producer method is intended for convenient inline usage. Example:
132
+     *
133
+     * <code>
134
+     *     $qb = $conn->getQueryBuilder()
135
+     *         ->select('u')
136
+     *         ->from('users', 'u')
137
+     *         ->where($qb->expr()->eq('u.id', 1));
138
+     * </code>
139
+     *
140
+     * For more complex expression construction, consider storing the expression
141
+     * builder object in a local variable.
142
+     *
143
+     * @return \OCP\DB\QueryBuilder\IExpressionBuilder
144
+     * @since 8.2.0
145
+     */
146
+    public function expr();
147
+
148
+    /**
149
+     * Gets an FunctionBuilder used for object-oriented construction of query functions.
150
+     * This producer method is intended for convenient inline usage. Example:
151
+     *
152
+     * <code>
153
+     *     $qb = $conn->getQueryBuilder()
154
+     *         ->select('u')
155
+     *         ->from('users', 'u')
156
+     *         ->where($qb->fun()->md5('u.id'));
157
+     * </code>
158
+     *
159
+     * For more complex function construction, consider storing the function
160
+     * builder object in a local variable.
161
+     *
162
+     * @return \OCP\DB\QueryBuilder\IFunctionBuilder
163
+     * @since 12.0.0
164
+     */
165
+    public function func();
166
+
167
+    /**
168
+     * Gets the type of the currently built query.
169
+     *
170
+     * @return integer
171
+     * @since 8.2.0
172
+     */
173
+    public function getType();
174
+
175
+    /**
176
+     * Gets the associated DBAL Connection for this query builder.
177
+     *
178
+     * @return \OCP\IDBConnection
179
+     * @since 8.2.0
180
+     */
181
+    public function getConnection();
182
+
183
+    /**
184
+     * Gets the state of this query builder instance.
185
+     *
186
+     * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
187
+     * @since 8.2.0
188
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
189
+     *    and we can not fix this in our wrapper.
190
+     */
191
+    public function getState();
192
+
193
+    /**
194
+     * Execute for select statements
195
+     *
196
+     * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0
197
+     * @return IResult
198
+     * @since 22.0.0
199
+     *
200
+     * @throws Exception
201
+     * @throws \RuntimeException in case of usage with non select query
202
+     */
203
+    public function executeQuery(?IDBConnection $connection = null): IResult;
204
+
205
+    /**
206
+     * Execute insert, update and delete statements
207
+     *
208
+     * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0
209
+     * @return int the number of affected rows
210
+     * @since 22.0.0
211
+     *
212
+     * @throws Exception
213
+     * @throws \RuntimeException in case of usage with select query
214
+     */
215
+    public function executeStatement(?IDBConnection $connection = null): int;
216
+
217
+    /**
218
+     * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
219
+     *
220
+     * <code>
221
+     *     $qb = $conn->getQueryBuilder()
222
+     *         ->select('u')
223
+     *         ->from('User', 'u')
224
+     *     echo $qb->getSQL(); // SELECT u FROM User u
225
+     * </code>
226
+     *
227
+     * @return string The SQL query string.
228
+     * @since 8.2.0
229
+     */
230
+    public function getSQL();
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|int $type One of the IQueryBuilder::PARAM_* constants.
246
+     *
247
+     * @return $this This QueryBuilder instance.
248
+     * @since 8.2.0
249
+     */
250
+    public function setParameter($key, $value, $type = null);
251
+
252
+    /**
253
+     * Sets a collection of query parameters for the query being constructed.
254
+     *
255
+     * <code>
256
+     *     $qb = $conn->getQueryBuilder()
257
+     *         ->select('u')
258
+     *         ->from('users', 'u')
259
+     *         ->where('u.id = :user_id1 OR u.id = :user_id2')
260
+     *         ->setParameters(array(
261
+     *             ':user_id1' => 1,
262
+     *             ':user_id2' => 2
263
+     *         ));
264
+     * </code>
265
+     *
266
+     * @param array $params The query parameters to set.
267
+     * @param array $types The query parameters types to set.
268
+     *
269
+     * @return $this This QueryBuilder instance.
270
+     * @since 8.2.0
271
+     */
272
+    public function setParameters(array $params, array $types = []);
273
+
274
+    /**
275
+     * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
276
+     *
277
+     * @return array The currently defined query parameters indexed by parameter index or name.
278
+     * @since 8.2.0
279
+     */
280
+    public function getParameters();
281
+
282
+    /**
283
+     * Gets a (previously set) query parameter of the query being constructed.
284
+     *
285
+     * @param mixed $key The key (index or name) of the bound parameter.
286
+     *
287
+     * @return mixed The value of the bound parameter.
288
+     * @since 8.2.0
289
+     */
290
+    public function getParameter($key);
291
+
292
+    /**
293
+     * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
294
+     *
295
+     * @return array The currently defined query parameter types indexed by parameter index or name.
296
+     * @since 8.2.0
297
+     */
298
+    public function getParameterTypes();
299
+
300
+    /**
301
+     * Gets a (previously set) query parameter type of the query being constructed.
302
+     *
303
+     * @param mixed $key The key (index or name) of the bound parameter type.
304
+     *
305
+     * @return mixed The value of the bound parameter type.
306
+     * @since 8.2.0
307
+     */
308
+    public function getParameterType($key);
309
+
310
+    /**
311
+     * Sets the position of the first result to retrieve (the "offset").
312
+     *
313
+     * @param int $firstResult The first result to return.
314
+     *
315
+     * @return $this This QueryBuilder instance.
316
+     * @since 8.2.0
317
+     */
318
+    public function setFirstResult($firstResult);
319
+
320
+    /**
321
+     * Gets the position of the first result the query object was set to retrieve (the "offset").
322
+     * Returns 0 if {@link setFirstResult} was not applied to this QueryBuilder.
323
+     *
324
+     * @return int The position of the first result.
325
+     * @since 8.2.0
326
+     */
327
+    public function getFirstResult();
328
+
329
+    /**
330
+     * Sets the maximum number of results to retrieve (the "limit").
331
+     *
332
+     * @param int|null $maxResults The maximum number of results to retrieve.
333
+     *
334
+     * @return $this This QueryBuilder instance.
335
+     * @since 8.2.0
336
+     */
337
+    public function setMaxResults($maxResults);
338
+
339
+    /**
340
+     * Gets the maximum number of results the query object was set to retrieve (the "limit").
341
+     * Returns NULL if {@link setMaxResults} was not applied to this query builder.
342
+     *
343
+     * @return int|null The maximum number of results.
344
+     * @since 8.2.0
345
+     */
346
+    public function getMaxResults();
347
+
348
+    /**
349
+     * Specifies an item that is to be returned in the query result.
350
+     * Replaces any previously specified selections, if any.
351
+     *
352
+     * <code>
353
+     *     $qb = $conn->getQueryBuilder()
354
+     *         ->select('u.id', 'p.id')
355
+     *         ->from('users', 'u')
356
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
357
+     * </code>
358
+     *
359
+     * @param mixed ...$selects The selection expressions.
360
+     *
361
+     * @return $this This QueryBuilder instance.
362
+     * @since 8.2.0
363
+     *
364
+     * @psalm-taint-sink sql $selects
365
+     */
366
+    public function select(...$selects);
367
+
368
+    /**
369
+     * Specifies an item that is to be returned with a different name in the query result.
370
+     *
371
+     * <code>
372
+     *     $qb = $conn->getQueryBuilder()
373
+     *         ->selectAlias('u.id', 'user_id')
374
+     *         ->from('users', 'u')
375
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
376
+     * </code>
377
+     *
378
+     * @param mixed $select The selection expressions.
379
+     * @param string $alias The column alias used in the constructed query.
380
+     *
381
+     * @return $this This QueryBuilder instance.
382
+     * @since 8.2.1
383
+     *
384
+     * @psalm-taint-sink sql $select
385
+     * @psalm-taint-sink sql $alias
386
+     */
387
+    public function selectAlias($select, $alias);
388
+
389
+    /**
390
+     * Specifies an item that is to be returned uniquely in the query result.
391
+     *
392
+     * <code>
393
+     *     $qb = $conn->getQueryBuilder()
394
+     *         ->selectDistinct('type')
395
+     *         ->from('users');
396
+     * </code>
397
+     *
398
+     * @param mixed $select The selection expressions.
399
+     *
400
+     * @return $this This QueryBuilder instance.
401
+     * @since 9.0.0
402
+     *
403
+     * @psalm-taint-sink sql $select
404
+     */
405
+    public function selectDistinct($select);
406
+
407
+    /**
408
+     * Adds an item that is to be returned in the query result.
409
+     *
410
+     * <code>
411
+     *     $qb = $conn->getQueryBuilder()
412
+     *         ->select('u.id')
413
+     *         ->addSelect('p.id')
414
+     *         ->from('users', 'u')
415
+     *         ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
416
+     * </code>
417
+     *
418
+     * @param mixed ...$select The selection expression.
419
+     *
420
+     * @return $this This QueryBuilder instance.
421
+     * @since 8.2.0
422
+     *
423
+     * @psalm-taint-sink sql $select
424
+     */
425
+    public function addSelect(...$select);
426
+
427
+    /**
428
+     * Turns the query being built into a bulk delete query that ranges over
429
+     * a certain table.
430
+     *
431
+     * <code>
432
+     *     $qb = $conn->getQueryBuilder()
433
+     *         ->delete('users')
434
+     *         ->where('id = :user_id');
435
+     *         ->setParameter(':user_id', 1);
436
+     * </code>
437
+     *
438
+     * @param string $delete The table whose rows are subject to the deletion.
439
+     * @param string $alias The table alias used in the constructed query.
440
+     *
441
+     * @return $this This QueryBuilder instance.
442
+     * @since 8.2.0
443
+     * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
444
+     *
445
+     * @psalm-taint-sink sql $delete
446
+     */
447
+    public function delete($delete = null, $alias = null);
448
+
449
+    /**
450
+     * Turns the query being built into a bulk update query that ranges over
451
+     * a certain table
452
+     *
453
+     * <code>
454
+     *     $qb = $conn->getQueryBuilder()
455
+     *         ->update('users')
456
+     *         ->set('email', ':email')
457
+     *         ->where('id = :user_id');
458
+     *         ->setParameter(':user_id', 1);
459
+     * </code>
460
+     *
461
+     * @param string $update The table whose rows are subject to the update.
462
+     * @param string $alias The table alias used in the constructed query.
463
+     *
464
+     * @return $this This QueryBuilder instance.
465
+     * @since 8.2.0
466
+     * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
467
+     *
468
+     * @psalm-taint-sink sql $update
469
+     */
470
+    public function update($update = null, $alias = null);
471
+
472
+    /**
473
+     * Turns the query being built into an insert query that inserts into
474
+     * a certain table
475
+     *
476
+     * <code>
477
+     *     $qb = $conn->getQueryBuilder()
478
+     *         ->insert('users')
479
+     *         ->values(
480
+     *             array(
481
+     *                 'name' => '?',
482
+     *                 'password' => '?'
483
+     *             )
484
+     *         );
485
+     * </code>
486
+     *
487
+     * @param string $insert The table into which the rows should be inserted.
488
+     *
489
+     * @return $this This QueryBuilder instance.
490
+     * @since 8.2.0
491
+     *
492
+     * @psalm-taint-sink sql $insert
493
+     */
494
+    public function insert($insert = null);
495
+
496
+    /**
497
+     * Creates and adds a query root corresponding to the table identified by the
498
+     * given alias, forming a cartesian product with any existing query roots.
499
+     *
500
+     * <code>
501
+     *     $qb = $conn->getQueryBuilder()
502
+     *         ->select('u.id')
503
+     *         ->from('users', 'u')
504
+     * </code>
505
+     *
506
+     * @param string|IQueryFunction $from The table.
507
+     * @param string|null $alias The alias of the table.
508
+     *
509
+     * @return $this This QueryBuilder instance.
510
+     * @since 8.2.0
511
+     *
512
+     * @psalm-taint-sink sql $from
513
+     */
514
+    public function from($from, $alias = null);
515
+
516
+    /**
517
+     * Creates and adds a join to the query.
518
+     *
519
+     * <code>
520
+     *     $qb = $conn->getQueryBuilder()
521
+     *         ->select('u.name')
522
+     *         ->from('users', 'u')
523
+     *         ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
524
+     * </code>
525
+     *
526
+     * @param string $fromAlias The alias that points to a from clause.
527
+     * @param string $join The table name to join.
528
+     * @param string $alias The alias of the join table.
529
+     * @param string|ICompositeExpression|null $condition The condition for the join.
530
+     *
531
+     * @return $this This QueryBuilder instance.
532
+     * @since 8.2.0
533
+     *
534
+     * @psalm-taint-sink sql $fromAlias
535
+     * @psalm-taint-sink sql $join
536
+     * @psalm-taint-sink sql $alias
537
+     * @psalm-taint-sink sql $condition
538
+     */
539
+    public function join($fromAlias, $join, $alias, $condition = null);
540
+
541
+    /**
542
+     * Creates and adds a join to the query.
543
+     *
544
+     * <code>
545
+     *     $qb = $conn->getQueryBuilder()
546
+     *         ->select('u.name')
547
+     *         ->from('users', 'u')
548
+     *         ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
549
+     * </code>
550
+     *
551
+     * @param string $fromAlias The alias that points to a from clause.
552
+     * @param string $join The table name to join.
553
+     * @param string $alias The alias of the join table.
554
+     * @param string|ICompositeExpression|null $condition The condition for the join.
555
+     *
556
+     * @return $this This QueryBuilder instance.
557
+     * @since 8.2.0
558
+     *
559
+     * @psalm-taint-sink sql $fromAlias
560
+     * @psalm-taint-sink sql $join
561
+     * @psalm-taint-sink sql $alias
562
+     * @psalm-taint-sink sql $condition
563
+     */
564
+    public function innerJoin($fromAlias, $join, $alias, $condition = null);
565
+
566
+    /**
567
+     * Creates and adds a left join to the query.
568
+     *
569
+     * <code>
570
+     *     $qb = $conn->getQueryBuilder()
571
+     *         ->select('u.name')
572
+     *         ->from('users', 'u')
573
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
574
+     * </code>
575
+     *
576
+     * @param string $fromAlias The alias that points to a from clause.
577
+     * @param string|IQueryFunction $join The table name to join.
578
+     * @param string $alias The alias of the join table.
579
+     * @param string|ICompositeExpression|null $condition The condition for the join.
580
+     *
581
+     * @return $this This QueryBuilder instance.
582
+     * @since 8.2.0
583
+     * @since 30.0.0 Allow passing IQueryFunction as parameter for `$join` to allow join with a sub-query.
584
+     *
585
+     * @psalm-taint-sink sql $fromAlias
586
+     * @psalm-taint-sink sql $join
587
+     * @psalm-taint-sink sql $alias
588
+     * @psalm-taint-sink sql $condition
589
+     */
590
+    public function leftJoin($fromAlias, $join, $alias, $condition = null);
591
+
592
+    /**
593
+     * Creates and adds a right join to the query.
594
+     *
595
+     * <code>
596
+     *     $qb = $conn->getQueryBuilder()
597
+     *         ->select('u.name')
598
+     *         ->from('users', 'u')
599
+     *         ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
600
+     * </code>
601
+     *
602
+     * @param string $fromAlias The alias that points to a from clause.
603
+     * @param string $join The table name to join.
604
+     * @param string $alias The alias of the join table.
605
+     * @param string|ICompositeExpression|null $condition The condition for the join.
606
+     *
607
+     * @return $this This QueryBuilder instance.
608
+     * @since 8.2.0
609
+     *
610
+     * @psalm-taint-sink sql $fromAlias
611
+     * @psalm-taint-sink sql $join
612
+     * @psalm-taint-sink sql $alias
613
+     * @psalm-taint-sink sql $condition
614
+     */
615
+    public function rightJoin($fromAlias, $join, $alias, $condition = null);
616
+
617
+    /**
618
+     * Sets a new value for a column in a bulk update query.
619
+     *
620
+     * <code>
621
+     *     $qb = $conn->getQueryBuilder()
622
+     *         ->update('users', 'u')
623
+     *         ->set('u.password', md5('password'))
624
+     *         ->where('u.id = ?');
625
+     * </code>
626
+     *
627
+     * @param string $key The column to set.
628
+     * @param ILiteral|IParameter|IQueryFunction|string $value The value, expression, placeholder, etc.
629
+     *
630
+     * @return $this This QueryBuilder instance.
631
+     * @since 8.2.0
632
+     *
633
+     * @psalm-taint-sink sql $key
634
+     * @psalm-taint-sink sql $value
635
+     */
636
+    public function set($key, $value);
637
+
638
+    /**
639
+     * Specifies one or more restrictions to the query result.
640
+     * Replaces any previously specified restrictions, if any.
641
+     *
642
+     * <code>
643
+     *     $qb = $conn->getQueryBuilder()
644
+     *         ->select('u.name')
645
+     *         ->from('users', 'u')
646
+     *         ->where('u.id = ?');
647
+     *
648
+     *     // You can optionally programmatically build and/or expressions
649
+     *     $qb = $conn->getQueryBuilder();
650
+     *
651
+     *     $or = $qb->expr()->orx(
652
+     *         $qb->expr()->eq('u.id', 1),
653
+     *         $qb->expr()->eq('u.id', 2),
654
+     *     );
655
+     *
656
+     *     $qb->update('users', 'u')
657
+     *         ->set('u.password', md5('password'))
658
+     *         ->where($or);
659
+     * </code>
660
+     *
661
+     * @param mixed $predicates The restriction predicates.
662
+     *
663
+     * @return $this This QueryBuilder instance.
664
+     * @since 8.2.0
665
+     *
666
+     * @psalm-taint-sink sql $predicates
667
+     */
668
+    public function where(...$predicates);
669
+
670
+    /**
671
+     * Adds one or more restrictions to the query results, forming a logical
672
+     * conjunction with any previously specified restrictions.
673
+     *
674
+     * <code>
675
+     *     $qb = $conn->getQueryBuilder()
676
+     *         ->select('u')
677
+     *         ->from('users', 'u')
678
+     *         ->where('u.username LIKE ?')
679
+     *         ->andWhere('u.is_active = 1');
680
+     * </code>
681
+     *
682
+     * @param mixed ...$where The query restrictions.
683
+     *
684
+     * @return $this This QueryBuilder instance.
685
+     *
686
+     * @see where()
687
+     * @since 8.2.0
688
+     *
689
+     * @psalm-taint-sink sql $where
690
+     */
691
+    public function andWhere(...$where);
692
+
693
+    /**
694
+     * Adds one or more restrictions to the query results, forming a logical
695
+     * disjunction with any previously specified restrictions.
696
+     *
697
+     * <code>
698
+     *     $qb = $conn->getQueryBuilder()
699
+     *         ->select('u.name')
700
+     *         ->from('users', 'u')
701
+     *         ->where('u.id = 1')
702
+     *         ->orWhere('u.id = 2');
703
+     * </code>
704
+     *
705
+     * @param mixed ...$where The WHERE statement.
706
+     *
707
+     * @return $this This QueryBuilder instance.
708
+     *
709
+     * @see where()
710
+     * @since 8.2.0
711
+     *
712
+     * @psalm-taint-sink sql $where
713
+     */
714
+    public function orWhere(...$where);
715
+
716
+    /**
717
+     * Specifies a grouping over the results of the query.
718
+     * Replaces any previously specified groupings, if any.
719
+     *
720
+     * <code>
721
+     *     $qb = $conn->getQueryBuilder()
722
+     *         ->select('u.name')
723
+     *         ->from('users', 'u')
724
+     *         ->groupBy('u.id');
725
+     * </code>
726
+     *
727
+     * @param mixed ...$groupBys The grouping expression.
728
+     *
729
+     * @return $this This QueryBuilder instance.
730
+     * @since 8.2.0
731
+     *
732
+     * @psalm-taint-sink sql $groupBys
733
+     */
734
+    public function groupBy(...$groupBys);
735
+
736
+    /**
737
+     * Adds a grouping expression to the query.
738
+     *
739
+     * <code>
740
+     *     $qb = $conn->getQueryBuilder()
741
+     *         ->select('u.name')
742
+     *         ->from('users', 'u')
743
+     *         ->groupBy('u.lastLogin');
744
+     *         ->addGroupBy('u.createdAt')
745
+     * </code>
746
+     *
747
+     * @param mixed ...$groupBy The grouping expression.
748
+     *
749
+     * @return $this This QueryBuilder instance.
750
+     * @since 8.2.0
751
+     *
752
+     * @psalm-taint-sink sql $groupby
753
+     */
754
+    public function addGroupBy(...$groupBy);
755
+
756
+    /**
757
+     * Sets a value for a column in an insert query.
758
+     *
759
+     * <code>
760
+     *     $qb = $conn->getQueryBuilder()
761
+     *         ->insert('users')
762
+     *         ->values(
763
+     *             array(
764
+     *                 'name' => '?'
765
+     *             )
766
+     *         )
767
+     *         ->setValue('password', '?');
768
+     * </code>
769
+     *
770
+     * @param string $column The column into which the value should be inserted.
771
+     * @param IParameter|string $value The value that should be inserted into the column.
772
+     *
773
+     * @return $this This QueryBuilder instance.
774
+     * @since 8.2.0
775
+     *
776
+     * @psalm-taint-sink sql $column
777
+     * @psalm-taint-sink sql $value
778
+     */
779
+    public function setValue($column, $value);
780
+
781
+    /**
782
+     * Specifies values for an insert query indexed by column names.
783
+     * Replaces any previous values, if any.
784
+     *
785
+     * <code>
786
+     *     $qb = $conn->getQueryBuilder()
787
+     *         ->insert('users')
788
+     *         ->values(
789
+     *             array(
790
+     *                 'name' => '?',
791
+     *                 'password' => '?'
792
+     *             )
793
+     *         );
794
+     * </code>
795
+     *
796
+     * @param array $values The values to specify for the insert query indexed by column names.
797
+     *
798
+     * @return $this This QueryBuilder instance.
799
+     * @since 8.2.0
800
+     *
801
+     * @psalm-taint-sink sql $values
802
+     */
803
+    public function values(array $values);
804
+
805
+    /**
806
+     * Specifies a restriction over the groups of the query.
807
+     * Replaces any previous having restrictions, if any.
808
+     *
809
+     * @param mixed ...$having The restriction over the groups.
810
+     *
811
+     * @return $this This QueryBuilder instance.
812
+     * @since 8.2.0
813
+     *
814
+     * @psalm-taint-sink sql $having
815
+     */
816
+    public function having(...$having);
817
+
818
+    /**
819
+     * Adds a restriction over the groups of the query, forming a logical
820
+     * conjunction with any existing having restrictions.
821
+     *
822
+     * @param mixed ...$having The restriction to append.
823
+     *
824
+     * @return $this This QueryBuilder instance.
825
+     * @since 8.2.0
826
+     *
827
+     * @psalm-taint-sink sql $andHaving
828
+     */
829
+    public function andHaving(...$having);
830
+
831
+    /**
832
+     * Adds a restriction over the groups of the query, forming a logical
833
+     * disjunction with any existing having restrictions.
834
+     *
835
+     * @param mixed ...$having The restriction to add.
836
+     *
837
+     * @return $this This QueryBuilder instance.
838
+     * @since 8.2.0
839
+     *
840
+     * @psalm-taint-sink sql $having
841
+     */
842
+    public function orHaving(...$having);
843
+
844
+    /**
845
+     * Specifies an ordering for the query results.
846
+     * Replaces any previously specified orderings, if any.
847
+     *
848
+     * @param string|IQueryFunction|ILiteral|IParameter $sort The ordering expression.
849
+     * @param string $order The ordering direction.
850
+     *
851
+     * @return $this This QueryBuilder instance.
852
+     * @since 8.2.0
853
+     *
854
+     * @psalm-taint-sink sql $sort
855
+     * @psalm-taint-sink sql $order
856
+     */
857
+    public function orderBy($sort, $order = null);
858
+
859
+    /**
860
+     * Adds an ordering to the query results.
861
+     *
862
+     * @param string|ILiteral|IParameter|IQueryFunction $sort The ordering expression.
863
+     * @param string $order The ordering direction.
864
+     *
865
+     * @return $this This QueryBuilder instance.
866
+     * @since 8.2.0
867
+     *
868
+     * @psalm-taint-sink sql $sort
869
+     * @psalm-taint-sink sql $order
870
+     */
871
+    public function addOrderBy($sort, $order = null);
872
+
873
+    /**
874
+     * Gets a query part by its name.
875
+     *
876
+     * @param string $queryPartName
877
+     *
878
+     * @return mixed
879
+     * @since 8.2.0
880
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
881
+     *  and we can not fix this in our wrapper. Please track the details you need, outside the object.
882
+     */
883
+    public function getQueryPart($queryPartName);
884
+
885
+    /**
886
+     * Gets all query parts.
887
+     *
888
+     * @return array
889
+     * @since 8.2.0
890
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
891
+     *  and we can not fix this in our wrapper. Please track the details you need, outside the object.
892
+     */
893
+    public function getQueryParts();
894
+
895
+    /**
896
+     * Resets SQL parts.
897
+     *
898
+     * @param array|null $queryPartNames
899
+     *
900
+     * @return $this This QueryBuilder instance.
901
+     * @since 8.2.0
902
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
903
+     * and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
904
+     */
905
+    public function resetQueryParts($queryPartNames = null);
906
+
907
+    /**
908
+     * Resets a single SQL part.
909
+     *
910
+     * @param string $queryPartName
911
+     *
912
+     * @return $this This QueryBuilder instance.
913
+     * @since 8.2.0
914
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
915
+     *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
916
+     */
917
+    public function resetQueryPart($queryPartName);
918
+
919
+    /**
920
+     * Creates a new named parameter and bind the value $value to it.
921
+     *
922
+     * This method provides a shortcut for PDOStatement::bindValue
923
+     * when using prepared statements.
924
+     *
925
+     * The parameter $value specifies the value that you want to bind. If
926
+     * $placeholder is not provided bindValue() will automatically create a
927
+     * placeholder for you. An automatic placeholder will be of the name
928
+     * ':dcValue1', ':dcValue2' etc.
929
+     *
930
+     * For more information see {@link https://www.php.net/pdostatement-bindparam}
931
+     *
932
+     * Example:
933
+     * <code>
934
+     * $value = 2;
935
+     * $q->eq( 'id', $q->bindValue( $value ) );
936
+     * $stmt = $q->executeQuery(); // executed with 'id = 2'
937
+     * </code>
938
+     *
939
+     * @license New BSD License
940
+     * @link http://www.zetacomponents.org
941
+     *
942
+     * @param mixed $value
943
+     * @param self::PARAM_* $type
944
+     * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
945
+     *
946
+     * @return IParameter
947
+     * @since 8.2.0
948
+     *
949
+     * @psalm-taint-escape sql
950
+     */
951
+    public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null);
952
+
953
+    /**
954
+     * Creates a new positional parameter and bind the given value to it.
955
+     *
956
+     * Attention: If you are using positional parameters with the query builder you have
957
+     * to be very careful to bind all parameters in the order they appear in the SQL
958
+     * statement , otherwise they get bound in the wrong order which can lead to serious
959
+     * bugs in your code.
960
+     *
961
+     * Example:
962
+     * <code>
963
+     *  $qb = $conn->getQueryBuilder();
964
+     *  $qb->select('u.*')
965
+     *     ->from('users', 'u')
966
+     *     ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
967
+     *     ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
968
+     * </code>
969
+     *
970
+     * @param mixed $value
971
+     * @param self::PARAM_* $type
972
+     *
973
+     * @return IParameter
974
+     * @since 8.2.0
975
+     *
976
+     * @psalm-taint-escape sql
977
+     */
978
+    public function createPositionalParameter($value, $type = self::PARAM_STR);
979
+
980
+    /**
981
+     * Creates a new parameter
982
+     *
983
+     * Example:
984
+     * <code>
985
+     *  $qb = $conn->getQueryBuilder();
986
+     *  $qb->select('u.*')
987
+     *     ->from('users', 'u')
988
+     *     ->where('u.username = ' . $qb->createParameter('name'))
989
+     *     ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
990
+     * </code>
991
+     *
992
+     * @param string $name
993
+     *
994
+     * @return IParameter
995
+     * @since 8.2.0
996
+     *
997
+     * @psalm-taint-escape sql
998
+     */
999
+    public function createParameter($name);
1000
+
1001
+    /**
1002
+     * Creates a new function
1003
+     *
1004
+     * Attention: Column names inside the call have to be quoted before hand
1005
+     *
1006
+     * Example:
1007
+     * <code>
1008
+     *  $qb = $conn->getQueryBuilder();
1009
+     *  $qb->select($qb->createFunction('COUNT(*)'))
1010
+     *     ->from('users', 'u')
1011
+     *  echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
1012
+     * </code>
1013
+     * <code>
1014
+     *  $qb = $conn->getQueryBuilder();
1015
+     *  $qb->select($qb->createFunction('COUNT(`column`)'))
1016
+     *     ->from('users', 'u')
1017
+     *  echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
1018
+     * </code>
1019
+     *
1020
+     * @param string $call
1021
+     *
1022
+     * @return IQueryFunction
1023
+     * @since 8.2.0
1024
+     *
1025
+     * @psalm-taint-sink sql $call
1026
+     */
1027
+    public function createFunction($call);
1028
+
1029
+    /**
1030
+     * Used to get the id of the last inserted element
1031
+     * @return int
1032
+     * @throws \BadMethodCallException When being called before an insert query has been run.
1033
+     * @since 9.0.0
1034
+     */
1035
+    public function getLastInsertId(): int;
1036
+
1037
+    /**
1038
+     * Returns the table name quoted and with database prefix as needed by the implementation.
1039
+     * If a query function is passed the function is casted to string,
1040
+     * this allows passing functions as sub-queries for join expression.
1041
+     *
1042
+     * @param string|IQueryFunction $table
1043
+     * @return string
1044
+     * @since 9.0.0
1045
+     * @since 24.0.0 accepts IQueryFunction as parameter
1046
+     */
1047
+    public function getTableName($table);
1048
+
1049
+    /**
1050
+     * Returns the table name with database prefix as needed by the implementation
1051
+     *
1052
+     * @param string $table
1053
+     * @return string
1054
+     * @since 30.0.0
1055
+     */
1056
+    public function prefixTableName(string $table): string;
1057
+
1058
+    /**
1059
+     * Returns the column name quoted and with table alias prefix as needed by the implementation
1060
+     *
1061
+     * @param string $column
1062
+     * @param string $tableAlias
1063
+     * @return string
1064
+     * @since 9.0.0
1065
+     */
1066
+    public function getColumnName($column, $tableAlias = '');
1067
+
1068
+    /**
1069
+     * Provide a hint for the shard key for queries where this can't be detected otherwise
1070
+     *
1071
+     * @param string $column
1072
+     * @param mixed $value
1073
+     * @return $this
1074
+     * @since 30.0.0
1075
+     */
1076
+    public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self;
1077
+
1078
+    /**
1079
+     * Set the query to run across all shards if sharding is enabled.
1080
+     *
1081
+     * @return $this
1082
+     * @since 30.0.0
1083
+     */
1084
+    public function runAcrossAllShards(): self;
1085
+
1086
+    /**
1087
+     * Get a list of column names that are expected in the query output
1088
+     *
1089
+     * @return array
1090
+     * @since 30.0.0
1091
+     */
1092
+    public function getOutputColumns(): array;
1093 1093
 }
Please login to merge, or discard this patch.
lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php 1 patch
Indentation   +274 added lines, -274 removed lines patch added patch discarded remove patch
@@ -16,278 +16,278 @@
 block discarded – undo
16 16
  * Base class for creating classes that extend the builtin query builder
17 17
  */
18 18
 abstract class ExtendedQueryBuilder implements IQueryBuilder {
19
-	public function __construct(
20
-		protected IQueryBuilder $builder,
21
-	) {
22
-	}
23
-
24
-	public function automaticTablePrefix($enabled) {
25
-		$this->builder->automaticTablePrefix($enabled);
26
-		return $this;
27
-	}
28
-
29
-	public function expr() {
30
-		return $this->builder->expr();
31
-	}
32
-
33
-	public function func() {
34
-		return $this->builder->func();
35
-	}
36
-
37
-	public function getType() {
38
-		return $this->builder->getType();
39
-	}
40
-
41
-	public function getConnection() {
42
-		return $this->builder->getConnection();
43
-	}
44
-
45
-	public function getState() {
46
-		return $this->builder->getState();
47
-	}
48
-
49
-	public function getSQL() {
50
-		return $this->builder->getSQL();
51
-	}
52
-
53
-	public function setParameter($key, $value, $type = null) {
54
-		$this->builder->setParameter($key, $value, $type);
55
-		return $this;
56
-	}
57
-
58
-	public function setParameters(array $params, array $types = []) {
59
-		$this->builder->setParameters($params, $types);
60
-		return $this;
61
-	}
62
-
63
-	public function getParameters() {
64
-		return $this->builder->getParameters();
65
-	}
66
-
67
-	public function getParameter($key) {
68
-		return $this->builder->getParameter($key);
69
-	}
70
-
71
-	public function getParameterTypes() {
72
-		return $this->builder->getParameterTypes();
73
-	}
74
-
75
-	public function getParameterType($key) {
76
-		return $this->builder->getParameterType($key);
77
-	}
78
-
79
-	public function setFirstResult($firstResult) {
80
-		$this->builder->setFirstResult($firstResult);
81
-		return $this;
82
-	}
83
-
84
-	public function getFirstResult() {
85
-		return $this->builder->getFirstResult();
86
-	}
87
-
88
-	public function setMaxResults($maxResults) {
89
-		$this->builder->setMaxResults($maxResults);
90
-		return $this;
91
-	}
92
-
93
-	public function getMaxResults() {
94
-		return $this->builder->getMaxResults();
95
-	}
96
-
97
-	public function select(...$selects) {
98
-		$this->builder->select(...$selects);
99
-		return $this;
100
-	}
101
-
102
-	public function selectAlias($select, $alias) {
103
-		$this->builder->selectAlias($select, $alias);
104
-		return $this;
105
-	}
106
-
107
-	public function selectDistinct($select) {
108
-		$this->builder->selectDistinct($select);
109
-		return $this;
110
-	}
111
-
112
-	public function addSelect(...$select) {
113
-		$this->builder->addSelect(...$select);
114
-		return $this;
115
-	}
116
-
117
-	public function delete($delete = null, $alias = null) {
118
-		$this->builder->delete($delete, $alias);
119
-		return $this;
120
-	}
121
-
122
-	public function update($update = null, $alias = null) {
123
-		$this->builder->update($update, $alias);
124
-		return $this;
125
-	}
126
-
127
-	public function insert($insert = null) {
128
-		$this->builder->insert($insert);
129
-		return $this;
130
-	}
131
-
132
-	public function from($from, $alias = null) {
133
-		$this->builder->from($from, $alias);
134
-		return $this;
135
-	}
136
-
137
-	public function join($fromAlias, $join, $alias, $condition = null) {
138
-		$this->builder->join($fromAlias, $join, $alias, $condition);
139
-		return $this;
140
-	}
141
-
142
-	public function innerJoin($fromAlias, $join, $alias, $condition = null) {
143
-		$this->builder->innerJoin($fromAlias, $join, $alias, $condition);
144
-		return $this;
145
-	}
146
-
147
-	public function leftJoin($fromAlias, $join, $alias, $condition = null) {
148
-		$this->builder->leftJoin($fromAlias, $join, $alias, $condition);
149
-		return $this;
150
-	}
151
-
152
-	public function rightJoin($fromAlias, $join, $alias, $condition = null) {
153
-		$this->builder->rightJoin($fromAlias, $join, $alias, $condition);
154
-		return $this;
155
-	}
156
-
157
-	public function set($key, $value) {
158
-		$this->builder->set($key, $value);
159
-		return $this;
160
-	}
161
-
162
-	public function where(...$predicates) {
163
-		$this->builder->where(...$predicates);
164
-		return $this;
165
-	}
166
-
167
-	public function andWhere(...$where) {
168
-		$this->builder->andWhere(...$where);
169
-		return $this;
170
-	}
171
-
172
-	public function orWhere(...$where) {
173
-		$this->builder->orWhere(...$where);
174
-		return $this;
175
-	}
176
-
177
-	public function groupBy(...$groupBys) {
178
-		$this->builder->groupBy(...$groupBys);
179
-		return $this;
180
-	}
181
-
182
-	public function addGroupBy(...$groupBy) {
183
-		$this->builder->addGroupBy(...$groupBy);
184
-		return $this;
185
-	}
186
-
187
-	public function setValue($column, $value) {
188
-		$this->builder->setValue($column, $value);
189
-		return $this;
190
-	}
191
-
192
-	public function values(array $values) {
193
-		$this->builder->values($values);
194
-		return $this;
195
-	}
196
-
197
-	public function having(...$having) {
198
-		$this->builder->having(...$having);
199
-		return $this;
200
-	}
201
-
202
-	public function andHaving(...$having) {
203
-		$this->builder->andHaving(...$having);
204
-		return $this;
205
-	}
206
-
207
-	public function orHaving(...$having) {
208
-		$this->builder->orHaving(...$having);
209
-		return $this;
210
-	}
211
-
212
-	public function orderBy($sort, $order = null) {
213
-		$this->builder->orderBy($sort, $order);
214
-		return $this;
215
-	}
216
-
217
-	public function addOrderBy($sort, $order = null) {
218
-		$this->builder->addOrderBy($sort, $order);
219
-		return $this;
220
-	}
221
-
222
-	public function getQueryPart($queryPartName) {
223
-		return $this->builder->getQueryPart($queryPartName);
224
-	}
225
-
226
-	public function getQueryParts() {
227
-		return $this->builder->getQueryParts();
228
-	}
229
-
230
-	public function resetQueryParts($queryPartNames = null) {
231
-		$this->builder->resetQueryParts($queryPartNames);
232
-		return $this;
233
-	}
234
-
235
-	public function resetQueryPart($queryPartName) {
236
-		$this->builder->resetQueryPart($queryPartName);
237
-		return $this;
238
-	}
239
-
240
-	public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null) {
241
-		return $this->builder->createNamedParameter($value, $type, $placeHolder);
242
-	}
243
-
244
-	public function createPositionalParameter($value, $type = self::PARAM_STR) {
245
-		return $this->builder->createPositionalParameter($value, $type);
246
-	}
247
-
248
-	public function createParameter($name) {
249
-		return $this->builder->createParameter($name);
250
-	}
251
-
252
-	public function createFunction($call) {
253
-		return $this->builder->createFunction($call);
254
-	}
255
-
256
-	public function getLastInsertId(): int {
257
-		return $this->builder->getLastInsertId();
258
-	}
259
-
260
-	public function getTableName($table) {
261
-		return $this->builder->getTableName($table);
262
-	}
263
-
264
-	public function getColumnName($column, $tableAlias = '') {
265
-		return $this->builder->getColumnName($column, $tableAlias);
266
-	}
267
-
268
-	public function executeQuery(?IDBConnection $connection = null): IResult {
269
-		return $this->builder->executeQuery($connection);
270
-	}
271
-
272
-	public function executeStatement(?IDBConnection $connection = null): int {
273
-		return $this->builder->executeStatement($connection);
274
-	}
275
-
276
-	public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self {
277
-		$this->builder->hintShardKey($column, $value, $overwrite);
278
-		return $this;
279
-	}
280
-
281
-	public function runAcrossAllShards(): self {
282
-		$this->builder->runAcrossAllShards();
283
-		return $this;
284
-	}
285
-
286
-	public function getOutputColumns(): array {
287
-		return $this->builder->getOutputColumns();
288
-	}
289
-
290
-	public function prefixTableName(string $table): string {
291
-		return $this->builder->prefixTableName($table);
292
-	}
19
+    public function __construct(
20
+        protected IQueryBuilder $builder,
21
+    ) {
22
+    }
23
+
24
+    public function automaticTablePrefix($enabled) {
25
+        $this->builder->automaticTablePrefix($enabled);
26
+        return $this;
27
+    }
28
+
29
+    public function expr() {
30
+        return $this->builder->expr();
31
+    }
32
+
33
+    public function func() {
34
+        return $this->builder->func();
35
+    }
36
+
37
+    public function getType() {
38
+        return $this->builder->getType();
39
+    }
40
+
41
+    public function getConnection() {
42
+        return $this->builder->getConnection();
43
+    }
44
+
45
+    public function getState() {
46
+        return $this->builder->getState();
47
+    }
48
+
49
+    public function getSQL() {
50
+        return $this->builder->getSQL();
51
+    }
52
+
53
+    public function setParameter($key, $value, $type = null) {
54
+        $this->builder->setParameter($key, $value, $type);
55
+        return $this;
56
+    }
57
+
58
+    public function setParameters(array $params, array $types = []) {
59
+        $this->builder->setParameters($params, $types);
60
+        return $this;
61
+    }
62
+
63
+    public function getParameters() {
64
+        return $this->builder->getParameters();
65
+    }
66
+
67
+    public function getParameter($key) {
68
+        return $this->builder->getParameter($key);
69
+    }
70
+
71
+    public function getParameterTypes() {
72
+        return $this->builder->getParameterTypes();
73
+    }
74
+
75
+    public function getParameterType($key) {
76
+        return $this->builder->getParameterType($key);
77
+    }
78
+
79
+    public function setFirstResult($firstResult) {
80
+        $this->builder->setFirstResult($firstResult);
81
+        return $this;
82
+    }
83
+
84
+    public function getFirstResult() {
85
+        return $this->builder->getFirstResult();
86
+    }
87
+
88
+    public function setMaxResults($maxResults) {
89
+        $this->builder->setMaxResults($maxResults);
90
+        return $this;
91
+    }
92
+
93
+    public function getMaxResults() {
94
+        return $this->builder->getMaxResults();
95
+    }
96
+
97
+    public function select(...$selects) {
98
+        $this->builder->select(...$selects);
99
+        return $this;
100
+    }
101
+
102
+    public function selectAlias($select, $alias) {
103
+        $this->builder->selectAlias($select, $alias);
104
+        return $this;
105
+    }
106
+
107
+    public function selectDistinct($select) {
108
+        $this->builder->selectDistinct($select);
109
+        return $this;
110
+    }
111
+
112
+    public function addSelect(...$select) {
113
+        $this->builder->addSelect(...$select);
114
+        return $this;
115
+    }
116
+
117
+    public function delete($delete = null, $alias = null) {
118
+        $this->builder->delete($delete, $alias);
119
+        return $this;
120
+    }
121
+
122
+    public function update($update = null, $alias = null) {
123
+        $this->builder->update($update, $alias);
124
+        return $this;
125
+    }
126
+
127
+    public function insert($insert = null) {
128
+        $this->builder->insert($insert);
129
+        return $this;
130
+    }
131
+
132
+    public function from($from, $alias = null) {
133
+        $this->builder->from($from, $alias);
134
+        return $this;
135
+    }
136
+
137
+    public function join($fromAlias, $join, $alias, $condition = null) {
138
+        $this->builder->join($fromAlias, $join, $alias, $condition);
139
+        return $this;
140
+    }
141
+
142
+    public function innerJoin($fromAlias, $join, $alias, $condition = null) {
143
+        $this->builder->innerJoin($fromAlias, $join, $alias, $condition);
144
+        return $this;
145
+    }
146
+
147
+    public function leftJoin($fromAlias, $join, $alias, $condition = null) {
148
+        $this->builder->leftJoin($fromAlias, $join, $alias, $condition);
149
+        return $this;
150
+    }
151
+
152
+    public function rightJoin($fromAlias, $join, $alias, $condition = null) {
153
+        $this->builder->rightJoin($fromAlias, $join, $alias, $condition);
154
+        return $this;
155
+    }
156
+
157
+    public function set($key, $value) {
158
+        $this->builder->set($key, $value);
159
+        return $this;
160
+    }
161
+
162
+    public function where(...$predicates) {
163
+        $this->builder->where(...$predicates);
164
+        return $this;
165
+    }
166
+
167
+    public function andWhere(...$where) {
168
+        $this->builder->andWhere(...$where);
169
+        return $this;
170
+    }
171
+
172
+    public function orWhere(...$where) {
173
+        $this->builder->orWhere(...$where);
174
+        return $this;
175
+    }
176
+
177
+    public function groupBy(...$groupBys) {
178
+        $this->builder->groupBy(...$groupBys);
179
+        return $this;
180
+    }
181
+
182
+    public function addGroupBy(...$groupBy) {
183
+        $this->builder->addGroupBy(...$groupBy);
184
+        return $this;
185
+    }
186
+
187
+    public function setValue($column, $value) {
188
+        $this->builder->setValue($column, $value);
189
+        return $this;
190
+    }
191
+
192
+    public function values(array $values) {
193
+        $this->builder->values($values);
194
+        return $this;
195
+    }
196
+
197
+    public function having(...$having) {
198
+        $this->builder->having(...$having);
199
+        return $this;
200
+    }
201
+
202
+    public function andHaving(...$having) {
203
+        $this->builder->andHaving(...$having);
204
+        return $this;
205
+    }
206
+
207
+    public function orHaving(...$having) {
208
+        $this->builder->orHaving(...$having);
209
+        return $this;
210
+    }
211
+
212
+    public function orderBy($sort, $order = null) {
213
+        $this->builder->orderBy($sort, $order);
214
+        return $this;
215
+    }
216
+
217
+    public function addOrderBy($sort, $order = null) {
218
+        $this->builder->addOrderBy($sort, $order);
219
+        return $this;
220
+    }
221
+
222
+    public function getQueryPart($queryPartName) {
223
+        return $this->builder->getQueryPart($queryPartName);
224
+    }
225
+
226
+    public function getQueryParts() {
227
+        return $this->builder->getQueryParts();
228
+    }
229
+
230
+    public function resetQueryParts($queryPartNames = null) {
231
+        $this->builder->resetQueryParts($queryPartNames);
232
+        return $this;
233
+    }
234
+
235
+    public function resetQueryPart($queryPartName) {
236
+        $this->builder->resetQueryPart($queryPartName);
237
+        return $this;
238
+    }
239
+
240
+    public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null) {
241
+        return $this->builder->createNamedParameter($value, $type, $placeHolder);
242
+    }
243
+
244
+    public function createPositionalParameter($value, $type = self::PARAM_STR) {
245
+        return $this->builder->createPositionalParameter($value, $type);
246
+    }
247
+
248
+    public function createParameter($name) {
249
+        return $this->builder->createParameter($name);
250
+    }
251
+
252
+    public function createFunction($call) {
253
+        return $this->builder->createFunction($call);
254
+    }
255
+
256
+    public function getLastInsertId(): int {
257
+        return $this->builder->getLastInsertId();
258
+    }
259
+
260
+    public function getTableName($table) {
261
+        return $this->builder->getTableName($table);
262
+    }
263
+
264
+    public function getColumnName($column, $tableAlias = '') {
265
+        return $this->builder->getColumnName($column, $tableAlias);
266
+    }
267
+
268
+    public function executeQuery(?IDBConnection $connection = null): IResult {
269
+        return $this->builder->executeQuery($connection);
270
+    }
271
+
272
+    public function executeStatement(?IDBConnection $connection = null): int {
273
+        return $this->builder->executeStatement($connection);
274
+    }
275
+
276
+    public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self {
277
+        $this->builder->hintShardKey($column, $value, $overwrite);
278
+        return $this;
279
+    }
280
+
281
+    public function runAcrossAllShards(): self {
282
+        $this->builder->runAcrossAllShards();
283
+        return $this;
284
+    }
285
+
286
+    public function getOutputColumns(): array {
287
+        return $this->builder->getOutputColumns();
288
+    }
289
+
290
+    public function prefixTableName(string $table): string {
291
+        return $this->builder->prefixTableName($table);
292
+    }
293 293
 }
Please login to merge, or discard this patch.
lib/private/DB/QueryBuilder/QueryBuilder.php 1 patch
Indentation   +1342 added lines, -1342 removed lines patch added patch discarded remove patch
@@ -28,1347 +28,1347 @@
 block discarded – undo
28 28
 use Psr\Log\LoggerInterface;
29 29
 
30 30
 class QueryBuilder implements IQueryBuilder {
31
-	/** @var ConnectionAdapter */
32
-	private $connection;
33
-
34
-	/** @var SystemConfig */
35
-	private $systemConfig;
36
-
37
-	private LoggerInterface $logger;
38
-
39
-	/** @var \Doctrine\DBAL\Query\QueryBuilder */
40
-	private $queryBuilder;
41
-
42
-	/** @var QuoteHelper */
43
-	private $helper;
44
-
45
-	/** @var bool */
46
-	private $automaticTablePrefix = true;
47
-	private bool $nonEmptyWhere = false;
48
-
49
-	/** @var string */
50
-	protected $lastInsertedTable;
51
-	private array $selectedColumns = [];
52
-
53
-	/**
54
-	 * Initializes a new QueryBuilder.
55
-	 *
56
-	 * @param ConnectionAdapter $connection
57
-	 * @param SystemConfig $systemConfig
58
-	 */
59
-	public function __construct(ConnectionAdapter $connection, SystemConfig $systemConfig, LoggerInterface $logger) {
60
-		$this->connection = $connection;
61
-		$this->systemConfig = $systemConfig;
62
-		$this->logger = $logger;
63
-		$this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection->getInner());
64
-		$this->helper = new QuoteHelper();
65
-	}
66
-
67
-	/**
68
-	 * Enable/disable automatic prefixing of table names with the oc_ prefix
69
-	 *
70
-	 * @param bool $enabled If set to true table names will be prefixed with the
71
-	 *                      owncloud database prefix automatically.
72
-	 * @since 8.2.0
73
-	 */
74
-	public function automaticTablePrefix($enabled) {
75
-		$this->automaticTablePrefix = (bool)$enabled;
76
-	}
77
-
78
-	/**
79
-	 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
80
-	 * This producer method is intended for convenient inline usage. Example:
81
-	 *
82
-	 * <code>
83
-	 *     $qb = $conn->getQueryBuilder()
84
-	 *         ->select('u')
85
-	 *         ->from('users', 'u')
86
-	 *         ->where($qb->expr()->eq('u.id', 1));
87
-	 * </code>
88
-	 *
89
-	 * For more complex expression construction, consider storing the expression
90
-	 * builder object in a local variable.
91
-	 *
92
-	 * @return \OCP\DB\QueryBuilder\IExpressionBuilder
93
-	 */
94
-	public function expr() {
95
-		return match($this->connection->getDatabaseProvider()) {
96
-			IDBConnection::PLATFORM_ORACLE => new OCIExpressionBuilder($this->connection, $this, $this->logger),
97
-			IDBConnection::PLATFORM_POSTGRES => new PgSqlExpressionBuilder($this->connection, $this, $this->logger),
98
-			IDBConnection::PLATFORM_MARIADB,
99
-			IDBConnection::PLATFORM_MYSQL => new MySqlExpressionBuilder($this->connection, $this, $this->logger),
100
-			IDBConnection::PLATFORM_SQLITE => new SqliteExpressionBuilder($this->connection, $this, $this->logger),
101
-		};
102
-	}
103
-
104
-	/**
105
-	 * Gets an FunctionBuilder used for object-oriented construction of query functions.
106
-	 * This producer method is intended for convenient inline usage. Example:
107
-	 *
108
-	 * <code>
109
-	 *     $qb = $conn->getQueryBuilder()
110
-	 *         ->select('u')
111
-	 *         ->from('users', 'u')
112
-	 *         ->where($qb->fun()->md5('u.id'));
113
-	 * </code>
114
-	 *
115
-	 * For more complex function construction, consider storing the function
116
-	 * builder object in a local variable.
117
-	 *
118
-	 * @return \OCP\DB\QueryBuilder\IFunctionBuilder
119
-	 */
120
-	public function func() {
121
-		return match($this->connection->getDatabaseProvider()) {
122
-			IDBConnection::PLATFORM_ORACLE => new OCIFunctionBuilder($this->connection, $this, $this->helper),
123
-			IDBConnection::PLATFORM_POSTGRES => new PgSqlFunctionBuilder($this->connection, $this, $this->helper),
124
-			IDBConnection::PLATFORM_MARIADB,
125
-			IDBConnection::PLATFORM_MYSQL => new FunctionBuilder($this->connection, $this, $this->helper),
126
-			IDBConnection::PLATFORM_SQLITE => new SqliteFunctionBuilder($this->connection, $this, $this->helper),
127
-		};
128
-	}
129
-
130
-	/**
131
-	 * Gets the type of the currently built query.
132
-	 *
133
-	 * @return integer
134
-	 */
135
-	public function getType() {
136
-		return $this->queryBuilder->getType();
137
-	}
138
-
139
-	/**
140
-	 * Gets the associated DBAL Connection for this query builder.
141
-	 *
142
-	 * @return \OCP\IDBConnection
143
-	 */
144
-	public function getConnection() {
145
-		return $this->connection;
146
-	}
147
-
148
-	/**
149
-	 * Gets the state of this query builder instance.
150
-	 *
151
-	 * @return int Always returns 0 which is former `QueryBuilder::STATE_DIRTY`
152
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
153
-	 *    and we can not fix this in our wrapper.
154
-	 */
155
-	public function getState() {
156
-		$this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
157
-		return $this->queryBuilder->getState();
158
-	}
159
-
160
-	private function prepareForExecute() {
161
-		if ($this->systemConfig->getValue('log_query', false)) {
162
-			try {
163
-				$params = [];
164
-				foreach ($this->getParameters() as $placeholder => $value) {
165
-					if ($value instanceof \DateTimeInterface) {
166
-						$params[] = $placeholder . ' => DateTime:\'' . $value->format('c') . '\'';
167
-					} elseif (is_array($value)) {
168
-						$params[] = $placeholder . ' => (\'' . implode('\', \'', $value) . '\')';
169
-					} else {
170
-						$params[] = $placeholder . ' => \'' . $value . '\'';
171
-					}
172
-				}
173
-				if (empty($params)) {
174
-					$this->logger->debug('DB QueryBuilder: \'{query}\'', [
175
-						'query' => $this->getSQL(),
176
-						'app' => 'core',
177
-					]);
178
-				} else {
179
-					$this->logger->debug('DB QueryBuilder: \'{query}\' with parameters: {params}', [
180
-						'query' => $this->getSQL(),
181
-						'params' => implode(', ', $params),
182
-						'app' => 'core',
183
-					]);
184
-				}
185
-			} catch (\Error $e) {
186
-				// likely an error during conversion of $value to string
187
-				$this->logger->error('DB QueryBuilder: error trying to log SQL query', ['exception' => $e]);
188
-			}
189
-		}
190
-
191
-		// if (!empty($this->getQueryPart('select'))) {
192
-		// $select = $this->getQueryPart('select');
193
-		// $hasSelectAll = array_filter($select, static function ($s) {
194
-		// return $s === '*';
195
-		// });
196
-		// $hasSelectSpecific = array_filter($select, static function ($s) {
197
-		// return $s !== '*';
198
-		// });
199
-
200
-		// if (empty($hasSelectAll) === empty($hasSelectSpecific)) {
201
-		// $exception = new QueryException('Query is selecting * and specific values in the same query. This is not supported in Oracle.');
202
-		// $this->logger->error($exception->getMessage(), [
203
-		// 'query' => $this->getSQL(),
204
-		// 'app' => 'core',
205
-		// 'exception' => $exception,
206
-		// ]);
207
-		// }
208
-		// }
209
-
210
-		$tooLongOutputColumns = [];
211
-		foreach ($this->getOutputColumns() as $column) {
212
-			if (strlen($column) > 30) {
213
-				$tooLongOutputColumns[] = $column;
214
-			}
215
-		}
216
-
217
-		if (!empty($tooLongOutputColumns)) {
218
-			$exception = new QueryException('More than 30 characters for an output column name are not allowed on Oracle.');
219
-			$this->logger->error($exception->getMessage(), [
220
-				'query' => $this->getSQL(),
221
-				'columns' => $tooLongOutputColumns,
222
-				'app' => 'core',
223
-				'exception' => $exception,
224
-			]);
225
-		}
226
-
227
-		$numberOfParameters = 0;
228
-		$hasTooLargeArrayParameter = false;
229
-		foreach ($this->getParameters() as $parameter) {
230
-			if (is_array($parameter)) {
231
-				$count = count($parameter);
232
-				$numberOfParameters += $count;
233
-				$hasTooLargeArrayParameter = $hasTooLargeArrayParameter || ($count > 1000);
234
-			}
235
-		}
236
-
237
-		if ($hasTooLargeArrayParameter) {
238
-			$exception = new QueryException('More than 1000 expressions in a list are not allowed on Oracle.');
239
-			$this->logger->error($exception->getMessage(), [
240
-				'query' => $this->getSQL(),
241
-				'app' => 'core',
242
-				'exception' => $exception,
243
-			]);
244
-		}
245
-
246
-		if ($numberOfParameters > 65535) {
247
-			$exception = new QueryException('The number of parameters must not exceed 65535. Restriction by PostgreSQL.');
248
-			$this->logger->error($exception->getMessage(), [
249
-				'query' => $this->getSQL(),
250
-				'app' => 'core',
251
-				'exception' => $exception,
252
-			]);
253
-		}
254
-	}
255
-
256
-	public function executeQuery(?IDBConnection $connection = null): IResult {
257
-		if ($this->getType() !== \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
258
-			throw new \RuntimeException('Invalid query type, expected SELECT query');
259
-		}
260
-
261
-		$this->prepareForExecute();
262
-		if (!$connection) {
263
-			$connection = $this->connection;
264
-		}
265
-
266
-		return $connection->executeQuery(
267
-			$this->getSQL(),
268
-			$this->getParameters(),
269
-			$this->getParameterTypes(),
270
-		);
271
-	}
272
-
273
-	public function executeStatement(?IDBConnection $connection = null): int {
274
-		if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
275
-			throw new \RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
276
-		}
277
-
278
-		$this->prepareForExecute();
279
-		if (!$connection) {
280
-			$connection = $this->connection;
281
-		}
282
-
283
-		return $connection->executeStatement(
284
-			$this->getSQL(),
285
-			$this->getParameters(),
286
-			$this->getParameterTypes(),
287
-		);
288
-	}
289
-
290
-
291
-	/**
292
-	 * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
293
-	 *
294
-	 * <code>
295
-	 *     $qb = $conn->getQueryBuilder()
296
-	 *         ->select('u')
297
-	 *         ->from('User', 'u')
298
-	 *     echo $qb->getSQL(); // SELECT u FROM User u
299
-	 * </code>
300
-	 *
301
-	 * @return string The SQL query string.
302
-	 */
303
-	public function getSQL() {
304
-		return $this->queryBuilder->getSQL();
305
-	}
306
-
307
-	/**
308
-	 * Sets a query parameter for the query being constructed.
309
-	 *
310
-	 * <code>
311
-	 *     $qb = $conn->getQueryBuilder()
312
-	 *         ->select('u')
313
-	 *         ->from('users', 'u')
314
-	 *         ->where('u.id = :user_id')
315
-	 *         ->setParameter(':user_id', 1);
316
-	 * </code>
317
-	 *
318
-	 * @param string|integer $key The parameter position or name.
319
-	 * @param mixed $value The parameter value.
320
-	 * @param string|null|int $type One of the IQueryBuilder::PARAM_* constants.
321
-	 *
322
-	 * @return $this This QueryBuilder instance.
323
-	 */
324
-	public function setParameter($key, $value, $type = null) {
325
-		$this->queryBuilder->setParameter($key, $value, $type);
326
-
327
-		return $this;
328
-	}
329
-
330
-	/**
331
-	 * Sets a collection of query parameters for the query being constructed.
332
-	 *
333
-	 * <code>
334
-	 *     $qb = $conn->getQueryBuilder()
335
-	 *         ->select('u')
336
-	 *         ->from('users', 'u')
337
-	 *         ->where('u.id = :user_id1 OR u.id = :user_id2')
338
-	 *         ->setParameters(array(
339
-	 *             ':user_id1' => 1,
340
-	 *             ':user_id2' => 2
341
-	 *         ));
342
-	 * </code>
343
-	 *
344
-	 * @param array $params The query parameters to set.
345
-	 * @param array $types The query parameters types to set.
346
-	 *
347
-	 * @return $this This QueryBuilder instance.
348
-	 */
349
-	public function setParameters(array $params, array $types = []) {
350
-		$this->queryBuilder->setParameters($params, $types);
351
-
352
-		return $this;
353
-	}
354
-
355
-	/**
356
-	 * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
357
-	 *
358
-	 * @return array The currently defined query parameters indexed by parameter index or name.
359
-	 */
360
-	public function getParameters() {
361
-		return $this->queryBuilder->getParameters();
362
-	}
363
-
364
-	/**
365
-	 * Gets a (previously set) query parameter of the query being constructed.
366
-	 *
367
-	 * @param mixed $key The key (index or name) of the bound parameter.
368
-	 *
369
-	 * @return mixed The value of the bound parameter.
370
-	 */
371
-	public function getParameter($key) {
372
-		return $this->queryBuilder->getParameter($key);
373
-	}
374
-
375
-	/**
376
-	 * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
377
-	 *
378
-	 * @return array The currently defined query parameter types indexed by parameter index or name.
379
-	 */
380
-	public function getParameterTypes() {
381
-		return $this->queryBuilder->getParameterTypes();
382
-	}
383
-
384
-	/**
385
-	 * Gets a (previously set) query parameter type of the query being constructed.
386
-	 *
387
-	 * @param mixed $key The key (index or name) of the bound parameter type.
388
-	 *
389
-	 * @return mixed The value of the bound parameter type.
390
-	 */
391
-	public function getParameterType($key) {
392
-		return $this->queryBuilder->getParameterType($key);
393
-	}
394
-
395
-	/**
396
-	 * Sets the position of the first result to retrieve (the "offset").
397
-	 *
398
-	 * @param int $firstResult The first result to return.
399
-	 *
400
-	 * @return $this This QueryBuilder instance.
401
-	 */
402
-	public function setFirstResult($firstResult) {
403
-		$this->queryBuilder->setFirstResult((int)$firstResult);
404
-
405
-		return $this;
406
-	}
407
-
408
-	/**
409
-	 * Gets the position of the first result the query object was set to retrieve (the "offset").
410
-	 * Returns 0 if {@link setFirstResult} was not applied to this QueryBuilder.
411
-	 *
412
-	 * @return int The position of the first result.
413
-	 */
414
-	public function getFirstResult() {
415
-		return $this->queryBuilder->getFirstResult();
416
-	}
417
-
418
-	/**
419
-	 * Sets the maximum number of results to retrieve (the "limit").
420
-	 *
421
-	 * NOTE: Setting max results to "0" will cause mixed behaviour. While most
422
-	 * of the databases will just return an empty result set, Oracle will return
423
-	 * all entries.
424
-	 *
425
-	 * @param int|null $maxResults The maximum number of results to retrieve.
426
-	 *
427
-	 * @return $this This QueryBuilder instance.
428
-	 */
429
-	public function setMaxResults($maxResults) {
430
-		if ($maxResults === null) {
431
-			$this->queryBuilder->setMaxResults($maxResults);
432
-		} else {
433
-			$this->queryBuilder->setMaxResults((int)$maxResults);
434
-		}
435
-
436
-		return $this;
437
-	}
438
-
439
-	/**
440
-	 * Gets the maximum number of results the query object was set to retrieve (the "limit").
441
-	 * Returns NULL if {@link setMaxResults} was not applied to this query builder.
442
-	 *
443
-	 * @return int|null The maximum number of results.
444
-	 */
445
-	public function getMaxResults() {
446
-		return $this->queryBuilder->getMaxResults();
447
-	}
448
-
449
-	/**
450
-	 * Specifies an item that is to be returned in the query result.
451
-	 * Replaces any previously specified selections, if any.
452
-	 *
453
-	 * <code>
454
-	 *     $qb = $conn->getQueryBuilder()
455
-	 *         ->select('u.id', 'p.id')
456
-	 *         ->from('users', 'u')
457
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
458
-	 * </code>
459
-	 *
460
-	 * @param mixed ...$selects The selection expressions.
461
-	 *
462
-	 * '@return $this This QueryBuilder instance.
463
-	 */
464
-	public function select(...$selects) {
465
-		if (count($selects) === 1 && is_array($selects[0])) {
466
-			$selects = $selects[0];
467
-		}
468
-		$this->addOutputColumns($selects);
469
-
470
-		$this->queryBuilder->select(
471
-			$this->helper->quoteColumnNames($selects)
472
-		);
473
-
474
-		return $this;
475
-	}
476
-
477
-	/**
478
-	 * Specifies an item that is to be returned with a different name in the query result.
479
-	 *
480
-	 * <code>
481
-	 *     $qb = $conn->getQueryBuilder()
482
-	 *         ->selectAlias('u.id', 'user_id')
483
-	 *         ->from('users', 'u')
484
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
485
-	 * </code>
486
-	 *
487
-	 * @param mixed $select The selection expressions.
488
-	 * @param string $alias The column alias used in the constructed query.
489
-	 *
490
-	 * @return $this This QueryBuilder instance.
491
-	 */
492
-	public function selectAlias($select, $alias) {
493
-		$this->queryBuilder->addSelect(
494
-			$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
495
-		);
496
-		$this->addOutputColumns([$alias]);
497
-
498
-		return $this;
499
-	}
500
-
501
-	/**
502
-	 * Specifies an item that is to be returned uniquely in the query result.
503
-	 *
504
-	 * <code>
505
-	 *     $qb = $conn->getQueryBuilder()
506
-	 *         ->selectDistinct('type')
507
-	 *         ->from('users');
508
-	 * </code>
509
-	 *
510
-	 * @param mixed $select The selection expressions.
511
-	 *
512
-	 * @return $this This QueryBuilder instance.
513
-	 */
514
-	public function selectDistinct($select) {
515
-		if (!is_array($select)) {
516
-			$select = [$select];
517
-		}
518
-		$this->addOutputColumns($select);
519
-
520
-		$quotedSelect = $this->helper->quoteColumnNames($select);
521
-
522
-		$this->queryBuilder->addSelect(
523
-			'DISTINCT ' . implode(', ', $quotedSelect)
524
-		);
525
-
526
-		return $this;
527
-	}
528
-
529
-	/**
530
-	 * Adds an item that is to be returned in the query result.
531
-	 *
532
-	 * <code>
533
-	 *     $qb = $conn->getQueryBuilder()
534
-	 *         ->select('u.id')
535
-	 *         ->addSelect('p.id')
536
-	 *         ->from('users', 'u')
537
-	 *         ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
538
-	 * </code>
539
-	 *
540
-	 * @param mixed ...$selects The selection expression.
541
-	 *
542
-	 * @return $this This QueryBuilder instance.
543
-	 */
544
-	public function addSelect(...$selects) {
545
-		if (count($selects) === 1 && is_array($selects[0])) {
546
-			$selects = $selects[0];
547
-		}
548
-		$this->addOutputColumns($selects);
549
-
550
-		$this->queryBuilder->addSelect(
551
-			$this->helper->quoteColumnNames($selects)
552
-		);
553
-
554
-		return $this;
555
-	}
556
-
557
-	private function addOutputColumns(array $columns): void {
558
-		foreach ($columns as $column) {
559
-			if (is_array($column)) {
560
-				$this->addOutputColumns($column);
561
-			} elseif (is_string($column) && !str_contains($column, '*')) {
562
-				if (str_contains(strtolower($column), ' as ')) {
563
-					[, $column] = preg_split('/ as /i', $column);
564
-				}
565
-				if (str_contains($column, '.')) {
566
-					[, $column] = explode('.', $column);
567
-				}
568
-				$this->selectedColumns[] = $column;
569
-			}
570
-		}
571
-	}
572
-
573
-	public function getOutputColumns(): array {
574
-		return array_unique($this->selectedColumns);
575
-	}
576
-
577
-	/**
578
-	 * Turns the query being built into a bulk delete query that ranges over
579
-	 * a certain table.
580
-	 *
581
-	 * <code>
582
-	 *     $qb = $conn->getQueryBuilder()
583
-	 *         ->delete('users', 'u')
584
-	 *         ->where('u.id = :user_id');
585
-	 *         ->setParameter(':user_id', 1);
586
-	 * </code>
587
-	 *
588
-	 * @param string $delete The table whose rows are subject to the deletion.
589
-	 * @param string $alias The table alias used in the constructed query.
590
-	 *
591
-	 * @return $this This QueryBuilder instance.
592
-	 * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
593
-	 */
594
-	public function delete($delete = null, $alias = null) {
595
-		if ($alias !== null) {
596
-			$this->logger->debug('DELETE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for DELETE query')]);
597
-		}
598
-
599
-		$this->queryBuilder->delete(
600
-			$this->getTableName($delete),
601
-			$alias
602
-		);
603
-
604
-		return $this;
605
-	}
606
-
607
-	/**
608
-	 * Turns the query being built into a bulk update query that ranges over
609
-	 * a certain table
610
-	 *
611
-	 * <code>
612
-	 *     $qb = $conn->getQueryBuilder()
613
-	 *         ->update('users', 'u')
614
-	 *         ->set('u.password', md5('password'))
615
-	 *         ->where('u.id = ?');
616
-	 * </code>
617
-	 *
618
-	 * @param string $update The table whose rows are subject to the update.
619
-	 * @param string $alias The table alias used in the constructed query.
620
-	 *
621
-	 * @return $this This QueryBuilder instance.
622
-	 * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
623
-	 */
624
-	public function update($update = null, $alias = null) {
625
-		if ($alias !== null) {
626
-			$this->logger->debug('UPDATE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for UPDATE query')]);
627
-		}
628
-
629
-		$this->queryBuilder->update(
630
-			$this->getTableName($update),
631
-			$alias
632
-		);
633
-
634
-		return $this;
635
-	}
636
-
637
-	/**
638
-	 * Turns the query being built into an insert query that inserts into
639
-	 * a certain table
640
-	 *
641
-	 * <code>
642
-	 *     $qb = $conn->getQueryBuilder()
643
-	 *         ->insert('users')
644
-	 *         ->values(
645
-	 *             array(
646
-	 *                 'name' => '?',
647
-	 *                 'password' => '?'
648
-	 *             )
649
-	 *         );
650
-	 * </code>
651
-	 *
652
-	 * @param string $insert The table into which the rows should be inserted.
653
-	 *
654
-	 * @return $this This QueryBuilder instance.
655
-	 */
656
-	public function insert($insert = null) {
657
-		$this->queryBuilder->insert(
658
-			$this->getTableName($insert)
659
-		);
660
-
661
-		$this->lastInsertedTable = $insert;
662
-
663
-		return $this;
664
-	}
665
-
666
-	/**
667
-	 * Creates and adds a query root corresponding to the table identified by the
668
-	 * given alias, forming a cartesian product with any existing query roots.
669
-	 *
670
-	 * <code>
671
-	 *     $qb = $conn->getQueryBuilder()
672
-	 *         ->select('u.id')
673
-	 *         ->from('users', 'u')
674
-	 * </code>
675
-	 *
676
-	 * @param string|IQueryFunction $from The table.
677
-	 * @param string|null $alias The alias of the table.
678
-	 *
679
-	 * @return $this This QueryBuilder instance.
680
-	 */
681
-	public function from($from, $alias = null) {
682
-		$this->queryBuilder->from(
683
-			$this->getTableName($from),
684
-			$this->quoteAlias($alias)
685
-		);
686
-
687
-		return $this;
688
-	}
689
-
690
-	/**
691
-	 * Creates and adds a join to the query.
692
-	 *
693
-	 * <code>
694
-	 *     $qb = $conn->getQueryBuilder()
695
-	 *         ->select('u.name')
696
-	 *         ->from('users', 'u')
697
-	 *         ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
698
-	 * </code>
699
-	 *
700
-	 * @param string $fromAlias The alias that points to a from clause.
701
-	 * @param string $join The table name to join.
702
-	 * @param string $alias The alias of the join table.
703
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
704
-	 *
705
-	 * @return $this This QueryBuilder instance.
706
-	 */
707
-	public function join($fromAlias, $join, $alias, $condition = null) {
708
-		$this->queryBuilder->join(
709
-			$this->quoteAlias($fromAlias),
710
-			$this->getTableName($join),
711
-			$this->quoteAlias($alias),
712
-			$condition
713
-		);
714
-
715
-		return $this;
716
-	}
717
-
718
-	/**
719
-	 * Creates and adds a join to the query.
720
-	 *
721
-	 * <code>
722
-	 *     $qb = $conn->getQueryBuilder()
723
-	 *         ->select('u.name')
724
-	 *         ->from('users', 'u')
725
-	 *         ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
726
-	 * </code>
727
-	 *
728
-	 * @param string $fromAlias The alias that points to a from clause.
729
-	 * @param string $join The table name to join.
730
-	 * @param string $alias The alias of the join table.
731
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
732
-	 *
733
-	 * @return $this This QueryBuilder instance.
734
-	 */
735
-	public function innerJoin($fromAlias, $join, $alias, $condition = null) {
736
-		$this->queryBuilder->innerJoin(
737
-			$this->quoteAlias($fromAlias),
738
-			$this->getTableName($join),
739
-			$this->quoteAlias($alias),
740
-			$condition
741
-		);
742
-
743
-		return $this;
744
-	}
745
-
746
-	/**
747
-	 * Creates and adds a left join to the query.
748
-	 *
749
-	 * <code>
750
-	 *     $qb = $conn->getQueryBuilder()
751
-	 *         ->select('u.name')
752
-	 *         ->from('users', 'u')
753
-	 *         ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
754
-	 * </code>
755
-	 *
756
-	 * @param string $fromAlias The alias that points to a from clause.
757
-	 * @param string|IQueryFunction $join The table name or sub-query to join.
758
-	 * @param string $alias The alias of the join table.
759
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
760
-	 *
761
-	 * @return $this This QueryBuilder instance.
762
-	 */
763
-	public function leftJoin($fromAlias, $join, $alias, $condition = null) {
764
-		$this->queryBuilder->leftJoin(
765
-			$this->quoteAlias($fromAlias),
766
-			$this->getTableName($join),
767
-			$this->quoteAlias($alias),
768
-			$condition
769
-		);
770
-
771
-		return $this;
772
-	}
773
-
774
-	/**
775
-	 * Creates and adds a right join to the query.
776
-	 *
777
-	 * <code>
778
-	 *     $qb = $conn->getQueryBuilder()
779
-	 *         ->select('u.name')
780
-	 *         ->from('users', 'u')
781
-	 *         ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
782
-	 * </code>
783
-	 *
784
-	 * @param string $fromAlias The alias that points to a from clause.
785
-	 * @param string $join The table name to join.
786
-	 * @param string $alias The alias of the join table.
787
-	 * @param string|ICompositeExpression|null $condition The condition for the join.
788
-	 *
789
-	 * @return $this This QueryBuilder instance.
790
-	 */
791
-	public function rightJoin($fromAlias, $join, $alias, $condition = null) {
792
-		$this->queryBuilder->rightJoin(
793
-			$this->quoteAlias($fromAlias),
794
-			$this->getTableName($join),
795
-			$this->quoteAlias($alias),
796
-			$condition
797
-		);
798
-
799
-		return $this;
800
-	}
801
-
802
-	/**
803
-	 * Sets a new value for a column in a bulk update query.
804
-	 *
805
-	 * <code>
806
-	 *     $qb = $conn->getQueryBuilder()
807
-	 *         ->update('users', 'u')
808
-	 *         ->set('u.password', md5('password'))
809
-	 *         ->where('u.id = ?');
810
-	 * </code>
811
-	 *
812
-	 * @param string $key The column to set.
813
-	 * @param ILiteral|IParameter|IQueryFunction|string $value The value, expression, placeholder, etc.
814
-	 *
815
-	 * @return $this This QueryBuilder instance.
816
-	 */
817
-	public function set($key, $value) {
818
-		$this->queryBuilder->set(
819
-			$this->helper->quoteColumnName($key),
820
-			$this->helper->quoteColumnName($value)
821
-		);
822
-
823
-		return $this;
824
-	}
825
-
826
-	/**
827
-	 * Specifies one or more restrictions to the query result.
828
-	 * Replaces any previously specified restrictions, if any.
829
-	 *
830
-	 * <code>
831
-	 *     $qb = $conn->getQueryBuilder()
832
-	 *         ->select('u.name')
833
-	 *         ->from('users', 'u')
834
-	 *         ->where('u.id = ?');
835
-	 *
836
-	 *     // You can optionally programmatically build and/or expressions
837
-	 *     $qb = $conn->getQueryBuilder();
838
-	 *
839
-	 *     $or = $qb->expr()->orx(
840
-	 *         $qb->expr()->eq('u.id', 1),
841
-	 *         $qb->expr()->eq('u.id', 2),
842
-	 *     );
843
-	 *
844
-	 *     $qb->update('users', 'u')
845
-	 *         ->set('u.password', md5('password'))
846
-	 *         ->where($or);
847
-	 * </code>
848
-	 *
849
-	 * @param mixed ...$predicates The restriction predicates.
850
-	 *
851
-	 * @return $this This QueryBuilder instance.
852
-	 */
853
-	public function where(...$predicates) {
854
-		if ($this->nonEmptyWhere && $this->systemConfig->getValue('debug', false)) {
855
-			// Only logging a warning, not throwing for now.
856
-			$e = new QueryException('Using where() on non-empty WHERE part, please verify it is intentional to not call andWhere() or orWhere() instead. Otherwise consider creating a new query builder object or call resetQueryPart(\'where\') first.');
857
-			$this->logger->warning($e->getMessage(), ['exception' => $e]);
858
-		}
859
-
860
-		$this->nonEmptyWhere = true;
861
-
862
-		call_user_func_array(
863
-			[$this->queryBuilder, 'where'],
864
-			$predicates
865
-		);
866
-
867
-		return $this;
868
-	}
869
-
870
-	/**
871
-	 * Adds one or more restrictions to the query results, forming a logical
872
-	 * conjunction with any previously specified restrictions.
873
-	 *
874
-	 * <code>
875
-	 *     $qb = $conn->getQueryBuilder()
876
-	 *         ->select('u')
877
-	 *         ->from('users', 'u')
878
-	 *         ->where('u.username LIKE ?')
879
-	 *         ->andWhere('u.is_active = 1');
880
-	 * </code>
881
-	 *
882
-	 * @param mixed ...$where The query restrictions.
883
-	 *
884
-	 * @return $this This QueryBuilder instance.
885
-	 *
886
-	 * @see where()
887
-	 */
888
-	public function andWhere(...$where) {
889
-		$this->nonEmptyWhere = true;
890
-		call_user_func_array(
891
-			[$this->queryBuilder, 'andWhere'],
892
-			$where
893
-		);
894
-
895
-		return $this;
896
-	}
897
-
898
-	/**
899
-	 * Adds one or more restrictions to the query results, forming a logical
900
-	 * disjunction with any previously specified restrictions.
901
-	 *
902
-	 * <code>
903
-	 *     $qb = $conn->getQueryBuilder()
904
-	 *         ->select('u.name')
905
-	 *         ->from('users', 'u')
906
-	 *         ->where('u.id = 1')
907
-	 *         ->orWhere('u.id = 2');
908
-	 * </code>
909
-	 *
910
-	 * @param mixed ...$where The WHERE statement.
911
-	 *
912
-	 * @return $this This QueryBuilder instance.
913
-	 *
914
-	 * @see where()
915
-	 */
916
-	public function orWhere(...$where) {
917
-		$this->nonEmptyWhere = true;
918
-		call_user_func_array(
919
-			[$this->queryBuilder, 'orWhere'],
920
-			$where
921
-		);
922
-
923
-		return $this;
924
-	}
925
-
926
-	/**
927
-	 * Specifies a grouping over the results of the query.
928
-	 * Replaces any previously specified groupings, if any.
929
-	 *
930
-	 * <code>
931
-	 *     $qb = $conn->getQueryBuilder()
932
-	 *         ->select('u.name')
933
-	 *         ->from('users', 'u')
934
-	 *         ->groupBy('u.id');
935
-	 * </code>
936
-	 *
937
-	 * @param mixed ...$groupBys The grouping expression.
938
-	 *
939
-	 * @return $this This QueryBuilder instance.
940
-	 */
941
-	public function groupBy(...$groupBys) {
942
-		if (count($groupBys) === 1 && is_array($groupBys[0])) {
943
-			$groupBys = $groupBys[0];
944
-		}
945
-
946
-		call_user_func_array(
947
-			[$this->queryBuilder, 'groupBy'],
948
-			$this->helper->quoteColumnNames($groupBys)
949
-		);
950
-
951
-		return $this;
952
-	}
953
-
954
-	/**
955
-	 * Adds a grouping expression to the query.
956
-	 *
957
-	 * <code>
958
-	 *     $qb = $conn->getQueryBuilder()
959
-	 *         ->select('u.name')
960
-	 *         ->from('users', 'u')
961
-	 *         ->groupBy('u.lastLogin');
962
-	 *         ->addGroupBy('u.createdAt')
963
-	 * </code>
964
-	 *
965
-	 * @param mixed ...$groupBy The grouping expression.
966
-	 *
967
-	 * @return $this This QueryBuilder instance.
968
-	 */
969
-	public function addGroupBy(...$groupBy) {
970
-		call_user_func_array(
971
-			[$this->queryBuilder, 'addGroupBy'],
972
-			$this->helper->quoteColumnNames($groupBy)
973
-		);
974
-
975
-		return $this;
976
-	}
977
-
978
-	/**
979
-	 * Sets a value for a column in an insert query.
980
-	 *
981
-	 * <code>
982
-	 *     $qb = $conn->getQueryBuilder()
983
-	 *         ->insert('users')
984
-	 *         ->values(
985
-	 *             array(
986
-	 *                 'name' => '?'
987
-	 *             )
988
-	 *         )
989
-	 *         ->setValue('password', '?');
990
-	 * </code>
991
-	 *
992
-	 * @param string $column The column into which the value should be inserted.
993
-	 * @param IParameter|string $value The value that should be inserted into the column.
994
-	 *
995
-	 * @return $this This QueryBuilder instance.
996
-	 */
997
-	public function setValue($column, $value) {
998
-		$this->queryBuilder->setValue(
999
-			$this->helper->quoteColumnName($column),
1000
-			(string)$value
1001
-		);
1002
-
1003
-		return $this;
1004
-	}
1005
-
1006
-	/**
1007
-	 * Specifies values for an insert query indexed by column names.
1008
-	 * Replaces any previous values, if any.
1009
-	 *
1010
-	 * <code>
1011
-	 *     $qb = $conn->getQueryBuilder()
1012
-	 *         ->insert('users')
1013
-	 *         ->values(
1014
-	 *             array(
1015
-	 *                 'name' => '?',
1016
-	 *                 'password' => '?'
1017
-	 *             )
1018
-	 *         );
1019
-	 * </code>
1020
-	 *
1021
-	 * @param array $values The values to specify for the insert query indexed by column names.
1022
-	 *
1023
-	 * @return $this This QueryBuilder instance.
1024
-	 */
1025
-	public function values(array $values) {
1026
-		$quotedValues = [];
1027
-		foreach ($values as $key => $value) {
1028
-			$quotedValues[$this->helper->quoteColumnName($key)] = $value;
1029
-		}
1030
-
1031
-		$this->queryBuilder->values($quotedValues);
1032
-
1033
-		return $this;
1034
-	}
1035
-
1036
-	/**
1037
-	 * Specifies a restriction over the groups of the query.
1038
-	 * Replaces any previous having restrictions, if any.
1039
-	 *
1040
-	 * @param mixed ...$having The restriction over the groups.
1041
-	 *
1042
-	 * @return $this This QueryBuilder instance.
1043
-	 */
1044
-	public function having(...$having) {
1045
-		call_user_func_array(
1046
-			[$this->queryBuilder, 'having'],
1047
-			$having
1048
-		);
1049
-
1050
-		return $this;
1051
-	}
1052
-
1053
-	/**
1054
-	 * Adds a restriction over the groups of the query, forming a logical
1055
-	 * conjunction with any existing having restrictions.
1056
-	 *
1057
-	 * @param mixed ...$having The restriction to append.
1058
-	 *
1059
-	 * @return $this This QueryBuilder instance.
1060
-	 */
1061
-	public function andHaving(...$having) {
1062
-		call_user_func_array(
1063
-			[$this->queryBuilder, 'andHaving'],
1064
-			$having
1065
-		);
1066
-
1067
-		return $this;
1068
-	}
1069
-
1070
-	/**
1071
-	 * Adds a restriction over the groups of the query, forming a logical
1072
-	 * disjunction with any existing having restrictions.
1073
-	 *
1074
-	 * @param mixed ...$having The restriction to add.
1075
-	 *
1076
-	 * @return $this This QueryBuilder instance.
1077
-	 */
1078
-	public function orHaving(...$having) {
1079
-		call_user_func_array(
1080
-			[$this->queryBuilder, 'orHaving'],
1081
-			$having
1082
-		);
1083
-
1084
-		return $this;
1085
-	}
1086
-
1087
-	/**
1088
-	 * Specifies an ordering for the query results.
1089
-	 * Replaces any previously specified orderings, if any.
1090
-	 *
1091
-	 * @param string|IQueryFunction|ILiteral|IParameter $sort The ordering expression.
1092
-	 * @param string $order The ordering direction.
1093
-	 *
1094
-	 * @return $this This QueryBuilder instance.
1095
-	 */
1096
-	public function orderBy($sort, $order = null) {
1097
-		$this->queryBuilder->orderBy(
1098
-			$this->helper->quoteColumnName($sort),
1099
-			$order
1100
-		);
1101
-
1102
-		return $this;
1103
-	}
1104
-
1105
-	/**
1106
-	 * Adds an ordering to the query results.
1107
-	 *
1108
-	 * @param string|ILiteral|IParameter|IQueryFunction $sort The ordering expression.
1109
-	 * @param string $order The ordering direction.
1110
-	 *
1111
-	 * @return $this This QueryBuilder instance.
1112
-	 */
1113
-	public function addOrderBy($sort, $order = null) {
1114
-		$this->queryBuilder->addOrderBy(
1115
-			$this->helper->quoteColumnName($sort),
1116
-			$order
1117
-		);
1118
-
1119
-		return $this;
1120
-	}
1121
-
1122
-	/**
1123
-	 * Gets a query part by its name.
1124
-	 *
1125
-	 * @param string $queryPartName
1126
-	 *
1127
-	 * @return mixed
1128
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1129
-	 *   and we can not fix this in our wrapper. Please track the details you need, outside the object.
1130
-	 */
1131
-	public function getQueryPart($queryPartName) {
1132
-		$this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1133
-		return $this->queryBuilder->getQueryPart($queryPartName);
1134
-	}
1135
-
1136
-	/**
1137
-	 * Gets all query parts.
1138
-	 *
1139
-	 * @return array
1140
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1141
-	 *   and we can not fix this in our wrapper. Please track the details you need, outside the object.
1142
-	 */
1143
-	public function getQueryParts() {
1144
-		$this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1145
-		return $this->queryBuilder->getQueryParts();
1146
-	}
1147
-
1148
-	/**
1149
-	 * Resets SQL parts.
1150
-	 *
1151
-	 * @param array|null $queryPartNames
1152
-	 *
1153
-	 * @return $this This QueryBuilder instance.
1154
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1155
-	 *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
1156
-	 */
1157
-	public function resetQueryParts($queryPartNames = null) {
1158
-		$this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1159
-		$this->queryBuilder->resetQueryParts($queryPartNames);
1160
-
1161
-		return $this;
1162
-	}
1163
-
1164
-	/**
1165
-	 * Resets a single SQL part.
1166
-	 *
1167
-	 * @param string $queryPartName
1168
-	 *
1169
-	 * @return $this This QueryBuilder instance.
1170
-	 * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1171
-	 *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
1172
-	 */
1173
-	public function resetQueryPart($queryPartName) {
1174
-		$this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1175
-		$this->queryBuilder->resetQueryPart($queryPartName);
1176
-
1177
-		return $this;
1178
-	}
1179
-
1180
-	/**
1181
-	 * Creates a new named parameter and bind the value $value to it.
1182
-	 *
1183
-	 * This method provides a shortcut for PDOStatement::bindValue
1184
-	 * when using prepared statements.
1185
-	 *
1186
-	 * The parameter $value specifies the value that you want to bind. If
1187
-	 * $placeholder is not provided bindValue() will automatically create a
1188
-	 * placeholder for you. An automatic placeholder will be of the name
1189
-	 * ':dcValue1', ':dcValue2' etc.
1190
-	 *
1191
-	 * For more information see {@link https://www.php.net/pdostatement-bindparam}
1192
-	 *
1193
-	 * Example:
1194
-	 * <code>
1195
-	 * $value = 2;
1196
-	 * $q->eq( 'id', $q->bindValue( $value ) );
1197
-	 * $stmt = $q->executeQuery(); // executed with 'id = 2'
1198
-	 * </code>
1199
-	 *
1200
-	 * @license New BSD License
1201
-	 * @link http://www.zetacomponents.org
1202
-	 *
1203
-	 * @param mixed $value
1204
-	 * @param IQueryBuilder::PARAM_* $type
1205
-	 * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
1206
-	 *
1207
-	 * @return IParameter the placeholder name used.
1208
-	 */
1209
-	public function createNamedParameter($value, $type = IQueryBuilder::PARAM_STR, $placeHolder = null) {
1210
-		return new Parameter($this->queryBuilder->createNamedParameter($value, $type, $placeHolder));
1211
-	}
1212
-
1213
-	/**
1214
-	 * Creates a new positional parameter and bind the given value to it.
1215
-	 *
1216
-	 * Attention: If you are using positional parameters with the query builder you have
1217
-	 * to be very careful to bind all parameters in the order they appear in the SQL
1218
-	 * statement , otherwise they get bound in the wrong order which can lead to serious
1219
-	 * bugs in your code.
1220
-	 *
1221
-	 * Example:
1222
-	 * <code>
1223
-	 *  $qb = $conn->getQueryBuilder();
1224
-	 *  $qb->select('u.*')
1225
-	 *     ->from('users', 'u')
1226
-	 *     ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
1227
-	 *     ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
1228
-	 * </code>
1229
-	 *
1230
-	 * @param mixed $value
1231
-	 * @param IQueryBuilder::PARAM_* $type
1232
-	 *
1233
-	 * @return IParameter
1234
-	 */
1235
-	public function createPositionalParameter($value, $type = IQueryBuilder::PARAM_STR) {
1236
-		return new Parameter($this->queryBuilder->createPositionalParameter($value, $type));
1237
-	}
1238
-
1239
-	/**
1240
-	 * Creates a new parameter
1241
-	 *
1242
-	 * Example:
1243
-	 * <code>
1244
-	 *  $qb = $conn->getQueryBuilder();
1245
-	 *  $qb->select('u.*')
1246
-	 *     ->from('users', 'u')
1247
-	 *     ->where('u.username = ' . $qb->createParameter('name'))
1248
-	 *     ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
1249
-	 * </code>
1250
-	 *
1251
-	 * @param string $name
1252
-	 *
1253
-	 * @return IParameter
1254
-	 */
1255
-	public function createParameter($name) {
1256
-		return new Parameter(':' . $name);
1257
-	}
1258
-
1259
-	/**
1260
-	 * Creates a new function
1261
-	 *
1262
-	 * Attention: Column names inside the call have to be quoted before hand
1263
-	 *
1264
-	 * Example:
1265
-	 * <code>
1266
-	 *  $qb = $conn->getQueryBuilder();
1267
-	 *  $qb->select($qb->createFunction('COUNT(*)'))
1268
-	 *     ->from('users', 'u')
1269
-	 *  echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
1270
-	 * </code>
1271
-	 * <code>
1272
-	 *  $qb = $conn->getQueryBuilder();
1273
-	 *  $qb->select($qb->createFunction('COUNT(`column`)'))
1274
-	 *     ->from('users', 'u')
1275
-	 *  echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
1276
-	 * </code>
1277
-	 *
1278
-	 * @param string $call
1279
-	 *
1280
-	 * @return IQueryFunction
1281
-	 */
1282
-	public function createFunction($call) {
1283
-		return new QueryFunction($call);
1284
-	}
1285
-
1286
-	/**
1287
-	 * Used to get the id of the last inserted element
1288
-	 * @return int
1289
-	 * @throws \BadMethodCallException When being called before an insert query has been run.
1290
-	 */
1291
-	public function getLastInsertId(): int {
1292
-		if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) {
1293
-			// lastInsertId() needs the prefix but no quotes
1294
-			$table = $this->prefixTableName($this->lastInsertedTable);
1295
-			return $this->connection->lastInsertId($table);
1296
-		}
1297
-
1298
-		throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.');
1299
-	}
1300
-
1301
-	/**
1302
-	 * Returns the table name quoted and with database prefix as needed by the implementation
1303
-	 *
1304
-	 * @param string|IQueryFunction $table
1305
-	 * @return string
1306
-	 */
1307
-	public function getTableName($table) {
1308
-		if ($table instanceof IQueryFunction) {
1309
-			return (string)$table;
1310
-		}
1311
-
1312
-		$table = $this->prefixTableName($table);
1313
-		return $this->helper->quoteColumnName($table);
1314
-	}
1315
-
1316
-	/**
1317
-	 * Returns the table name with database prefix as needed by the implementation
1318
-	 *
1319
-	 * Was protected until version 30.
1320
-	 *
1321
-	 * @param string $table
1322
-	 * @return string
1323
-	 */
1324
-	public function prefixTableName(string $table): string {
1325
-		if ($this->automaticTablePrefix === false || str_starts_with($table, '*PREFIX*')) {
1326
-			return $table;
1327
-		}
1328
-
1329
-		return '*PREFIX*' . $table;
1330
-	}
1331
-
1332
-	/**
1333
-	 * Returns the column name quoted and with table alias prefix as needed by the implementation
1334
-	 *
1335
-	 * @param string $column
1336
-	 * @param string $tableAlias
1337
-	 * @return string
1338
-	 */
1339
-	public function getColumnName($column, $tableAlias = '') {
1340
-		if ($tableAlias !== '') {
1341
-			$tableAlias .= '.';
1342
-		}
1343
-
1344
-		return $this->helper->quoteColumnName($tableAlias . $column);
1345
-	}
1346
-
1347
-	/**
1348
-	 * Returns the column name quoted and with table alias prefix as needed by the implementation
1349
-	 *
1350
-	 * @param string $alias
1351
-	 * @return string
1352
-	 */
1353
-	public function quoteAlias($alias) {
1354
-		if ($alias === '' || $alias === null) {
1355
-			return $alias;
1356
-		}
1357
-
1358
-		return $this->helper->quoteColumnName($alias);
1359
-	}
1360
-
1361
-	public function escapeLikeParameter(string $parameter): string {
1362
-		return $this->connection->escapeLikeParameter($parameter);
1363
-	}
1364
-
1365
-	public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self {
1366
-		return $this;
1367
-	}
1368
-
1369
-	public function runAcrossAllShards(): self {
1370
-		// noop
1371
-		return $this;
1372
-	}
31
+    /** @var ConnectionAdapter */
32
+    private $connection;
33
+
34
+    /** @var SystemConfig */
35
+    private $systemConfig;
36
+
37
+    private LoggerInterface $logger;
38
+
39
+    /** @var \Doctrine\DBAL\Query\QueryBuilder */
40
+    private $queryBuilder;
41
+
42
+    /** @var QuoteHelper */
43
+    private $helper;
44
+
45
+    /** @var bool */
46
+    private $automaticTablePrefix = true;
47
+    private bool $nonEmptyWhere = false;
48
+
49
+    /** @var string */
50
+    protected $lastInsertedTable;
51
+    private array $selectedColumns = [];
52
+
53
+    /**
54
+     * Initializes a new QueryBuilder.
55
+     *
56
+     * @param ConnectionAdapter $connection
57
+     * @param SystemConfig $systemConfig
58
+     */
59
+    public function __construct(ConnectionAdapter $connection, SystemConfig $systemConfig, LoggerInterface $logger) {
60
+        $this->connection = $connection;
61
+        $this->systemConfig = $systemConfig;
62
+        $this->logger = $logger;
63
+        $this->queryBuilder = new \Doctrine\DBAL\Query\QueryBuilder($this->connection->getInner());
64
+        $this->helper = new QuoteHelper();
65
+    }
66
+
67
+    /**
68
+     * Enable/disable automatic prefixing of table names with the oc_ prefix
69
+     *
70
+     * @param bool $enabled If set to true table names will be prefixed with the
71
+     *                      owncloud database prefix automatically.
72
+     * @since 8.2.0
73
+     */
74
+    public function automaticTablePrefix($enabled) {
75
+        $this->automaticTablePrefix = (bool)$enabled;
76
+    }
77
+
78
+    /**
79
+     * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
80
+     * This producer method is intended for convenient inline usage. Example:
81
+     *
82
+     * <code>
83
+     *     $qb = $conn->getQueryBuilder()
84
+     *         ->select('u')
85
+     *         ->from('users', 'u')
86
+     *         ->where($qb->expr()->eq('u.id', 1));
87
+     * </code>
88
+     *
89
+     * For more complex expression construction, consider storing the expression
90
+     * builder object in a local variable.
91
+     *
92
+     * @return \OCP\DB\QueryBuilder\IExpressionBuilder
93
+     */
94
+    public function expr() {
95
+        return match($this->connection->getDatabaseProvider()) {
96
+            IDBConnection::PLATFORM_ORACLE => new OCIExpressionBuilder($this->connection, $this, $this->logger),
97
+            IDBConnection::PLATFORM_POSTGRES => new PgSqlExpressionBuilder($this->connection, $this, $this->logger),
98
+            IDBConnection::PLATFORM_MARIADB,
99
+            IDBConnection::PLATFORM_MYSQL => new MySqlExpressionBuilder($this->connection, $this, $this->logger),
100
+            IDBConnection::PLATFORM_SQLITE => new SqliteExpressionBuilder($this->connection, $this, $this->logger),
101
+        };
102
+    }
103
+
104
+    /**
105
+     * Gets an FunctionBuilder used for object-oriented construction of query functions.
106
+     * This producer method is intended for convenient inline usage. Example:
107
+     *
108
+     * <code>
109
+     *     $qb = $conn->getQueryBuilder()
110
+     *         ->select('u')
111
+     *         ->from('users', 'u')
112
+     *         ->where($qb->fun()->md5('u.id'));
113
+     * </code>
114
+     *
115
+     * For more complex function construction, consider storing the function
116
+     * builder object in a local variable.
117
+     *
118
+     * @return \OCP\DB\QueryBuilder\IFunctionBuilder
119
+     */
120
+    public function func() {
121
+        return match($this->connection->getDatabaseProvider()) {
122
+            IDBConnection::PLATFORM_ORACLE => new OCIFunctionBuilder($this->connection, $this, $this->helper),
123
+            IDBConnection::PLATFORM_POSTGRES => new PgSqlFunctionBuilder($this->connection, $this, $this->helper),
124
+            IDBConnection::PLATFORM_MARIADB,
125
+            IDBConnection::PLATFORM_MYSQL => new FunctionBuilder($this->connection, $this, $this->helper),
126
+            IDBConnection::PLATFORM_SQLITE => new SqliteFunctionBuilder($this->connection, $this, $this->helper),
127
+        };
128
+    }
129
+
130
+    /**
131
+     * Gets the type of the currently built query.
132
+     *
133
+     * @return integer
134
+     */
135
+    public function getType() {
136
+        return $this->queryBuilder->getType();
137
+    }
138
+
139
+    /**
140
+     * Gets the associated DBAL Connection for this query builder.
141
+     *
142
+     * @return \OCP\IDBConnection
143
+     */
144
+    public function getConnection() {
145
+        return $this->connection;
146
+    }
147
+
148
+    /**
149
+     * Gets the state of this query builder instance.
150
+     *
151
+     * @return int Always returns 0 which is former `QueryBuilder::STATE_DIRTY`
152
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
153
+     *    and we can not fix this in our wrapper.
154
+     */
155
+    public function getState() {
156
+        $this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
157
+        return $this->queryBuilder->getState();
158
+    }
159
+
160
+    private function prepareForExecute() {
161
+        if ($this->systemConfig->getValue('log_query', false)) {
162
+            try {
163
+                $params = [];
164
+                foreach ($this->getParameters() as $placeholder => $value) {
165
+                    if ($value instanceof \DateTimeInterface) {
166
+                        $params[] = $placeholder . ' => DateTime:\'' . $value->format('c') . '\'';
167
+                    } elseif (is_array($value)) {
168
+                        $params[] = $placeholder . ' => (\'' . implode('\', \'', $value) . '\')';
169
+                    } else {
170
+                        $params[] = $placeholder . ' => \'' . $value . '\'';
171
+                    }
172
+                }
173
+                if (empty($params)) {
174
+                    $this->logger->debug('DB QueryBuilder: \'{query}\'', [
175
+                        'query' => $this->getSQL(),
176
+                        'app' => 'core',
177
+                    ]);
178
+                } else {
179
+                    $this->logger->debug('DB QueryBuilder: \'{query}\' with parameters: {params}', [
180
+                        'query' => $this->getSQL(),
181
+                        'params' => implode(', ', $params),
182
+                        'app' => 'core',
183
+                    ]);
184
+                }
185
+            } catch (\Error $e) {
186
+                // likely an error during conversion of $value to string
187
+                $this->logger->error('DB QueryBuilder: error trying to log SQL query', ['exception' => $e]);
188
+            }
189
+        }
190
+
191
+        // if (!empty($this->getQueryPart('select'))) {
192
+        // $select = $this->getQueryPart('select');
193
+        // $hasSelectAll = array_filter($select, static function ($s) {
194
+        // return $s === '*';
195
+        // });
196
+        // $hasSelectSpecific = array_filter($select, static function ($s) {
197
+        // return $s !== '*';
198
+        // });
199
+
200
+        // if (empty($hasSelectAll) === empty($hasSelectSpecific)) {
201
+        // $exception = new QueryException('Query is selecting * and specific values in the same query. This is not supported in Oracle.');
202
+        // $this->logger->error($exception->getMessage(), [
203
+        // 'query' => $this->getSQL(),
204
+        // 'app' => 'core',
205
+        // 'exception' => $exception,
206
+        // ]);
207
+        // }
208
+        // }
209
+
210
+        $tooLongOutputColumns = [];
211
+        foreach ($this->getOutputColumns() as $column) {
212
+            if (strlen($column) > 30) {
213
+                $tooLongOutputColumns[] = $column;
214
+            }
215
+        }
216
+
217
+        if (!empty($tooLongOutputColumns)) {
218
+            $exception = new QueryException('More than 30 characters for an output column name are not allowed on Oracle.');
219
+            $this->logger->error($exception->getMessage(), [
220
+                'query' => $this->getSQL(),
221
+                'columns' => $tooLongOutputColumns,
222
+                'app' => 'core',
223
+                'exception' => $exception,
224
+            ]);
225
+        }
226
+
227
+        $numberOfParameters = 0;
228
+        $hasTooLargeArrayParameter = false;
229
+        foreach ($this->getParameters() as $parameter) {
230
+            if (is_array($parameter)) {
231
+                $count = count($parameter);
232
+                $numberOfParameters += $count;
233
+                $hasTooLargeArrayParameter = $hasTooLargeArrayParameter || ($count > 1000);
234
+            }
235
+        }
236
+
237
+        if ($hasTooLargeArrayParameter) {
238
+            $exception = new QueryException('More than 1000 expressions in a list are not allowed on Oracle.');
239
+            $this->logger->error($exception->getMessage(), [
240
+                'query' => $this->getSQL(),
241
+                'app' => 'core',
242
+                'exception' => $exception,
243
+            ]);
244
+        }
245
+
246
+        if ($numberOfParameters > 65535) {
247
+            $exception = new QueryException('The number of parameters must not exceed 65535. Restriction by PostgreSQL.');
248
+            $this->logger->error($exception->getMessage(), [
249
+                'query' => $this->getSQL(),
250
+                'app' => 'core',
251
+                'exception' => $exception,
252
+            ]);
253
+        }
254
+    }
255
+
256
+    public function executeQuery(?IDBConnection $connection = null): IResult {
257
+        if ($this->getType() !== \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
258
+            throw new \RuntimeException('Invalid query type, expected SELECT query');
259
+        }
260
+
261
+        $this->prepareForExecute();
262
+        if (!$connection) {
263
+            $connection = $this->connection;
264
+        }
265
+
266
+        return $connection->executeQuery(
267
+            $this->getSQL(),
268
+            $this->getParameters(),
269
+            $this->getParameterTypes(),
270
+        );
271
+    }
272
+
273
+    public function executeStatement(?IDBConnection $connection = null): int {
274
+        if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
275
+            throw new \RuntimeException('Invalid query type, expected INSERT, DELETE or UPDATE statement');
276
+        }
277
+
278
+        $this->prepareForExecute();
279
+        if (!$connection) {
280
+            $connection = $this->connection;
281
+        }
282
+
283
+        return $connection->executeStatement(
284
+            $this->getSQL(),
285
+            $this->getParameters(),
286
+            $this->getParameterTypes(),
287
+        );
288
+    }
289
+
290
+
291
+    /**
292
+     * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
293
+     *
294
+     * <code>
295
+     *     $qb = $conn->getQueryBuilder()
296
+     *         ->select('u')
297
+     *         ->from('User', 'u')
298
+     *     echo $qb->getSQL(); // SELECT u FROM User u
299
+     * </code>
300
+     *
301
+     * @return string The SQL query string.
302
+     */
303
+    public function getSQL() {
304
+        return $this->queryBuilder->getSQL();
305
+    }
306
+
307
+    /**
308
+     * Sets a query parameter for the query being constructed.
309
+     *
310
+     * <code>
311
+     *     $qb = $conn->getQueryBuilder()
312
+     *         ->select('u')
313
+     *         ->from('users', 'u')
314
+     *         ->where('u.id = :user_id')
315
+     *         ->setParameter(':user_id', 1);
316
+     * </code>
317
+     *
318
+     * @param string|integer $key The parameter position or name.
319
+     * @param mixed $value The parameter value.
320
+     * @param string|null|int $type One of the IQueryBuilder::PARAM_* constants.
321
+     *
322
+     * @return $this This QueryBuilder instance.
323
+     */
324
+    public function setParameter($key, $value, $type = null) {
325
+        $this->queryBuilder->setParameter($key, $value, $type);
326
+
327
+        return $this;
328
+    }
329
+
330
+    /**
331
+     * Sets a collection of query parameters for the query being constructed.
332
+     *
333
+     * <code>
334
+     *     $qb = $conn->getQueryBuilder()
335
+     *         ->select('u')
336
+     *         ->from('users', 'u')
337
+     *         ->where('u.id = :user_id1 OR u.id = :user_id2')
338
+     *         ->setParameters(array(
339
+     *             ':user_id1' => 1,
340
+     *             ':user_id2' => 2
341
+     *         ));
342
+     * </code>
343
+     *
344
+     * @param array $params The query parameters to set.
345
+     * @param array $types The query parameters types to set.
346
+     *
347
+     * @return $this This QueryBuilder instance.
348
+     */
349
+    public function setParameters(array $params, array $types = []) {
350
+        $this->queryBuilder->setParameters($params, $types);
351
+
352
+        return $this;
353
+    }
354
+
355
+    /**
356
+     * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
357
+     *
358
+     * @return array The currently defined query parameters indexed by parameter index or name.
359
+     */
360
+    public function getParameters() {
361
+        return $this->queryBuilder->getParameters();
362
+    }
363
+
364
+    /**
365
+     * Gets a (previously set) query parameter of the query being constructed.
366
+     *
367
+     * @param mixed $key The key (index or name) of the bound parameter.
368
+     *
369
+     * @return mixed The value of the bound parameter.
370
+     */
371
+    public function getParameter($key) {
372
+        return $this->queryBuilder->getParameter($key);
373
+    }
374
+
375
+    /**
376
+     * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
377
+     *
378
+     * @return array The currently defined query parameter types indexed by parameter index or name.
379
+     */
380
+    public function getParameterTypes() {
381
+        return $this->queryBuilder->getParameterTypes();
382
+    }
383
+
384
+    /**
385
+     * Gets a (previously set) query parameter type of the query being constructed.
386
+     *
387
+     * @param mixed $key The key (index or name) of the bound parameter type.
388
+     *
389
+     * @return mixed The value of the bound parameter type.
390
+     */
391
+    public function getParameterType($key) {
392
+        return $this->queryBuilder->getParameterType($key);
393
+    }
394
+
395
+    /**
396
+     * Sets the position of the first result to retrieve (the "offset").
397
+     *
398
+     * @param int $firstResult The first result to return.
399
+     *
400
+     * @return $this This QueryBuilder instance.
401
+     */
402
+    public function setFirstResult($firstResult) {
403
+        $this->queryBuilder->setFirstResult((int)$firstResult);
404
+
405
+        return $this;
406
+    }
407
+
408
+    /**
409
+     * Gets the position of the first result the query object was set to retrieve (the "offset").
410
+     * Returns 0 if {@link setFirstResult} was not applied to this QueryBuilder.
411
+     *
412
+     * @return int The position of the first result.
413
+     */
414
+    public function getFirstResult() {
415
+        return $this->queryBuilder->getFirstResult();
416
+    }
417
+
418
+    /**
419
+     * Sets the maximum number of results to retrieve (the "limit").
420
+     *
421
+     * NOTE: Setting max results to "0" will cause mixed behaviour. While most
422
+     * of the databases will just return an empty result set, Oracle will return
423
+     * all entries.
424
+     *
425
+     * @param int|null $maxResults The maximum number of results to retrieve.
426
+     *
427
+     * @return $this This QueryBuilder instance.
428
+     */
429
+    public function setMaxResults($maxResults) {
430
+        if ($maxResults === null) {
431
+            $this->queryBuilder->setMaxResults($maxResults);
432
+        } else {
433
+            $this->queryBuilder->setMaxResults((int)$maxResults);
434
+        }
435
+
436
+        return $this;
437
+    }
438
+
439
+    /**
440
+     * Gets the maximum number of results the query object was set to retrieve (the "limit").
441
+     * Returns NULL if {@link setMaxResults} was not applied to this query builder.
442
+     *
443
+     * @return int|null The maximum number of results.
444
+     */
445
+    public function getMaxResults() {
446
+        return $this->queryBuilder->getMaxResults();
447
+    }
448
+
449
+    /**
450
+     * Specifies an item that is to be returned in the query result.
451
+     * Replaces any previously specified selections, if any.
452
+     *
453
+     * <code>
454
+     *     $qb = $conn->getQueryBuilder()
455
+     *         ->select('u.id', 'p.id')
456
+     *         ->from('users', 'u')
457
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
458
+     * </code>
459
+     *
460
+     * @param mixed ...$selects The selection expressions.
461
+     *
462
+     * '@return $this This QueryBuilder instance.
463
+     */
464
+    public function select(...$selects) {
465
+        if (count($selects) === 1 && is_array($selects[0])) {
466
+            $selects = $selects[0];
467
+        }
468
+        $this->addOutputColumns($selects);
469
+
470
+        $this->queryBuilder->select(
471
+            $this->helper->quoteColumnNames($selects)
472
+        );
473
+
474
+        return $this;
475
+    }
476
+
477
+    /**
478
+     * Specifies an item that is to be returned with a different name in the query result.
479
+     *
480
+     * <code>
481
+     *     $qb = $conn->getQueryBuilder()
482
+     *         ->selectAlias('u.id', 'user_id')
483
+     *         ->from('users', 'u')
484
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
485
+     * </code>
486
+     *
487
+     * @param mixed $select The selection expressions.
488
+     * @param string $alias The column alias used in the constructed query.
489
+     *
490
+     * @return $this This QueryBuilder instance.
491
+     */
492
+    public function selectAlias($select, $alias) {
493
+        $this->queryBuilder->addSelect(
494
+            $this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
495
+        );
496
+        $this->addOutputColumns([$alias]);
497
+
498
+        return $this;
499
+    }
500
+
501
+    /**
502
+     * Specifies an item that is to be returned uniquely in the query result.
503
+     *
504
+     * <code>
505
+     *     $qb = $conn->getQueryBuilder()
506
+     *         ->selectDistinct('type')
507
+     *         ->from('users');
508
+     * </code>
509
+     *
510
+     * @param mixed $select The selection expressions.
511
+     *
512
+     * @return $this This QueryBuilder instance.
513
+     */
514
+    public function selectDistinct($select) {
515
+        if (!is_array($select)) {
516
+            $select = [$select];
517
+        }
518
+        $this->addOutputColumns($select);
519
+
520
+        $quotedSelect = $this->helper->quoteColumnNames($select);
521
+
522
+        $this->queryBuilder->addSelect(
523
+            'DISTINCT ' . implode(', ', $quotedSelect)
524
+        );
525
+
526
+        return $this;
527
+    }
528
+
529
+    /**
530
+     * Adds an item that is to be returned in the query result.
531
+     *
532
+     * <code>
533
+     *     $qb = $conn->getQueryBuilder()
534
+     *         ->select('u.id')
535
+     *         ->addSelect('p.id')
536
+     *         ->from('users', 'u')
537
+     *         ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
538
+     * </code>
539
+     *
540
+     * @param mixed ...$selects The selection expression.
541
+     *
542
+     * @return $this This QueryBuilder instance.
543
+     */
544
+    public function addSelect(...$selects) {
545
+        if (count($selects) === 1 && is_array($selects[0])) {
546
+            $selects = $selects[0];
547
+        }
548
+        $this->addOutputColumns($selects);
549
+
550
+        $this->queryBuilder->addSelect(
551
+            $this->helper->quoteColumnNames($selects)
552
+        );
553
+
554
+        return $this;
555
+    }
556
+
557
+    private function addOutputColumns(array $columns): void {
558
+        foreach ($columns as $column) {
559
+            if (is_array($column)) {
560
+                $this->addOutputColumns($column);
561
+            } elseif (is_string($column) && !str_contains($column, '*')) {
562
+                if (str_contains(strtolower($column), ' as ')) {
563
+                    [, $column] = preg_split('/ as /i', $column);
564
+                }
565
+                if (str_contains($column, '.')) {
566
+                    [, $column] = explode('.', $column);
567
+                }
568
+                $this->selectedColumns[] = $column;
569
+            }
570
+        }
571
+    }
572
+
573
+    public function getOutputColumns(): array {
574
+        return array_unique($this->selectedColumns);
575
+    }
576
+
577
+    /**
578
+     * Turns the query being built into a bulk delete query that ranges over
579
+     * a certain table.
580
+     *
581
+     * <code>
582
+     *     $qb = $conn->getQueryBuilder()
583
+     *         ->delete('users', 'u')
584
+     *         ->where('u.id = :user_id');
585
+     *         ->setParameter(':user_id', 1);
586
+     * </code>
587
+     *
588
+     * @param string $delete The table whose rows are subject to the deletion.
589
+     * @param string $alias The table alias used in the constructed query.
590
+     *
591
+     * @return $this This QueryBuilder instance.
592
+     * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
593
+     */
594
+    public function delete($delete = null, $alias = null) {
595
+        if ($alias !== null) {
596
+            $this->logger->debug('DELETE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for DELETE query')]);
597
+        }
598
+
599
+        $this->queryBuilder->delete(
600
+            $this->getTableName($delete),
601
+            $alias
602
+        );
603
+
604
+        return $this;
605
+    }
606
+
607
+    /**
608
+     * Turns the query being built into a bulk update query that ranges over
609
+     * a certain table
610
+     *
611
+     * <code>
612
+     *     $qb = $conn->getQueryBuilder()
613
+     *         ->update('users', 'u')
614
+     *         ->set('u.password', md5('password'))
615
+     *         ->where('u.id = ?');
616
+     * </code>
617
+     *
618
+     * @param string $update The table whose rows are subject to the update.
619
+     * @param string $alias The table alias used in the constructed query.
620
+     *
621
+     * @return $this This QueryBuilder instance.
622
+     * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update
623
+     */
624
+    public function update($update = null, $alias = null) {
625
+        if ($alias !== null) {
626
+            $this->logger->debug('UPDATE queries with alias are no longer supported and the provided alias is ignored', ['exception' => new \InvalidArgumentException('Table alias provided for UPDATE query')]);
627
+        }
628
+
629
+        $this->queryBuilder->update(
630
+            $this->getTableName($update),
631
+            $alias
632
+        );
633
+
634
+        return $this;
635
+    }
636
+
637
+    /**
638
+     * Turns the query being built into an insert query that inserts into
639
+     * a certain table
640
+     *
641
+     * <code>
642
+     *     $qb = $conn->getQueryBuilder()
643
+     *         ->insert('users')
644
+     *         ->values(
645
+     *             array(
646
+     *                 'name' => '?',
647
+     *                 'password' => '?'
648
+     *             )
649
+     *         );
650
+     * </code>
651
+     *
652
+     * @param string $insert The table into which the rows should be inserted.
653
+     *
654
+     * @return $this This QueryBuilder instance.
655
+     */
656
+    public function insert($insert = null) {
657
+        $this->queryBuilder->insert(
658
+            $this->getTableName($insert)
659
+        );
660
+
661
+        $this->lastInsertedTable = $insert;
662
+
663
+        return $this;
664
+    }
665
+
666
+    /**
667
+     * Creates and adds a query root corresponding to the table identified by the
668
+     * given alias, forming a cartesian product with any existing query roots.
669
+     *
670
+     * <code>
671
+     *     $qb = $conn->getQueryBuilder()
672
+     *         ->select('u.id')
673
+     *         ->from('users', 'u')
674
+     * </code>
675
+     *
676
+     * @param string|IQueryFunction $from The table.
677
+     * @param string|null $alias The alias of the table.
678
+     *
679
+     * @return $this This QueryBuilder instance.
680
+     */
681
+    public function from($from, $alias = null) {
682
+        $this->queryBuilder->from(
683
+            $this->getTableName($from),
684
+            $this->quoteAlias($alias)
685
+        );
686
+
687
+        return $this;
688
+    }
689
+
690
+    /**
691
+     * Creates and adds a join to the query.
692
+     *
693
+     * <code>
694
+     *     $qb = $conn->getQueryBuilder()
695
+     *         ->select('u.name')
696
+     *         ->from('users', 'u')
697
+     *         ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
698
+     * </code>
699
+     *
700
+     * @param string $fromAlias The alias that points to a from clause.
701
+     * @param string $join The table name to join.
702
+     * @param string $alias The alias of the join table.
703
+     * @param string|ICompositeExpression|null $condition The condition for the join.
704
+     *
705
+     * @return $this This QueryBuilder instance.
706
+     */
707
+    public function join($fromAlias, $join, $alias, $condition = null) {
708
+        $this->queryBuilder->join(
709
+            $this->quoteAlias($fromAlias),
710
+            $this->getTableName($join),
711
+            $this->quoteAlias($alias),
712
+            $condition
713
+        );
714
+
715
+        return $this;
716
+    }
717
+
718
+    /**
719
+     * Creates and adds a join to the query.
720
+     *
721
+     * <code>
722
+     *     $qb = $conn->getQueryBuilder()
723
+     *         ->select('u.name')
724
+     *         ->from('users', 'u')
725
+     *         ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
726
+     * </code>
727
+     *
728
+     * @param string $fromAlias The alias that points to a from clause.
729
+     * @param string $join The table name to join.
730
+     * @param string $alias The alias of the join table.
731
+     * @param string|ICompositeExpression|null $condition The condition for the join.
732
+     *
733
+     * @return $this This QueryBuilder instance.
734
+     */
735
+    public function innerJoin($fromAlias, $join, $alias, $condition = null) {
736
+        $this->queryBuilder->innerJoin(
737
+            $this->quoteAlias($fromAlias),
738
+            $this->getTableName($join),
739
+            $this->quoteAlias($alias),
740
+            $condition
741
+        );
742
+
743
+        return $this;
744
+    }
745
+
746
+    /**
747
+     * Creates and adds a left join to the query.
748
+     *
749
+     * <code>
750
+     *     $qb = $conn->getQueryBuilder()
751
+     *         ->select('u.name')
752
+     *         ->from('users', 'u')
753
+     *         ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
754
+     * </code>
755
+     *
756
+     * @param string $fromAlias The alias that points to a from clause.
757
+     * @param string|IQueryFunction $join The table name or sub-query to join.
758
+     * @param string $alias The alias of the join table.
759
+     * @param string|ICompositeExpression|null $condition The condition for the join.
760
+     *
761
+     * @return $this This QueryBuilder instance.
762
+     */
763
+    public function leftJoin($fromAlias, $join, $alias, $condition = null) {
764
+        $this->queryBuilder->leftJoin(
765
+            $this->quoteAlias($fromAlias),
766
+            $this->getTableName($join),
767
+            $this->quoteAlias($alias),
768
+            $condition
769
+        );
770
+
771
+        return $this;
772
+    }
773
+
774
+    /**
775
+     * Creates and adds a right join to the query.
776
+     *
777
+     * <code>
778
+     *     $qb = $conn->getQueryBuilder()
779
+     *         ->select('u.name')
780
+     *         ->from('users', 'u')
781
+     *         ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
782
+     * </code>
783
+     *
784
+     * @param string $fromAlias The alias that points to a from clause.
785
+     * @param string $join The table name to join.
786
+     * @param string $alias The alias of the join table.
787
+     * @param string|ICompositeExpression|null $condition The condition for the join.
788
+     *
789
+     * @return $this This QueryBuilder instance.
790
+     */
791
+    public function rightJoin($fromAlias, $join, $alias, $condition = null) {
792
+        $this->queryBuilder->rightJoin(
793
+            $this->quoteAlias($fromAlias),
794
+            $this->getTableName($join),
795
+            $this->quoteAlias($alias),
796
+            $condition
797
+        );
798
+
799
+        return $this;
800
+    }
801
+
802
+    /**
803
+     * Sets a new value for a column in a bulk update query.
804
+     *
805
+     * <code>
806
+     *     $qb = $conn->getQueryBuilder()
807
+     *         ->update('users', 'u')
808
+     *         ->set('u.password', md5('password'))
809
+     *         ->where('u.id = ?');
810
+     * </code>
811
+     *
812
+     * @param string $key The column to set.
813
+     * @param ILiteral|IParameter|IQueryFunction|string $value The value, expression, placeholder, etc.
814
+     *
815
+     * @return $this This QueryBuilder instance.
816
+     */
817
+    public function set($key, $value) {
818
+        $this->queryBuilder->set(
819
+            $this->helper->quoteColumnName($key),
820
+            $this->helper->quoteColumnName($value)
821
+        );
822
+
823
+        return $this;
824
+    }
825
+
826
+    /**
827
+     * Specifies one or more restrictions to the query result.
828
+     * Replaces any previously specified restrictions, if any.
829
+     *
830
+     * <code>
831
+     *     $qb = $conn->getQueryBuilder()
832
+     *         ->select('u.name')
833
+     *         ->from('users', 'u')
834
+     *         ->where('u.id = ?');
835
+     *
836
+     *     // You can optionally programmatically build and/or expressions
837
+     *     $qb = $conn->getQueryBuilder();
838
+     *
839
+     *     $or = $qb->expr()->orx(
840
+     *         $qb->expr()->eq('u.id', 1),
841
+     *         $qb->expr()->eq('u.id', 2),
842
+     *     );
843
+     *
844
+     *     $qb->update('users', 'u')
845
+     *         ->set('u.password', md5('password'))
846
+     *         ->where($or);
847
+     * </code>
848
+     *
849
+     * @param mixed ...$predicates The restriction predicates.
850
+     *
851
+     * @return $this This QueryBuilder instance.
852
+     */
853
+    public function where(...$predicates) {
854
+        if ($this->nonEmptyWhere && $this->systemConfig->getValue('debug', false)) {
855
+            // Only logging a warning, not throwing for now.
856
+            $e = new QueryException('Using where() on non-empty WHERE part, please verify it is intentional to not call andWhere() or orWhere() instead. Otherwise consider creating a new query builder object or call resetQueryPart(\'where\') first.');
857
+            $this->logger->warning($e->getMessage(), ['exception' => $e]);
858
+        }
859
+
860
+        $this->nonEmptyWhere = true;
861
+
862
+        call_user_func_array(
863
+            [$this->queryBuilder, 'where'],
864
+            $predicates
865
+        );
866
+
867
+        return $this;
868
+    }
869
+
870
+    /**
871
+     * Adds one or more restrictions to the query results, forming a logical
872
+     * conjunction with any previously specified restrictions.
873
+     *
874
+     * <code>
875
+     *     $qb = $conn->getQueryBuilder()
876
+     *         ->select('u')
877
+     *         ->from('users', 'u')
878
+     *         ->where('u.username LIKE ?')
879
+     *         ->andWhere('u.is_active = 1');
880
+     * </code>
881
+     *
882
+     * @param mixed ...$where The query restrictions.
883
+     *
884
+     * @return $this This QueryBuilder instance.
885
+     *
886
+     * @see where()
887
+     */
888
+    public function andWhere(...$where) {
889
+        $this->nonEmptyWhere = true;
890
+        call_user_func_array(
891
+            [$this->queryBuilder, 'andWhere'],
892
+            $where
893
+        );
894
+
895
+        return $this;
896
+    }
897
+
898
+    /**
899
+     * Adds one or more restrictions to the query results, forming a logical
900
+     * disjunction with any previously specified restrictions.
901
+     *
902
+     * <code>
903
+     *     $qb = $conn->getQueryBuilder()
904
+     *         ->select('u.name')
905
+     *         ->from('users', 'u')
906
+     *         ->where('u.id = 1')
907
+     *         ->orWhere('u.id = 2');
908
+     * </code>
909
+     *
910
+     * @param mixed ...$where The WHERE statement.
911
+     *
912
+     * @return $this This QueryBuilder instance.
913
+     *
914
+     * @see where()
915
+     */
916
+    public function orWhere(...$where) {
917
+        $this->nonEmptyWhere = true;
918
+        call_user_func_array(
919
+            [$this->queryBuilder, 'orWhere'],
920
+            $where
921
+        );
922
+
923
+        return $this;
924
+    }
925
+
926
+    /**
927
+     * Specifies a grouping over the results of the query.
928
+     * Replaces any previously specified groupings, if any.
929
+     *
930
+     * <code>
931
+     *     $qb = $conn->getQueryBuilder()
932
+     *         ->select('u.name')
933
+     *         ->from('users', 'u')
934
+     *         ->groupBy('u.id');
935
+     * </code>
936
+     *
937
+     * @param mixed ...$groupBys The grouping expression.
938
+     *
939
+     * @return $this This QueryBuilder instance.
940
+     */
941
+    public function groupBy(...$groupBys) {
942
+        if (count($groupBys) === 1 && is_array($groupBys[0])) {
943
+            $groupBys = $groupBys[0];
944
+        }
945
+
946
+        call_user_func_array(
947
+            [$this->queryBuilder, 'groupBy'],
948
+            $this->helper->quoteColumnNames($groupBys)
949
+        );
950
+
951
+        return $this;
952
+    }
953
+
954
+    /**
955
+     * Adds a grouping expression to the query.
956
+     *
957
+     * <code>
958
+     *     $qb = $conn->getQueryBuilder()
959
+     *         ->select('u.name')
960
+     *         ->from('users', 'u')
961
+     *         ->groupBy('u.lastLogin');
962
+     *         ->addGroupBy('u.createdAt')
963
+     * </code>
964
+     *
965
+     * @param mixed ...$groupBy The grouping expression.
966
+     *
967
+     * @return $this This QueryBuilder instance.
968
+     */
969
+    public function addGroupBy(...$groupBy) {
970
+        call_user_func_array(
971
+            [$this->queryBuilder, 'addGroupBy'],
972
+            $this->helper->quoteColumnNames($groupBy)
973
+        );
974
+
975
+        return $this;
976
+    }
977
+
978
+    /**
979
+     * Sets a value for a column in an insert query.
980
+     *
981
+     * <code>
982
+     *     $qb = $conn->getQueryBuilder()
983
+     *         ->insert('users')
984
+     *         ->values(
985
+     *             array(
986
+     *                 'name' => '?'
987
+     *             )
988
+     *         )
989
+     *         ->setValue('password', '?');
990
+     * </code>
991
+     *
992
+     * @param string $column The column into which the value should be inserted.
993
+     * @param IParameter|string $value The value that should be inserted into the column.
994
+     *
995
+     * @return $this This QueryBuilder instance.
996
+     */
997
+    public function setValue($column, $value) {
998
+        $this->queryBuilder->setValue(
999
+            $this->helper->quoteColumnName($column),
1000
+            (string)$value
1001
+        );
1002
+
1003
+        return $this;
1004
+    }
1005
+
1006
+    /**
1007
+     * Specifies values for an insert query indexed by column names.
1008
+     * Replaces any previous values, if any.
1009
+     *
1010
+     * <code>
1011
+     *     $qb = $conn->getQueryBuilder()
1012
+     *         ->insert('users')
1013
+     *         ->values(
1014
+     *             array(
1015
+     *                 'name' => '?',
1016
+     *                 'password' => '?'
1017
+     *             )
1018
+     *         );
1019
+     * </code>
1020
+     *
1021
+     * @param array $values The values to specify for the insert query indexed by column names.
1022
+     *
1023
+     * @return $this This QueryBuilder instance.
1024
+     */
1025
+    public function values(array $values) {
1026
+        $quotedValues = [];
1027
+        foreach ($values as $key => $value) {
1028
+            $quotedValues[$this->helper->quoteColumnName($key)] = $value;
1029
+        }
1030
+
1031
+        $this->queryBuilder->values($quotedValues);
1032
+
1033
+        return $this;
1034
+    }
1035
+
1036
+    /**
1037
+     * Specifies a restriction over the groups of the query.
1038
+     * Replaces any previous having restrictions, if any.
1039
+     *
1040
+     * @param mixed ...$having The restriction over the groups.
1041
+     *
1042
+     * @return $this This QueryBuilder instance.
1043
+     */
1044
+    public function having(...$having) {
1045
+        call_user_func_array(
1046
+            [$this->queryBuilder, 'having'],
1047
+            $having
1048
+        );
1049
+
1050
+        return $this;
1051
+    }
1052
+
1053
+    /**
1054
+     * Adds a restriction over the groups of the query, forming a logical
1055
+     * conjunction with any existing having restrictions.
1056
+     *
1057
+     * @param mixed ...$having The restriction to append.
1058
+     *
1059
+     * @return $this This QueryBuilder instance.
1060
+     */
1061
+    public function andHaving(...$having) {
1062
+        call_user_func_array(
1063
+            [$this->queryBuilder, 'andHaving'],
1064
+            $having
1065
+        );
1066
+
1067
+        return $this;
1068
+    }
1069
+
1070
+    /**
1071
+     * Adds a restriction over the groups of the query, forming a logical
1072
+     * disjunction with any existing having restrictions.
1073
+     *
1074
+     * @param mixed ...$having The restriction to add.
1075
+     *
1076
+     * @return $this This QueryBuilder instance.
1077
+     */
1078
+    public function orHaving(...$having) {
1079
+        call_user_func_array(
1080
+            [$this->queryBuilder, 'orHaving'],
1081
+            $having
1082
+        );
1083
+
1084
+        return $this;
1085
+    }
1086
+
1087
+    /**
1088
+     * Specifies an ordering for the query results.
1089
+     * Replaces any previously specified orderings, if any.
1090
+     *
1091
+     * @param string|IQueryFunction|ILiteral|IParameter $sort The ordering expression.
1092
+     * @param string $order The ordering direction.
1093
+     *
1094
+     * @return $this This QueryBuilder instance.
1095
+     */
1096
+    public function orderBy($sort, $order = null) {
1097
+        $this->queryBuilder->orderBy(
1098
+            $this->helper->quoteColumnName($sort),
1099
+            $order
1100
+        );
1101
+
1102
+        return $this;
1103
+    }
1104
+
1105
+    /**
1106
+     * Adds an ordering to the query results.
1107
+     *
1108
+     * @param string|ILiteral|IParameter|IQueryFunction $sort The ordering expression.
1109
+     * @param string $order The ordering direction.
1110
+     *
1111
+     * @return $this This QueryBuilder instance.
1112
+     */
1113
+    public function addOrderBy($sort, $order = null) {
1114
+        $this->queryBuilder->addOrderBy(
1115
+            $this->helper->quoteColumnName($sort),
1116
+            $order
1117
+        );
1118
+
1119
+        return $this;
1120
+    }
1121
+
1122
+    /**
1123
+     * Gets a query part by its name.
1124
+     *
1125
+     * @param string $queryPartName
1126
+     *
1127
+     * @return mixed
1128
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1129
+     *   and we can not fix this in our wrapper. Please track the details you need, outside the object.
1130
+     */
1131
+    public function getQueryPart($queryPartName) {
1132
+        $this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1133
+        return $this->queryBuilder->getQueryPart($queryPartName);
1134
+    }
1135
+
1136
+    /**
1137
+     * Gets all query parts.
1138
+     *
1139
+     * @return array
1140
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1141
+     *   and we can not fix this in our wrapper. Please track the details you need, outside the object.
1142
+     */
1143
+    public function getQueryParts() {
1144
+        $this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1145
+        return $this->queryBuilder->getQueryParts();
1146
+    }
1147
+
1148
+    /**
1149
+     * Resets SQL parts.
1150
+     *
1151
+     * @param array|null $queryPartNames
1152
+     *
1153
+     * @return $this This QueryBuilder instance.
1154
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1155
+     *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
1156
+     */
1157
+    public function resetQueryParts($queryPartNames = null) {
1158
+        $this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1159
+        $this->queryBuilder->resetQueryParts($queryPartNames);
1160
+
1161
+        return $this;
1162
+    }
1163
+
1164
+    /**
1165
+     * Resets a single SQL part.
1166
+     *
1167
+     * @param string $queryPartName
1168
+     *
1169
+     * @return $this This QueryBuilder instance.
1170
+     * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update
1171
+     *  and we can not fix this in our wrapper. Please create a new IQueryBuilder instead.
1172
+     */
1173
+    public function resetQueryPart($queryPartName) {
1174
+        $this->logger->debug(IQueryBuilder::class . '::' . __FUNCTION__ . ' is deprecated and will be removed soon.', ['exception' => new \Exception('Deprecated call to ' . __METHOD__)]);
1175
+        $this->queryBuilder->resetQueryPart($queryPartName);
1176
+
1177
+        return $this;
1178
+    }
1179
+
1180
+    /**
1181
+     * Creates a new named parameter and bind the value $value to it.
1182
+     *
1183
+     * This method provides a shortcut for PDOStatement::bindValue
1184
+     * when using prepared statements.
1185
+     *
1186
+     * The parameter $value specifies the value that you want to bind. If
1187
+     * $placeholder is not provided bindValue() will automatically create a
1188
+     * placeholder for you. An automatic placeholder will be of the name
1189
+     * ':dcValue1', ':dcValue2' etc.
1190
+     *
1191
+     * For more information see {@link https://www.php.net/pdostatement-bindparam}
1192
+     *
1193
+     * Example:
1194
+     * <code>
1195
+     * $value = 2;
1196
+     * $q->eq( 'id', $q->bindValue( $value ) );
1197
+     * $stmt = $q->executeQuery(); // executed with 'id = 2'
1198
+     * </code>
1199
+     *
1200
+     * @license New BSD License
1201
+     * @link http://www.zetacomponents.org
1202
+     *
1203
+     * @param mixed $value
1204
+     * @param IQueryBuilder::PARAM_* $type
1205
+     * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
1206
+     *
1207
+     * @return IParameter the placeholder name used.
1208
+     */
1209
+    public function createNamedParameter($value, $type = IQueryBuilder::PARAM_STR, $placeHolder = null) {
1210
+        return new Parameter($this->queryBuilder->createNamedParameter($value, $type, $placeHolder));
1211
+    }
1212
+
1213
+    /**
1214
+     * Creates a new positional parameter and bind the given value to it.
1215
+     *
1216
+     * Attention: If you are using positional parameters with the query builder you have
1217
+     * to be very careful to bind all parameters in the order they appear in the SQL
1218
+     * statement , otherwise they get bound in the wrong order which can lead to serious
1219
+     * bugs in your code.
1220
+     *
1221
+     * Example:
1222
+     * <code>
1223
+     *  $qb = $conn->getQueryBuilder();
1224
+     *  $qb->select('u.*')
1225
+     *     ->from('users', 'u')
1226
+     *     ->where('u.username = ' . $qb->createPositionalParameter('Foo', IQueryBuilder::PARAM_STR))
1227
+     *     ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', IQueryBuilder::PARAM_STR))
1228
+     * </code>
1229
+     *
1230
+     * @param mixed $value
1231
+     * @param IQueryBuilder::PARAM_* $type
1232
+     *
1233
+     * @return IParameter
1234
+     */
1235
+    public function createPositionalParameter($value, $type = IQueryBuilder::PARAM_STR) {
1236
+        return new Parameter($this->queryBuilder->createPositionalParameter($value, $type));
1237
+    }
1238
+
1239
+    /**
1240
+     * Creates a new parameter
1241
+     *
1242
+     * Example:
1243
+     * <code>
1244
+     *  $qb = $conn->getQueryBuilder();
1245
+     *  $qb->select('u.*')
1246
+     *     ->from('users', 'u')
1247
+     *     ->where('u.username = ' . $qb->createParameter('name'))
1248
+     *     ->setParameter('name', 'Bar', IQueryBuilder::PARAM_STR))
1249
+     * </code>
1250
+     *
1251
+     * @param string $name
1252
+     *
1253
+     * @return IParameter
1254
+     */
1255
+    public function createParameter($name) {
1256
+        return new Parameter(':' . $name);
1257
+    }
1258
+
1259
+    /**
1260
+     * Creates a new function
1261
+     *
1262
+     * Attention: Column names inside the call have to be quoted before hand
1263
+     *
1264
+     * Example:
1265
+     * <code>
1266
+     *  $qb = $conn->getQueryBuilder();
1267
+     *  $qb->select($qb->createFunction('COUNT(*)'))
1268
+     *     ->from('users', 'u')
1269
+     *  echo $qb->getSQL(); // SELECT COUNT(*) FROM `users` u
1270
+     * </code>
1271
+     * <code>
1272
+     *  $qb = $conn->getQueryBuilder();
1273
+     *  $qb->select($qb->createFunction('COUNT(`column`)'))
1274
+     *     ->from('users', 'u')
1275
+     *  echo $qb->getSQL(); // SELECT COUNT(`column`) FROM `users` u
1276
+     * </code>
1277
+     *
1278
+     * @param string $call
1279
+     *
1280
+     * @return IQueryFunction
1281
+     */
1282
+    public function createFunction($call) {
1283
+        return new QueryFunction($call);
1284
+    }
1285
+
1286
+    /**
1287
+     * Used to get the id of the last inserted element
1288
+     * @return int
1289
+     * @throws \BadMethodCallException When being called before an insert query has been run.
1290
+     */
1291
+    public function getLastInsertId(): int {
1292
+        if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) {
1293
+            // lastInsertId() needs the prefix but no quotes
1294
+            $table = $this->prefixTableName($this->lastInsertedTable);
1295
+            return $this->connection->lastInsertId($table);
1296
+        }
1297
+
1298
+        throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.');
1299
+    }
1300
+
1301
+    /**
1302
+     * Returns the table name quoted and with database prefix as needed by the implementation
1303
+     *
1304
+     * @param string|IQueryFunction $table
1305
+     * @return string
1306
+     */
1307
+    public function getTableName($table) {
1308
+        if ($table instanceof IQueryFunction) {
1309
+            return (string)$table;
1310
+        }
1311
+
1312
+        $table = $this->prefixTableName($table);
1313
+        return $this->helper->quoteColumnName($table);
1314
+    }
1315
+
1316
+    /**
1317
+     * Returns the table name with database prefix as needed by the implementation
1318
+     *
1319
+     * Was protected until version 30.
1320
+     *
1321
+     * @param string $table
1322
+     * @return string
1323
+     */
1324
+    public function prefixTableName(string $table): string {
1325
+        if ($this->automaticTablePrefix === false || str_starts_with($table, '*PREFIX*')) {
1326
+            return $table;
1327
+        }
1328
+
1329
+        return '*PREFIX*' . $table;
1330
+    }
1331
+
1332
+    /**
1333
+     * Returns the column name quoted and with table alias prefix as needed by the implementation
1334
+     *
1335
+     * @param string $column
1336
+     * @param string $tableAlias
1337
+     * @return string
1338
+     */
1339
+    public function getColumnName($column, $tableAlias = '') {
1340
+        if ($tableAlias !== '') {
1341
+            $tableAlias .= '.';
1342
+        }
1343
+
1344
+        return $this->helper->quoteColumnName($tableAlias . $column);
1345
+    }
1346
+
1347
+    /**
1348
+     * Returns the column name quoted and with table alias prefix as needed by the implementation
1349
+     *
1350
+     * @param string $alias
1351
+     * @return string
1352
+     */
1353
+    public function quoteAlias($alias) {
1354
+        if ($alias === '' || $alias === null) {
1355
+            return $alias;
1356
+        }
1357
+
1358
+        return $this->helper->quoteColumnName($alias);
1359
+    }
1360
+
1361
+    public function escapeLikeParameter(string $parameter): string {
1362
+        return $this->connection->escapeLikeParameter($parameter);
1363
+    }
1364
+
1365
+    public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self {
1366
+        return $this;
1367
+    }
1368
+
1369
+    public function runAcrossAllShards(): self {
1370
+        // noop
1371
+        return $this;
1372
+    }
1373 1373
 
1374 1374
 }
Please login to merge, or discard this patch.