diff --git a/tests/Connection/ExpandArrayParametersTest.php b/tests/Connection/ExpandArrayParametersTest.php index 8ef6a3151ab..fe42fbe1cf0 100644 --- a/tests/Connection/ExpandArrayParametersTest.php +++ b/tests/Connection/ExpandArrayParametersTest.php @@ -15,328 +15,356 @@ class ExpandArrayParametersTest extends TestCase { - /** @return mixed[][] */ + /** @return iterable */ public static function dataExpandListParameters(): iterable { - return [ - 'Positional: Very simple with one needle' => [ - 'SELECT * FROM Foo WHERE foo IN (?)', - [[1, 2, 3]], - [ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)', - [1, 2, 3], - [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], - ], - 'Positional: One non-list before d one after list-needle' => [ - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?)', - ['string', [1, 2, 3]], - [ParameterType::STRING, ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)', - ['string', 1, 2, 3], - [ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], - ], - 'Positional: One non-list after list-needle' => [ - 'SELECT * FROM Foo WHERE bar IN (?) AND baz = ?', - [[1, 2, 3], 'foo'], - [ArrayParameterType::INTEGER, ParameterType::STRING], - 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?', - [1, 2, 3, 'foo'], - [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING], - ], - 'Positional: One non-list before and one after list-needle' => [ - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ?', - [1, [1, 2, 3], 4], - [ParameterType::INTEGER, ArrayParameterType::INTEGER, ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?', - [1, 1, 2, 3, 4], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ], - ], - 'Positional: Two lists' => [ - 'SELECT * FROM Foo WHERE foo IN (?, ?)', - [[1, 2, 3], [4, 5]], - [ArrayParameterType::INTEGER, ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)', - [1, 2, 3, 4, 5], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ], - ], - 'Positional: Empty "integer" array (DDC-1978)' => [ - 'SELECT * FROM Foo WHERE foo IN (?)', - [[]], - [ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (NULL)', - [], - [], - ], - 'Positional: Empty "str" array (DDC-1978)' => [ - 'SELECT * FROM Foo WHERE foo IN (?)', - [[]], - [ArrayParameterType::STRING], - 'SELECT * FROM Foo WHERE foo IN (NULL)', - [], - [], - ], - 'Positional: explicit keys for params and types' => [ - 'SELECT * FROM Foo WHERE foo = ? AND bar = ? AND baz = ?', - [1 => 'bar', 2 => 'baz', 0 => 1], - [2 => ParameterType::STRING, 1 => ParameterType::STRING], - 'SELECT * FROM Foo WHERE foo = ? AND bar = ? AND baz = ?', - [1 => 'bar', 0 => 1, 2 => 'baz'], - [1 => ParameterType::STRING, 2 => ParameterType::STRING], - ], - 'Positional: explicit keys for array params and array types' => [ - 'SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ? AND bax IN (?) AND bay IN (?)', - [ - 1 => ['bar1', 'bar2'], - 2 => true, - 0 => [1, 2, 3], - ['bax1', 'bax2'], - 4 => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], - ], - [ - 4 => ArrayParameterType::BINARY, - 3 => ArrayParameterType::ASCII, - 2 => ParameterType::BOOLEAN, - 1 => ArrayParameterType::STRING, - 0 => ArrayParameterType::INTEGER, - ], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ? AND bax IN (?, ?) ' . - 'AND bay IN (?, ?)', - [1, 2, 3, 'bar1', 'bar2', true, 'bax1', 'bax2', hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::STRING, - ParameterType::STRING, - ParameterType::BOOLEAN, - ParameterType::ASCII, - ParameterType::ASCII, - ParameterType::BINARY, - ParameterType::BINARY, - ], - ], - 'Named: Very simple with param int' => [ - 'SELECT * FROM Foo WHERE foo = :foo', - ['foo' => 1], - ['foo' => ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ?', - [1], - [ParameterType::INTEGER], - ], - 'Named: Very simple with param int and string' => [ - 'SELECT * FROM Foo WHERE foo = :foo AND bar = :bar', - ['bar' => 'Some String','foo' => 1], - ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::STRING], - 'SELECT * FROM Foo WHERE foo = ? AND bar = ?', - [1,'Some String'], - [ParameterType::INTEGER, ParameterType::STRING], - ], - 'Named: Very simple with one needle' => [ - 'SELECT * FROM Foo WHERE foo IN (:foo)', - ['foo' => [1, 2, 3]], - ['foo' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)', - [1, 2, 3], - [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], - ], - 'Named: One non-list before d one after list-needle' => [ - 'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar)', - ['foo' => 'string', 'bar' => [1, 2, 3]], - ['foo' => ParameterType::STRING, 'bar' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)', - ['string', 1, 2, 3], - [ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], - ], - 'Named: One non-list after list-needle' => [ - 'SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz', - ['bar' => [1, 2, 3], 'baz' => 'foo'], - ['bar' => ArrayParameterType::INTEGER, 'baz' => ParameterType::STRING], - 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?', - [1, 2, 3, 'foo'], - [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING], - ], - 'Named: One non-list before and one after list-needle' => [ - 'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar) AND baz = :baz', - ['bar' => [1, 2, 3],'foo' => 1, 'baz' => 4], - [ - 'bar' => ArrayParameterType::INTEGER, - 'foo' => ParameterType::INTEGER, - 'baz' => ParameterType::INTEGER, - ], - 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?', - [1, 1, 2, 3, 4], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ], - ], - 'Named: Two lists' => [ - 'SELECT * FROM Foo WHERE foo IN (:a, :b)', - ['b' => [4, 5],'a' => [1, 2, 3]], - ['a' => ArrayParameterType::INTEGER, 'b' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)', - [1, 2, 3, 4, 5], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ], - ], - 'Named: With the same name arg type string' => [ - 'SELECT * FROM Foo WHERE foo <> :arg AND bar = :arg', - ['arg' => 'Some String'], - ['arg' => ParameterType::STRING], - 'SELECT * FROM Foo WHERE foo <> ? AND bar = ?', - ['Some String','Some String'], - [ParameterType::STRING,ParameterType::STRING], - ], - 'Named: With the same name arg' => [ - 'SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)', - ['arg' => [1, 2, 3]], - ['arg' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND NOT bar IN (?, ?, ?)', - [1, 2, 3, 1, 2, 3], - [ - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ParameterType::INTEGER, - ], - ], - 'Named: Same name, other name in between (DBAL-299)' => [ - 'SELECT * FROM Foo WHERE (:foo = 2) AND (:bar = 3) AND (:foo = 2)', - ['foo' => 2,'bar' => 3], - ['foo' => ParameterType::INTEGER,'bar' => ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE (? = 2) AND (? = 3) AND (? = 2)', - [2, 3, 2], - [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], - ], - 'Named: Empty "integer" array (DDC-1978)' => [ - 'SELECT * FROM Foo WHERE foo IN (:foo)', - ['foo' => []], - ['foo' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (NULL)', - [], - [], - ], - 'Named: Two empty "str" array (DDC-1978)' => [ - 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', - ['foo' => [], 'bar' => []], - ['foo' => ArrayParameterType::STRING, 'bar' => ArrayParameterType::STRING], - 'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)', - [], - [], + yield 'Positional: Very simple with one needle' => [ + 'SELECT * FROM Foo WHERE foo IN (?)', + [[1, 2, 3]], + [ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)', + [1, 2, 3], + [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Positional: One non-list before d one after list-needle' => [ + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?)', + ['string', [1, 2, 3]], + [ParameterType::STRING, ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)', + ['string', 1, 2, 3], + [ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Positional: One non-list after list-needle' => [ + 'SELECT * FROM Foo WHERE bar IN (?) AND baz = ?', + [[1, 2, 3], 'foo'], + [ArrayParameterType::INTEGER, ParameterType::STRING], + 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?', + [1, 2, 3, 'foo'], + [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING], + ]; + + yield 'Positional: One non-list before and one after list-needle' => [ + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ?', + [1, [1, 2, 3], 4], + [ParameterType::INTEGER, ArrayParameterType::INTEGER, ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?', + [1, 1, 2, 3, 4], + [ + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, ], + ]; + + yield 'Positional: Two lists' => [ + 'SELECT * FROM Foo WHERE foo IN (?, ?)', + [[1, 2, 3], [4, 5]], + [ArrayParameterType::INTEGER, ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)', + [1, 2, 3, 4, 5], [ - 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', - ['foo' => [], 'bar' => []], - ['foo' => ArrayParameterType::ASCII, 'bar' => ArrayParameterType::ASCII], - 'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)', - [], - [], + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, ], + ]; + + yield 'Positional: Empty "integer" array (DDC-1978)' => [ + 'SELECT * FROM Foo WHERE foo IN (?)', + [[]], + [ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (NULL)', + [], + [], + ]; + + yield 'Positional: Empty "str" array (DDC-1978)' => [ + 'SELECT * FROM Foo WHERE foo IN (?)', + [[]], + [ArrayParameterType::STRING], + 'SELECT * FROM Foo WHERE foo IN (NULL)', + [], + [], + ]; + + yield 'Positional: explicit keys for params and types' => [ + 'SELECT * FROM Foo WHERE foo = ? AND bar = ? AND baz = ?', + [1 => 'bar', 2 => 'baz', 0 => 1], + [2 => ParameterType::STRING, 1 => ParameterType::STRING], + 'SELECT * FROM Foo WHERE foo = ? AND bar = ? AND baz = ?', + [1 => 'bar', 0 => 1, 2 => 'baz'], + [1 => ParameterType::STRING, 2 => ParameterType::STRING], + ]; + + yield 'Positional: explicit keys for array params and array types' => [ + 'SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ? AND bax IN (?) AND bay IN (?)', [ - 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar OR baz = :baz', - ['foo' => [1, 2], 'bar' => 'bar', 'baz' => 'baz'], - ['foo' => ArrayParameterType::INTEGER, 'baz' => 'string'], - 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ? OR baz = ?', - [1, 2, 'bar', 'baz'], - [ - 0 => ParameterType::INTEGER, - 1 => ParameterType::INTEGER, - 3 => 'string', - ], + 1 => ['bar1', 'bar2'], + 2 => true, + 0 => [1, 2, 3], + ['bax1', 'bax2'], + 4 => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], ], [ - 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar', - ['foo' => [1, 2], 'bar' => 'bar'], - ['foo' => ArrayParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ?', - [1, 2, 'bar'], - [ParameterType::INTEGER, ParameterType::INTEGER], + 4 => ArrayParameterType::BINARY, + 3 => ArrayParameterType::ASCII, + 2 => ParameterType::BOOLEAN, + 1 => ArrayParameterType::STRING, + 0 => ArrayParameterType::INTEGER, + ], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND bar IN (?, ?) AND baz = ? AND bax IN (?, ?) ' . + 'AND bay IN (?, ?)', + [1, 2, 3, 'bar1', 'bar2', true, 'bax1', 'bax2', hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], + [ + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::STRING, + ParameterType::STRING, + ParameterType::BOOLEAN, + ParameterType::ASCII, + ParameterType::ASCII, + ParameterType::BINARY, + ParameterType::BINARY, ], - 'Named parameters and partially implicit types' => [ - 'SELECT * FROM Foo WHERE foo = :foo OR bar = :bar', - ['foo' => 'foo', 'bar' => 'bar'], - ['foo' => ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ? OR bar = ?', - ['foo', 'bar'], - [ParameterType::INTEGER], + ]; + + yield 'Named: Very simple with param int' => [ + 'SELECT * FROM Foo WHERE foo = :foo', + ['foo' => 1], + ['foo' => ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ?', + [1], + [ParameterType::INTEGER], + ]; + + yield 'Named: Very simple with param int and string' => [ + 'SELECT * FROM Foo WHERE foo = :foo AND bar = :bar', + ['bar' => 'Some String','foo' => 1], + ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::STRING], + 'SELECT * FROM Foo WHERE foo = ? AND bar = ?', + [1,'Some String'], + [ParameterType::INTEGER, ParameterType::STRING], + ]; + + yield 'Named: Very simple with one needle' => [ + 'SELECT * FROM Foo WHERE foo IN (:foo)', + ['foo' => [1, 2, 3]], + ['foo' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?)', + [1, 2, 3], + [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Named: One non-list before d one after list-needle' => [ + 'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar)', + ['foo' => 'string', 'bar' => [1, 2, 3]], + ['foo' => ParameterType::STRING, 'bar' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?)', + ['string', 1, 2, 3], + [ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Named: One non-list after list-needle' => [ + 'SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz', + ['bar' => [1, 2, 3], 'baz' => 'foo'], + ['bar' => ArrayParameterType::INTEGER, 'baz' => ParameterType::STRING], + 'SELECT * FROM Foo WHERE bar IN (?, ?, ?) AND baz = ?', + [1, 2, 3, 'foo'], + [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING], + ]; + + yield 'Named: One non-list before and one after list-needle' => [ + 'SELECT * FROM Foo WHERE foo = :foo AND bar IN (:bar) AND baz = :baz', + ['bar' => [1, 2, 3],'foo' => 1, 'baz' => 4], + [ + 'bar' => ArrayParameterType::INTEGER, + 'foo' => ParameterType::INTEGER, + 'baz' => ParameterType::INTEGER, ], - 'Named parameters and explicit types' => [ - 'SELECT * FROM Foo WHERE foo = :foo OR bar = :bar', - ['foo' => 'foo', 'bar' => 'bar'], - ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ? OR bar = ?', - ['foo', 'bar'], - [ParameterType::INTEGER, ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? AND bar IN (?, ?, ?) AND baz = ?', + [1, 1, 2, 3, 4], + [ + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, ], - 'Null valued parameters (DBAL-522)' => [ - 'INSERT INTO Foo (foo, bar) values (:foo, :bar)', - ['foo' => 1, 'bar' => null], - ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::NULL], - 'INSERT INTO Foo (foo, bar) values (?, ?)', - [1, null], - [ParameterType::INTEGER, ParameterType::NULL], + ]; + + yield 'Named: Two lists' => [ + 'SELECT * FROM Foo WHERE foo IN (:a, :b)', + ['b' => [4, 5],'a' => [1, 2, 3]], + ['a' => ArrayParameterType::INTEGER, 'b' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)', + [1, 2, 3, 4, 5], + [ + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, ], + ]; + + yield 'Named: With the same name arg type string' => [ + 'SELECT * FROM Foo WHERE foo <> :arg AND bar = :arg', + ['arg' => 'Some String'], + ['arg' => ParameterType::STRING], + 'SELECT * FROM Foo WHERE foo <> ? AND bar = ?', + ['Some String','Some String'], + [ParameterType::STRING,ParameterType::STRING], + ]; + + yield 'Named: With the same name arg' => [ + 'SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)', + ['arg' => [1, 2, 3]], + ['arg' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?, ?) AND NOT bar IN (?, ?, ?)', + [1, 2, 3, 1, 2, 3], [ - 'INSERT INTO Foo (foo, bar) values (?, ?)', - [1, null], - [ParameterType::INTEGER, ParameterType::NULL], - 'INSERT INTO Foo (foo, bar) values (?, ?)', - [1, null], - [ParameterType::INTEGER, ParameterType::NULL], + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, + ParameterType::INTEGER, ], - 'Escaped single quotes SQL- and C-Style (DBAL-1205)' => [ - "SELECT * FROM Foo WHERE foo = :foo||''':not_a_param''\\'' OR bar = ''':not_a_param''\\'':bar", - ['foo' => 1, 'bar' => 2], - ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::INTEGER], - 'SELECT * FROM Foo WHERE foo = ?||\'\'\':not_a_param\'\'\\\'\' OR bar = \'\'\':not_a_param\'\'\\\'\'?', - [1, 2], - [ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Named: Same name, other name in between (DBAL-299)' => [ + 'SELECT * FROM Foo WHERE (:foo = 2) AND (:bar = 3) AND (:foo = 2)', + ['foo' => 2,'bar' => 3], + ['foo' => ParameterType::INTEGER,'bar' => ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE (? = 2) AND (? = 3) AND (? = 2)', + [2, 3, 2], + [ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Named: Empty "integer" array (DDC-1978)' => [ + 'SELECT * FROM Foo WHERE foo IN (:foo)', + ['foo' => []], + ['foo' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (NULL)', + [], + [], + ]; + + yield 'Named: Two empty "str" array (DDC-1978)' => [ + 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', + ['foo' => [], 'bar' => []], + ['foo' => ArrayParameterType::STRING, 'bar' => ArrayParameterType::STRING], + 'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)', + [], + [], + ]; + + yield [ + 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', + ['foo' => [], 'bar' => []], + ['foo' => ArrayParameterType::ASCII, 'bar' => ArrayParameterType::ASCII], + 'SELECT * FROM Foo WHERE foo IN (NULL) OR bar IN (NULL)', + [], + [], + ]; + + yield [ + 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar OR baz = :baz', + ['foo' => [1, 2], 'bar' => 'bar', 'baz' => 'baz'], + ['foo' => ArrayParameterType::INTEGER, 'baz' => 'string'], + 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ? OR baz = ?', + [1, 2, 'bar', 'baz'], + [ + 0 => ParameterType::INTEGER, + 1 => ParameterType::INTEGER, + 3 => 'string', ], + ]; + + yield [ + 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar = :bar', + ['foo' => [1, 2], 'bar' => 'bar'], + ['foo' => ArrayParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar = ?', + [1, 2, 'bar'], + [ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Named parameters and partially implicit types' => [ + 'SELECT * FROM Foo WHERE foo = :foo OR bar = :bar', + ['foo' => 'foo', 'bar' => 'bar'], + ['foo' => ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? OR bar = ?', + ['foo', 'bar'], + [ParameterType::INTEGER], + ]; + + yield 'Named parameters and explicit types' => [ + 'SELECT * FROM Foo WHERE foo = :foo OR bar = :bar', + ['foo' => 'foo', 'bar' => 'bar'], + ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ? OR bar = ?', + ['foo', 'bar'], + [ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield 'Null valued parameters (DBAL-522)' => [ + 'INSERT INTO Foo (foo, bar) values (:foo, :bar)', + ['foo' => 1, 'bar' => null], + ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::NULL], + 'INSERT INTO Foo (foo, bar) values (?, ?)', + [1, null], + [ParameterType::INTEGER, ParameterType::NULL], + ]; + + yield [ + 'INSERT INTO Foo (foo, bar) values (?, ?)', + [1, null], + [ParameterType::INTEGER, ParameterType::NULL], + 'INSERT INTO Foo (foo, bar) values (?, ?)', + [1, null], + [ParameterType::INTEGER, ParameterType::NULL], + ]; + + yield 'Escaped single quotes SQL- and C-Style (DBAL-1205)' => [ + "SELECT * FROM Foo WHERE foo = :foo||''':not_a_param''\\'' OR bar = ''':not_a_param''\\'':bar", + ['foo' => 1, 'bar' => 2], + ['foo' => ParameterType::INTEGER, 'bar' => ParameterType::INTEGER], + 'SELECT * FROM Foo WHERE foo = ?||\'\'\':not_a_param\'\'\\\'\' OR bar = \'\'\':not_a_param\'\'\\\'\'?', + [1, 2], + [ParameterType::INTEGER, ParameterType::INTEGER], + ]; + + yield [ + 'SELECT NULL FROM dummy WHERE ? IN (?)', + ['foo', ['bar', 'baz']], + [1 => ArrayParameterType::STRING], + 'SELECT NULL FROM dummy WHERE ? IN (?, ?)', + ['foo', 'bar', 'baz'], + [1 => ParameterType::STRING, ParameterType::STRING], + ]; + + yield 'Named: Binary array with explicit types' => [ + 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', [ - 'SELECT NULL FROM dummy WHERE ? IN (?)', - ['foo', ['bar', 'baz']], - [1 => ArrayParameterType::STRING], - 'SELECT NULL FROM dummy WHERE ? IN (?, ?)', - ['foo', 'bar', 'baz'], - [1 => ParameterType::STRING, ParameterType::STRING], + 'foo' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], + 'bar' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], ], - 'Named: Binary array with explicit types' => [ - 'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)', - [ - 'foo' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], - 'bar' => [hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], - ], - ['foo' => ArrayParameterType::BINARY, 'bar' => ArrayParameterType::BINARY], - 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar IN (?, ?)', - [hex2bin('DEADBEEF'), hex2bin('C0DEF00D'), hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], - [ - ParameterType::BINARY, - ParameterType::BINARY, - ParameterType::BINARY, - ParameterType::BINARY, - ], + ['foo' => ArrayParameterType::BINARY, 'bar' => ArrayParameterType::BINARY], + 'SELECT * FROM Foo WHERE foo IN (?, ?) OR bar IN (?, ?)', + [hex2bin('DEADBEEF'), hex2bin('C0DEF00D'), hex2bin('DEADBEEF'), hex2bin('C0DEF00D')], + [ + ParameterType::BINARY, + ParameterType::BINARY, + ParameterType::BINARY, + ParameterType::BINARY, ], ]; } @@ -364,30 +392,31 @@ public function testExpandListParameters( self::assertEquals($expectedTypes, $types, 'Types dont match'); } - /** @return mixed[][] */ + /** @return iterable */ public static function missingNamedParameterProvider(): iterable { - return [ - [ - 'SELECT * FROM foo WHERE bar = :param', - ['other' => 'val'], - [], - ], - [ - 'SELECT * FROM foo WHERE bar = :param', - [], - [], - ], - [ - 'SELECT * FROM foo WHERE bar = :param', - [], - ['bar' => ArrayParameterType::INTEGER], - ], - [ - 'SELECT * FROM foo WHERE bar = :param', - ['bar' => 'value'], - ['bar' => ArrayParameterType::INTEGER], - ], + yield [ + 'SELECT * FROM foo WHERE bar = :param', + ['other' => 'val'], + [], + ]; + + yield [ + 'SELECT * FROM foo WHERE bar = :param', + [], + [], + ]; + + yield [ + 'SELECT * FROM foo WHERE bar = :param', + [], + ['bar' => ArrayParameterType::INTEGER], + ]; + + yield [ + 'SELECT * FROM foo WHERE bar = :param', + ['bar' => 'value'], + ['bar' => ArrayParameterType::INTEGER], ]; } @@ -416,18 +445,17 @@ public function testMissingPositionalParameter(string $query, array $params): vo $this->expandArrayParameters($query, $params, []); } - /** @return mixed[][] */ + /** @return iterable */ public static function missingPositionalParameterProvider(): iterable { - return [ - 'No parameters' => [ - 'SELECT * FROM foo WHERE bar = ?', - [], - ], - 'Too few parameters' => [ - 'SELECT * FROM foo WHERE bar = ? AND baz = ?', - [1], - ], + yield 'No parameters' => [ + 'SELECT * FROM foo WHERE bar = ?', + [], + ]; + + yield 'Too few parameters' => [ + 'SELECT * FROM foo WHERE bar = ? AND baz = ?', + [1], ]; }