Fixed some stuff on the emulated Field2 function and added tests

This commit is contained in:
Jan Böhmer 2023-07-27 00:38:17 +02:00
parent 1d03b6c38d
commit 5c30210534
2 changed files with 45 additions and 30 deletions

View file

@ -26,6 +26,8 @@ namespace App\Doctrine\Functions;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\Query\AST\Functions\FunctionNode; use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\InputParameter;
use Doctrine\ORM\Query\AST\Literal;
use Doctrine\ORM\Query\AST\Node; use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser; use Doctrine\ORM\Query\Parser;
@ -37,6 +39,7 @@ class CustomField extends Field
protected Node|null|string $field = null; protected Node|null|string $field = null;
/** @var Node[] */
protected array $values = []; protected array $values = [];
@ -93,21 +96,34 @@ class CustomField extends Field
*/ */
private function getSqlForSQLite(SqlWalker $sqlWalker): string private function getSqlForSQLite(SqlWalker $sqlWalker): string
{ {
$query = 'FIELD2('; //We must collect the real values (including the bind ones, of all values) and merge them into one string
$resolved = [];
$query .= $this->field->dispatch($sqlWalker); foreach ($this->values as $node) {
if ($node instanceof InputParameter) {
$query .= ', "'; $value = $sqlWalker->getQuery()->getParameter($node->name)?->getValue();
if ($value) {
for ($i = 0, $iMax = count($this->values); $i < $iMax; $i++) { $resolved[] = $value;
if ($i > 0) { }
$query .= ',';
} }
$query .= $this->values[$i]->dispatch($sqlWalker);
} }
$query .= '")'; $output = [];
array_walk_recursive($resolved, function($value) use (&$output) {
$output[] = $value;
});
//Merge all values into one string and create a new node
$stringified = implode(',', $output);
//We use it as a string literal here, as bound parameters, seems to be difficult to use here
$literal = new Literal(Literal::STRING, $stringified);
$query = 'FIELD2(';
$query .= $this->field->dispatch($sqlWalker);
$query .= ',';
//We bind the stringified values as a new parameter
$query .= $literal->dispatch($sqlWalker);
$query .= ')';
return $query; return $query;
} }

View file

@ -49,27 +49,26 @@ class SQLiteRegexExtensionTest extends TestCase
public function fieldDataProvider(): \Generator public function fieldDataProvider(): \Generator
{ {
yield [
// Null cases
0, null, [],
0, null, [1],
0, 42, [1, 2],
// Ints // Null cases
1, 1, [1], yield [0, null, []];
1, 2, [2, 1], yield [0, null, [1]];
2, 1, [2, 1], yield [0, 42, [1, 2]];
2, 2, [2, 1, 2],
5, 3, [2, 1, 2, 1, 2, 3],
1, 2, [2, 1, 2, 1, 2, 1, 2, 1, 2, 1],
// Strings // Ints
1, 'a', ['a'], yield [1, 1, [1]];
1, 'b', ['b', 'a'], yield [1, 2, [2, 1]];
2, 'a', ['b', 'a'], yield [2, 1, [2, 1]];
2, 'b', ['b', 'a', 'b'], yield [6, 3, [2, 1, 2, 1, 2, 3]];
5, 'c', ['b', 'a', 'b', 'a', 'b', 'c'], yield [1, 2, [2, 1, 2, 1, 2, 1, 2, 1, 2, 1]];
]; yield [3, 5, [2, 1, 5, 3]];
// Strings
yield [1, 'a', ['a']];
yield [1, 'b', ['b', 'a']];
yield [2, 'a', ['b', 'a']];
yield [1, 'b', ['b', 'a', 'b']];
yield [6, 'c', ['b', 'a', 'b', 'a', 'b', 'c']];
} }
/** /**