‪TYPO3CMS  ‪main
ExpressionBuilderTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Platforms\TrimMode;
21 use PHPUnit\Framework\Attributes\DataProvider;
22 use PHPUnit\Framework\Attributes\Test;
23 use PHPUnit\Framework\MockObject\MockObject;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32 
33 final class ‪ExpressionBuilderTest extends UnitTestCase
34 {
35  private ‪Connection&MockObject ‪$connectionMock;
37 
41  protected function ‪setUp(): void
42  {
43  parent::setUp();
44  $this->connectionMock = $this->createMock(Connection::class);
45  $this->subject = new ‪ExpressionBuilder($this->connectionMock);
46  }
47 
48  #[Test]
49  public function ‪andXReturnType(): void
50  {
51  $result = $this->subject->and('"uid" = 1', '"pid" = 0');
52 
53  self::assertInstanceOf(CompositeExpression::class, $result);
54  self::assertSame(CompositeExpression::TYPE_AND, $result->getType());
55  }
56 
57  #[Test]
58  public function ‪orXReturnType(): void
59  {
60  $result = $this->subject->or('"uid" = 1', '"uid" = 7');
61 
62  self::assertInstanceOf(CompositeExpression::class, $result);
63  self::assertSame(CompositeExpression::TYPE_OR, $result->getType());
64  }
65 
66  #[Test]
67  public function ‪eqQuotesIdentifier(): void
68  {
69  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
70  $result = $this->subject->eq('aField', 1);
71 
72  self::assertSame('aField = 1', $result);
73  }
74 
75  #[Test]
76  public function ‪neqQuotesIdentifier(): void
77  {
78  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
79  $result = $this->subject->neq('aField', 1);
80 
81  self::assertSame('aField <> 1', $result);
82  }
83 
84  #[Test]
85  public function ‪ltQuotesIdentifier(): void
86  {
87  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
88  $result = $this->subject->lt('aField', 1);
89 
90  self::assertSame('aField < 1', $result);
91  }
92 
93  #[Test]
94  public function ‪lteQuotesIdentifier(): void
95  {
96  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
97  $result = $this->subject->lte('aField', 1);
98 
99  self::assertSame('aField <= 1', $result);
100  }
101 
102  #[Test]
103  public function ‪gtQuotesIdentifier(): void
104  {
105  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
106  $result = $this->subject->gt('aField', 1);
107 
108  self::assertSame('aField > 1', $result);
109  }
110 
111  #[Test]
112  public function ‪gteQuotesIdentifier(): void
113  {
114  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
115  $result = $this->subject->gte('aField', 1);
116 
117  self::assertSame('aField >= 1', $result);
118  }
119 
120  #[Test]
121  public function ‪isNullQuotesIdentifier(): void
122  {
123  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
124  $result = $this->subject->isNull('aField');
125 
126  self::assertSame('aField IS NULL', $result);
127  }
128 
129  #[Test]
130  public function ‪isNotNullQuotesIdentifier(): void
131  {
132  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
133  $result = $this->subject->isNotNull('aField');
134 
135  self::assertSame('aField IS NOT NULL', $result);
136  }
137 
138  #[Test]
139  public function ‪likeQuotesLiteral(): void
140  {
141  $databasePlatform = $this->createMock(MockMySQLPlatform::class);
142  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
143  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
144  $this->connectionMock->method('quote')->willReturnCallback(function (string $value): string {
145  return '"' . $value . '"';
146  });
147  $result = $this->subject->like('aField', "'aValue%'");
148  self::assertSame("aField LIKE 'aValue%' ESCAPE \"\\\"", $result);
149  }
150 
151  #[Test]
152  public function ‪notLikeQuotesLiteral(): void
153  {
154  $databasePlatform = $this->createMock(MockMySQLPlatform::class);
155  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
156  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
157  $this->connectionMock->method('quote')->willReturnCallback(function (string $value): string {
158  return '"' . $value . '"';
159  });
160  $result = $this->subject->notLike('aField', "'aValue%'");
161  self::assertSame("aField NOT LIKE 'aValue%' ESCAPE \"\\\"", $result);
162  }
163 
164  #[Test]
165  public function ‪inWithStringQuotesIdentifier(): void
166  {
167  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
168  $result = $this->subject->in('aField', '1,2,3');
169 
170  self::assertSame('aField IN (1,2,3)', $result);
171  }
172 
173  #[Test]
174  public function ‪inWithArrayQuotesIdentifier(): void
175  {
176  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
177  $result = $this->subject->in('aField', [1, 2, 3]);
178 
179  self::assertSame('aField IN (1, 2, 3)', $result);
180  }
181 
182  #[Test]
183  public function ‪inThrowsExceptionWithEmptyArray(): void
184  {
185  $this->expectException(\InvalidArgumentException::class);
186  $this->expectExceptionCode(1701857902);
187  $this->subject->in('aField', []);
188  }
189 
190  #[Test]
191  public function ‪inThrowsExceptionWithEmptyString(): void
192  {
193  $this->expectException(\InvalidArgumentException::class);
194  $this->expectExceptionCode(1701857903);
195  $this->subject->in('aField', '');
196  }
197 
198  #[Test]
199  public function ‪notInWithStringQuotesIdentifier(): void
200  {
201  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
202  $result = $this->subject->notIn('aField', '1,2,3');
203 
204  self::assertSame('aField NOT IN (1,2,3)', $result);
205  }
206 
207  #[Test]
208  public function ‪notInWithArrayQuotesIdentifier(): void
209  {
210  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')->with('aField')->willReturnArgument(0);
211  $result = $this->subject->notIn('aField', [1, 2, 3]);
212 
213  self::assertSame('aField NOT IN (1, 2, 3)', $result);
214  }
215 
216  #[Test]
218  {
219  $this->expectException(\InvalidArgumentException::class);
220  $this->expectExceptionCode(1701857904);
221  $this->subject->notIn('aField', []);
222  }
223 
224  #[Test]
226  {
227  $this->expectException(\InvalidArgumentException::class);
228  $this->expectExceptionCode(1701857905);
229  $this->subject->notIn('aField', '');
230  }
231 
232  #[Test]
234  {
235  $this->expectException(\InvalidArgumentException::class);
236  $this->expectExceptionCode(1459696089);
237  $this->subject->inSet('aField', '');
238  }
239 
240  #[Test]
242  {
243  $this->expectException(\InvalidArgumentException::class);
244  $this->expectExceptionCode(1459696090);
245  $this->subject->inSet('aField', 'an,Invalid,Value');
246  }
247 
248  #[Test]
249  public function ‪inSetForMySQL(): void
250  {
251  $databasePlatform = $this->createMock(MockMySQLPlatform::class);
252  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
253  return '`' . ‪$identifier . '`';
254  });
255 
256  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
257 
258  $result = $this->subject->inSet('aField', "'1'");
259 
260  self::assertSame('FIND_IN_SET(\'1\', `aField`)', $result);
261  }
262 
263  #[Test]
264  public function ‪inSetForPostgreSQL(): void
265  {
266  $databasePlatform = $this->createMock(MockPostgreSQLPlatform::class);
267  $series = [
268  ['1', "'1'"],
269  [',', "','"],
270  ];
271  $this->connectionMock->expects(self::exactly(2))->method('quote')
272  ->willReturnCallback(function (string $value) use (&$series): string {
273  $arguments = array_shift($series);
274  self::assertSame($arguments[0], $value);
275  return $arguments[1];
276  });
277  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
278  return '"' . ‪$identifier . '"';
279  });
280 
281  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
282 
283  $result = $this->subject->inSet('aField', "'1'");
284 
285  self::assertSame('\'1\' = ANY(string_to_array("aField"::text, \',\'))', $result);
286  }
287 
288  #[Test]
289  public function ‪inSetForPostgreSQLWithColumn(): void
290  {
291  $databasePlatform = $this->createMock(MockPostgreSQLPlatform::class);
292  $this->connectionMock->expects(self::atLeastOnce())->method('quote')->with(',')->willReturn("','");
293  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
294  return '"' . ‪$identifier . '"';
295  });
296 
297  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
298 
299  $result = $this->subject->inSet('aField', '"testtable"."uid"', true);
300 
301  self::assertSame('"testtable"."uid"::text = ANY(string_to_array("aField"::text, \',\'))', $result);
302  }
303 
304  #[Test]
305  public function ‪inSetForSQLite(): void
306  {
307  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
308  $series = [
309  [',', "','"],
310  [',', "','"],
311  [',1,', "'%,1,%'"],
312  ];
313  $this->connectionMock->expects(self::exactly(3))->method('quote')
314  ->willReturnCallback(function (string $value) use (&$series): string {
315  $arguments = array_shift($series);
316  self::assertSame($arguments[0], $value);
317  return $arguments[1];
318  });
319 
320  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
321  return '"' . ‪$identifier . '"';
322  });
323  $databasePlatform->method('quoteStringLiteral')->willReturnCallback(static function (string $str): string {
324  return "'" . str_replace("'", "''", $str) . "'";
325  });
326 
327  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
328 
329  $result = $this->subject->inSet('aField', "'1'");
330 
331  self::assertSame('instr(\',\'||"aField"||\',\', \'%,1,%\')', $result);
332  }
333 
334  #[Test]
336  {
337  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
338  $series = [
339  [',', "','"],
340  [',', "','"],
341  [',\'Some\'Value,', "',''Some''Value,'"],
342  ];
343  $this->connectionMock->expects(self::exactly(3))->method('quote')
344  ->willReturnCallback(function (string $value) use (&$series): string {
345  $arguments = array_shift($series);
346  self::assertSame($arguments[0], $value);
347  return $arguments[1];
348  });
349  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
350  return '"' . ‪$identifier . '"';
351  });
352  $databasePlatform->method('quoteStringLiteral')->willReturnCallback(static function (string $str): string {
353  return "'" . str_replace("'", "''", $str) . "'";
354  });
355 
356  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
357 
358  $result = $this->subject->inSet('aField', "'''Some''Value'");
359 
360  self::assertSame('instr(\',\'||"aField"||\',\', \',\'\'Some\'\'Value,\')', $result);
361  }
362 
363  #[Test]
365  {
366  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
367  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
368 
369  $this->expectException(\InvalidArgumentException::class);
370  $this->expectExceptionCode(1476029421);
371 
372  $this->subject->inSet('aField', '?');
373  }
374 
375  #[Test]
377  {
378  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
379  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
380 
381  $this->expectException(\InvalidArgumentException::class);
382  $this->expectExceptionCode(1476029421);
383 
384  $this->subject->inSet('aField', ':dcValue1');
385  }
386 
387  #[Test]
389  {
390  $this->expectException(\InvalidArgumentException::class);
391  $this->expectExceptionCode(1627573099);
392  $this->subject->notInSet('aField', '');
393  }
394 
395  #[Test]
397  {
398  $this->expectException(\InvalidArgumentException::class);
399  $this->expectExceptionCode(1627573100);
400  $this->subject->notInSet('aField', 'an,Invalid,Value');
401  }
402 
403  #[Test]
404  public function ‪notInSetForMySQL(): void
405  {
406  $databasePlatform = $this->createMock(MockMySQLPlatform::class);
407 
408  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
409  return '`' . ‪$identifier . '`';
410  });
411 
412  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
413 
414  $result = $this->subject->notInSet('aField', "'1'");
415 
416  self::assertSame('NOT FIND_IN_SET(\'1\', `aField`)', $result);
417  }
418 
419  #[Test]
420  public function ‪notInSetForPostgreSQL(): void
421  {
422  $databasePlatform = $this->createMock(MockPostgreSQLPlatform::class);
423  $series = [
424  ['1', "'1'"],
425  [',', "','"],
426  ];
427  $this->connectionMock->expects(self::exactly(2))->method('quote')
428  ->willReturnCallback(function (string $value) use (&$series): string {
429  $arguments = array_shift($series);
430  self::assertSame($arguments[0], $value);
431  return $arguments[1];
432  });
433  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
434  return '"' . ‪$identifier . '"';
435  });
436 
437  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
438 
439  $result = $this->subject->notInSet('aField', "'1'");
440 
441  self::assertSame('\'1\' <> ALL(string_to_array("aField"::text, \',\'))', $result);
442  }
443 
444  #[Test]
445  public function ‪notInSetForPostgreSQLWithColumn(): void
446  {
447  $databasePlatform = $this->createMock(MockPostgreSQLPlatform::class);
448 
449  $this->connectionMock->expects(self::atLeastOnce())->method('quote')->with(',')->willReturn("','");
450  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
451  return '"' . ‪$identifier . '"';
452  });
453 
454  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
455 
456  $result = $this->subject->notInSet('aField', '"testtable"."uid"', true);
457 
458  self::assertSame('"testtable"."uid"::text <> ALL(string_to_array("aField"::text, \',\'))', $result);
459  }
460 
461  #[Test]
462  public function ‪notInSetForSQLite(): void
463  {
464  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
465  $series = [
466  [',', "','"],
467  [',', "','"],
468  [',1,', "'%,1,%'"],
469  ];
470  $this->connectionMock->expects(self::exactly(3))->method('quote')
471  ->willReturnCallback(function (string $value) use (&$series): string {
472  $arguments = array_shift($series);
473  self::assertSame($arguments[0], $value);
474  return $arguments[1];
475  });
476  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
477  return '"' . ‪$identifier . '"';
478  });
479 
480  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
481 
482  $result = $this->subject->notInSet('aField', "'1'");
483 
484  self::assertSame('instr(\',\'||"aField"||\',\', \'%,1,%\') = 0', $result);
485  }
486 
487  #[Test]
489  {
490  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
491  $series = [
492  [',', "','"],
493  [',', "','"],
494  [',\'Some\'Value,', "',''Some''Value,'"],
495  ];
496  $this->connectionMock->expects(self::exactly(3))->method('quote')
497  ->willReturnCallback(function (string $value) use (&$series): string {
498  $arguments = array_shift($series);
499  self::assertSame($arguments[0], $value);
500  return $arguments[1];
501  });
502  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
503  return '"' . ‪$identifier . '"';
504  });
505 
506  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
507 
508  $result = $this->subject->notInSet('aField', "'''Some''Value'");
509 
510  self::assertSame('instr(\',\'||"aField"||\',\', \',\'\'Some\'\'Value,\') = 0', $result);
511  }
512 
513  #[Test]
515  {
516  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
517  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
518 
519  $this->expectException(\InvalidArgumentException::class);
520  $this->expectExceptionCode(1627573103);
521 
522  $this->subject->notInSet('aField', '?');
523  }
524 
525  #[Test]
527  {
528  $databasePlatform = $this->createMock(MockSQLitePlatform::class);
529  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
530 
531  $this->expectException(\InvalidArgumentException::class);
532  $this->expectExceptionCode(1476029421);
533 
534  $this->subject->inSet('aField', ':dcValue1');
535  }
536 
537  #[Test]
538  public function ‪defaultBitwiseAnd(): void
539  {
540  $databasePlatform = $this->createMock(MockMySQLPlatform::class);
541 
542  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
543  return '"' . ‪$identifier . '"';
544  });
545 
546  $this->connectionMock->method('getDatabasePlatform')->willReturn($databasePlatform);
547 
548  self::assertSame('"aField" & 1', $this->subject->bitAnd('aField', 1));
549  }
550 
551  #[Test]
552  public function ‪maxQuotesIdentifier(): void
553  {
554  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
555  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
556  });
557 
558  self::assertSame('MAX("tableName"."fieldName")', $this->subject->max('tableName.fieldName'));
559  self::assertSame(
560  'MAX("tableName"."fieldName") AS "anAlias"',
561  $this->subject->max('tableName.fieldName', 'anAlias')
562  );
563  }
564 
565  #[Test]
566  public function ‪minQuotesIdentifier(): void
567  {
568  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
569  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
570  });
571 
572  self::assertSame('MIN("tableName"."fieldName")', $this->subject->min('tableName.fieldName'));
573  self::assertSame(
574  'MIN("tableName"."fieldName") AS "anAlias"',
575  $this->subject->min('tableName.fieldName', 'anAlias')
576  );
577  }
578 
579  #[Test]
580  public function ‪sumQuotesIdentifier(): void
581  {
582  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
583  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
584  });
585 
586  self::assertSame('SUM("tableName"."fieldName")', $this->subject->sum('tableName.fieldName'));
587  self::assertSame(
588  'SUM("tableName"."fieldName") AS "anAlias"',
589  $this->subject->sum('tableName.fieldName', 'anAlias')
590  );
591  }
592 
593  #[Test]
594  public function ‪avgQuotesIdentifier(): void
595  {
596  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
597  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
598  });
599 
600  self::assertSame('AVG("tableName"."fieldName")', $this->subject->avg('tableName.fieldName'));
601  self::assertSame(
602  'AVG("tableName"."fieldName") AS "anAlias"',
603  $this->subject->avg('tableName.fieldName', 'anAlias')
604  );
605  }
606 
607  #[Test]
608  public function ‪countQuotesIdentifier(): void
609  {
610  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
611  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
612  });
613 
614  self::assertSame('COUNT("tableName"."fieldName")', $this->subject->count('tableName.fieldName'));
615  self::assertSame(
616  'COUNT("tableName"."fieldName") AS "anAlias"',
617  $this->subject->count('tableName.fieldName', 'anAlias')
618  );
619  }
620 
621  #[Test]
622  public function ‪lengthQuotesIdentifier(): void
623  {
624  $this->connectionMock->method('quoteIdentifier')->willReturnCallback(static function (string ‪$identifier): string {
625  return (new ‪MockPlatform())->quoteIdentifier(‪$identifier);
626  });
627 
628  self::assertSame('LENGTH("tableName"."fieldName")', $this->subject->length('tableName.fieldName'));
629  self::assertSame(
630  'LENGTH("tableName"."fieldName") AS "anAlias"',
631  $this->subject->length('tableName.fieldName', 'anAlias')
632  );
633  }
634 
635  #[Test]
637  {
638  $platform = new ‪MockPlatform();
639  $this->connectionMock->expects(self::atLeastOnce())->method('getDatabasePlatform')->willReturn($platform);
640  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')
641  ->willReturnCallback(
642  static function (string ‪$identifier) use ($platform): string {
643  return $platform->quoteIdentifier(‪$identifier);
644  }
645  );
646 
647  self::assertSame(
648  'TRIM("tableName"."fieldName")',
649  $this->subject->trim('tableName.fieldName')
650  );
651  }
652 
653  public static function ‪trimQuotesIdentifierDataProvider(): array
654  {
655  return [
656  'trim leading character' => [
657  TrimMode::LEADING,
658  'x',
659  'TRIM(LEADING "x" FROM "tableName"."fieldName")',
660  ],
661  'trim trailing character' => [
662  TrimMode::TRAILING,
663  'x',
664  'TRIM(TRAILING "x" FROM "tableName"."fieldName")',
665  ],
666  'trim character' => [
667  TrimMode::BOTH,
668  'x',
669  'TRIM(BOTH "x" FROM "tableName"."fieldName")',
670  ],
671  'trim space' => [
672  TrimMode::BOTH,
673  ' ',
674  'TRIM(BOTH " " FROM "tableName"."fieldName")',
675  ],
676  ];
677  }
678 
679  #[DataProvider('trimQuotesIdentifierDataProvider')]
680  #[Test]
681  public function ‪trimQuotesIdentifier(TrimMode $position, string $char, string $expected): void
682  {
683  $platform = new ‪MockPlatform();
684  $this->connectionMock->expects(self::atLeastOnce())->method('getDatabasePlatform')->willReturn($platform);
685  $this->connectionMock->expects(self::atLeastOnce())->method('quoteIdentifier')
686  ->willReturnCallback(
687  static function (string ‪$identifier) use ($platform): string {
688  return $platform->quoteIdentifier(‪$identifier);
689  }
690  );
691  $this->connectionMock->expects(self::atLeastOnce())->method('quote')->willReturnCallback(
692  static function (string ‪$identifier): string {
693  return '"' . ‪$identifier . '"';
694  }
695  );
696 
697  self::assertSame(
698  $expected,
699  $this->subject->trim('tableName.fieldName', $position, $char)
700  );
701  }
702 
703  #[Test]
704  public function ‪literalQuotesValue(): void
705  {
706  $this->connectionMock->expects(self::atLeastOnce())->method('quote')->with('aField')
707  ->willReturn('"aField"');
708  $result = $this->subject->literal('aField');
709 
710  self::assertSame('"aField"', $result);
711  }
712 }
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForPostgreSQLWithColumn
‪inSetForPostgreSQLWithColumn()
Definition: ExpressionBuilderTest.php:289
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\gtQuotesIdentifier
‪gtQuotesIdentifier()
Definition: ExpressionBuilderTest.php:103
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForSQLiteThrowsExceptionOnPositionalPlaceholder
‪inSetForSQLiteThrowsExceptionOnPositionalPlaceholder()
Definition: ExpressionBuilderTest.php:364
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\avgQuotesIdentifier
‪avgQuotesIdentifier()
Definition: ExpressionBuilderTest.php:594
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForSQLite
‪notInSetForSQLite()
Definition: ExpressionBuilderTest.php:462
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inThrowsExceptionWithEmptyString
‪inThrowsExceptionWithEmptyString()
Definition: ExpressionBuilderTest.php:191
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\ltQuotesIdentifier
‪ltQuotesIdentifier()
Definition: ExpressionBuilderTest.php:85
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\sumQuotesIdentifier
‪sumQuotesIdentifier()
Definition: ExpressionBuilderTest.php:580
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform\MockPostgreSQLPlatform
Definition: MockPostgreSQLPlatform.php:24
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\countQuotesIdentifier
‪countQuotesIdentifier()
Definition: ExpressionBuilderTest.php:608
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInWithStringQuotesIdentifier
‪notInWithStringQuotesIdentifier()
Definition: ExpressionBuilderTest.php:199
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\setUp
‪setUp()
Definition: ExpressionBuilderTest.php:41
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetThrowsExceptionWithInvalidValue
‪notInSetThrowsExceptionWithInvalidValue()
Definition: ExpressionBuilderTest.php:396
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notLikeQuotesLiteral
‪notLikeQuotesLiteral()
Definition: ExpressionBuilderTest.php:152
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inWithArrayQuotesIdentifier
‪inWithArrayQuotesIdentifier()
Definition: ExpressionBuilderTest.php:174
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\isNullQuotesIdentifier
‪isNullQuotesIdentifier()
Definition: ExpressionBuilderTest.php:121
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\neqQuotesIdentifier
‪neqQuotesIdentifier()
Definition: ExpressionBuilderTest.php:76
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest
Definition: ExpressionBuilderTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\andXReturnType
‪andXReturnType()
Definition: ExpressionBuilderTest.php:49
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForPostgreSQLWithColumn
‪notInSetForPostgreSQLWithColumn()
Definition: ExpressionBuilderTest.php:445
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\$subject
‪ExpressionBuilder $subject
Definition: ExpressionBuilderTest.php:36
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\likeQuotesLiteral
‪likeQuotesLiteral()
Definition: ExpressionBuilderTest.php:139
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\trimQuotesIdentifier
‪trimQuotesIdentifier(TrimMode $position, string $char, string $expected)
Definition: ExpressionBuilderTest.php:681
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inThrowsExceptionWithEmptyArray
‪inThrowsExceptionWithEmptyArray()
Definition: ExpressionBuilderTest.php:183
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\minQuotesIdentifier
‪minQuotesIdentifier()
Definition: ExpressionBuilderTest.php:566
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\isNotNullQuotesIdentifier
‪isNotNullQuotesIdentifier()
Definition: ExpressionBuilderTest.php:130
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\trimQuotesIdentifierWithDefaultValues
‪trimQuotesIdentifierWithDefaultValues()
Definition: ExpressionBuilderTest.php:636
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForSQLiteThrowsExceptionOnNamedPlaceholder
‪notInSetForSQLiteThrowsExceptionOnNamedPlaceholder()
Definition: ExpressionBuilderTest.php:526
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInThrowsExceptionWithEmptyString
‪notInThrowsExceptionWithEmptyString()
Definition: ExpressionBuilderTest.php:225
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForMySQL
‪inSetForMySQL()
Definition: ExpressionBuilderTest.php:249
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:27
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\trimQuotesIdentifierDataProvider
‪static trimQuotesIdentifierDataProvider()
Definition: ExpressionBuilderTest.php:653
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\gteQuotesIdentifier
‪gteQuotesIdentifier()
Definition: ExpressionBuilderTest.php:112
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForSQLite
‪inSetForSQLite()
Definition: ExpressionBuilderTest.php:305
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetThrowsExceptionWithEmptyValue
‪inSetThrowsExceptionWithEmptyValue()
Definition: ExpressionBuilderTest.php:233
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetThrowsExceptionWithInvalidValue
‪inSetThrowsExceptionWithInvalidValue()
Definition: ExpressionBuilderTest.php:241
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInThrowsExceptionWithEmptyArray
‪notInThrowsExceptionWithEmptyArray()
Definition: ExpressionBuilderTest.php:217
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetThrowsExceptionWithEmptyValue
‪notInSetThrowsExceptionWithEmptyValue()
Definition: ExpressionBuilderTest.php:388
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForMySQL
‪notInSetForMySQL()
Definition: ExpressionBuilderTest.php:404
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\eqQuotesIdentifier
‪eqQuotesIdentifier()
Definition: ExpressionBuilderTest.php:67
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForSQLiteWithQuoteCharactersInValue
‪inSetForSQLiteWithQuoteCharactersInValue()
Definition: ExpressionBuilderTest.php:335
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\$connectionMock
‪Connection &MockObject $connectionMock
Definition: ExpressionBuilderTest.php:35
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\lengthQuotesIdentifier
‪lengthQuotesIdentifier()
Definition: ExpressionBuilderTest.php:622
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\lteQuotesIdentifier
‪lteQuotesIdentifier()
Definition: ExpressionBuilderTest.php:94
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInWithArrayQuotesIdentifier
‪notInWithArrayQuotesIdentifier()
Definition: ExpressionBuilderTest.php:208
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\maxQuotesIdentifier
‪maxQuotesIdentifier()
Definition: ExpressionBuilderTest.php:552
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression
Definition: ExpressionBuilderTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForPostgreSQL
‪inSetForPostgreSQL()
Definition: ExpressionBuilderTest.php:264
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForPostgreSQL
‪notInSetForPostgreSQL()
Definition: ExpressionBuilderTest.php:420
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform\MockMySQLPlatform
Definition: MockMySQLPlatform.php:24
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inSetForSQLiteThrowsExceptionOnNamedPlaceholder
‪inSetForSQLiteThrowsExceptionOnNamedPlaceholder()
Definition: ExpressionBuilderTest.php:376
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\inWithStringQuotesIdentifier
‪inWithStringQuotesIdentifier()
Definition: ExpressionBuilderTest.php:165
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForSQLiteWithQuoteCharactersInValue
‪notInSetForSQLiteWithQuoteCharactersInValue()
Definition: ExpressionBuilderTest.php:488
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform\MockPlatform
Definition: MockPlatform.php:32
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform\MockSQLitePlatform
Definition: MockSQLitePlatform.php:24
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\literalQuotesValue
‪literalQuotesValue()
Definition: ExpressionBuilderTest.php:704
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\orXReturnType
‪orXReturnType()
Definition: ExpressionBuilderTest.php:58
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\defaultBitwiseAnd
‪defaultBitwiseAnd()
Definition: ExpressionBuilderTest.php:538
‪TYPO3\CMS\Core\Tests\Unit\Database\Query\Expression\ExpressionBuilderTest\notInSetForSQLiteThrowsExceptionOnPositionalPlaceholder
‪notInSetForSQLiteThrowsExceptionOnPositionalPlaceholder()
Definition: ExpressionBuilderTest.php:514