Make sure that the $types array has the same keys $params

This will allow to omit parameters with unspecified types
parent 9e880d97
......@@ -4,7 +4,9 @@ namespace Doctrine\DBAL;
use const PREG_OFFSET_CAPTURE;
use function array_fill;
use function array_fill_keys;
use function array_key_exists;
use function array_keys;
use function array_merge;
use function array_slice;
use function array_values;
......@@ -131,6 +133,10 @@ class SQLParserUtils
$bindIndex = -1;
if ($isPositional) {
// make sure that $types has the same keys as $params
// to allow omitting parameters with unspecified types
$types += array_fill_keys(array_keys($params), null);
ksort($params);
ksort($types);
}
......
......@@ -110,8 +110,7 @@ SQLDATA
public static function dataExpandListParameters() : iterable
{
return [
// Positional: Very simple with one needle
[
'Positional: Very simple with one needle' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[1, 2, 3]],
[Connection::PARAM_INT_ARRAY],
......@@ -119,8 +118,7 @@ SQLDATA
[1, 2, 3],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
// Positional: One non-list before d one after list-needle
[
'Positional: One non-list before d one after list-needle' => [
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?)',
['string', [1, 2, 3]],
[ParameterType::STRING, Connection::PARAM_INT_ARRAY],
......@@ -128,8 +126,7 @@ SQLDATA
['string', 1, 2, 3],
[ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
// Positional: One non-list after list-needle
[
'Positional: One non-list after list-needle' => [
'SELECT * FROM Foo WHERE bar IN (?) AND baz = ?',
[[1, 2, 3], 'foo'],
[Connection::PARAM_INT_ARRAY, ParameterType::STRING],
......@@ -137,8 +134,7 @@ SQLDATA
[1, 2, 3, 'foo'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
],
// Positional: One non-list before and one after list-needle
[
'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, Connection::PARAM_INT_ARRAY, ParameterType::INTEGER],
......@@ -152,8 +148,7 @@ SQLDATA
ParameterType::INTEGER,
],
],
// Positional: Two lists
[
'Positional: Two lists' => [
'SELECT * FROM Foo WHERE foo IN (?, ?)',
[[1, 2, 3], [4, 5]],
[Connection::PARAM_INT_ARRAY, Connection::PARAM_INT_ARRAY],
......@@ -167,8 +162,7 @@ SQLDATA
ParameterType::INTEGER,
],
],
// Positional: Empty "integer" array DDC-1978
[
'Positional: Empty "integer" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[]],
[Connection::PARAM_INT_ARRAY],
......@@ -176,8 +170,7 @@ SQLDATA
[],
[],
],
// Positional: Empty "str" array DDC-1978
[
'Positional: Empty "str" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (?)',
[[]],
[Connection::PARAM_STR_ARRAY],
......@@ -185,17 +178,15 @@ SQLDATA
[],
[],
],
// Positional: explicit keys for params and types
[
'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],
[1 => ParameterType::STRING, 2 => ParameterType::STRING, 0 => null],
],
// Positional: explicit keys for array params and array types
[
'Positional: explicit keys for array params and array types' => [
'SELECT * FROM Foo WHERE foo IN (?) AND bar IN (?) AND baz = ?',
[1 => ['bar1', 'bar2'], 2 => true, 0 => [1, 2, 3]],
[2 => ParameterType::BOOLEAN, 1 => Connection::PARAM_STR_ARRAY, 0 => Connection::PARAM_INT_ARRAY],
......@@ -210,8 +201,7 @@ SQLDATA
ParameterType::BOOLEAN,
],
],
// Positional starts from 1: One non-list before and one after list-needle
[
'Positional starts from 1: One non-list before and one after list-needle' => [
'SELECT * FROM Foo WHERE foo = ? AND bar IN (?) AND baz = ? AND foo IN (?)',
[1 => 1, 2 => [1, 2, 3], 3 => 4, 4 => [5, 6]],
[
......@@ -232,8 +222,7 @@ SQLDATA
ParameterType::INTEGER,
],
],
// Named parameters : Very simple with param int
[
'Named: Very simple with param int' => [
'SELECT * FROM Foo WHERE foo = :foo',
['foo' => 1],
['foo' => ParameterType::INTEGER],
......@@ -241,9 +230,7 @@ SQLDATA
[1],
[ParameterType::INTEGER],
],
// Named parameters : Very simple with param int and string
[
'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],
......@@ -251,8 +238,7 @@ SQLDATA
[1,'Some String'],
[ParameterType::INTEGER, ParameterType::STRING],
],
// Named parameters : Very simple with one needle
[
'Named: Very simple with one needle' => [
'SELECT * FROM Foo WHERE foo IN (:foo)',
['foo' => [1, 2, 3]],
['foo' => Connection::PARAM_INT_ARRAY],
......@@ -260,8 +246,7 @@ SQLDATA
[1, 2, 3],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
// Named parameters: One non-list before d one after list-needle
[
'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' => Connection::PARAM_INT_ARRAY],
......@@ -269,8 +254,7 @@ SQLDATA
['string', 1, 2, 3],
[ParameterType::STRING, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
// Named parameters: One non-list after list-needle
[
'Named: One non-list after list-needle' => [
'SELECT * FROM Foo WHERE bar IN (:bar) AND baz = :baz',
['bar' => [1, 2, 3], 'baz' => 'foo'],
['bar' => Connection::PARAM_INT_ARRAY, 'baz' => ParameterType::STRING],
......@@ -278,26 +262,39 @@ SQLDATA
[1, 2, 3, 'foo'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
],
// Named parameters: One non-list before and one after list-needle
[
'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' => Connection::PARAM_INT_ARRAY, 'foo' => ParameterType::INTEGER, 'baz' => ParameterType::INTEGER],
[
'bar' => Connection::PARAM_INT_ARRAY,
'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],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
],
],
// Named parameters: Two lists
[
'Named: Two lists' => [
'SELECT * FROM Foo WHERE foo IN (:a, :b)',
['b' => [4, 5],'a' => [1, 2, 3]],
['a' => Connection::PARAM_INT_ARRAY, 'b' => Connection::PARAM_INT_ARRAY],
'SELECT * FROM Foo WHERE foo IN (?, ?, ?, ?, ?)',
[1, 2, 3, 4, 5],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
],
],
// Named parameters : With the same name arg type string
[
'Named: With the same name arg type string' => [
'SELECT * FROM Foo WHERE foo <> :arg AND bar = :arg',
['arg' => 'Some String'],
['arg' => ParameterType::STRING],
......@@ -305,18 +302,22 @@ SQLDATA
['Some String','Some String'],
[ParameterType::STRING,ParameterType::STRING],
],
// Named parameters : With the same name arg
[
'Named: With the same name arg' => [
'SELECT * FROM Foo WHERE foo IN (:arg) AND NOT bar IN (:arg)',
['arg' => [1, 2, 3]],
['arg' => Connection::PARAM_INT_ARRAY],
'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],
[
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
],
],
// Named parameters : Same name, other name in between DBAL-299
[
'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],
......@@ -324,8 +325,7 @@ SQLDATA
[2, 3, 2],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::INTEGER],
],
// Named parameters : Empty "integer" array DDC-1978
[
'Named: Empty "integer" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (:foo)',
['foo' => []],
['foo' => Connection::PARAM_INT_ARRAY],
......@@ -333,8 +333,7 @@ SQLDATA
[],
[],
],
// Named parameters : Two empty "str" array DDC-1978
[
'Named: Two empty "str" array (DDC-1978)' => [
'SELECT * FROM Foo WHERE foo IN (:foo) OR bar IN (:bar)',
['foo' => [], 'bar' => []],
['foo' => Connection::PARAM_STR_ARRAY, 'bar' => Connection::PARAM_STR_ARRAY],
......@@ -358,8 +357,7 @@ SQLDATA
[1, 2, 'bar'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
],
// Params/types with colons
[
'Params/types with colons' => [
'SELECT * FROM Foo WHERE foo = :foo OR bar = :bar',
[':foo' => 'foo', ':bar' => 'bar'],
[':foo' => ParameterType::INTEGER],
......@@ -391,8 +389,7 @@ SQLDATA
[1, 2, 'bar'],
[ParameterType::INTEGER, ParameterType::INTEGER, ParameterType::STRING],
],
// DBAL-522 - null valued parameters are not considered
[
'Null valued parameters (DBAL-522)' => [
'INSERT INTO Foo (foo, bar) values (:foo, :bar)',
['foo' => 1, 'bar' => null],
[':foo' => ParameterType::INTEGER, ':bar' => ParameterType::NULL],
......@@ -408,8 +405,7 @@ SQLDATA
[1, null],
[ParameterType::INTEGER, ParameterType::NULL],
],
// DBAL-1205 - Escaped single quotes SQL- and C-Style
[
'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],
......@@ -417,6 +413,14 @@ SQLDATA
[1, 2],
[ParameterType::INTEGER, ParameterType::INTEGER],
],
[
'SELECT NULL FROM dummy WHERE ? IN (?)',
['foo', ['bar', 'baz']],
[1 => Connection::PARAM_STR_ARRAY],
'SELECT NULL FROM dummy WHERE ? IN (?, ?)',
['foo', 'bar', 'baz'],
[null, ParameterType::STRING, ParameterType::STRING],
],
];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment