diff --git a/src/Database/Table/SqlBuilder.php b/src/Database/Table/SqlBuilder.php index c708f9d29..0a236e242 100644 --- a/src/Database/Table/SqlBuilder.php +++ b/src/Database/Table/SqlBuilder.php @@ -317,7 +317,8 @@ protected function addCondition($condition, array $params, array &$conditions, a $replace = null; $placeholderNum = 0; - foreach ($params as $arg) { + while (count($params)) { + $arg = array_shift($params); preg_match('#(?:.*?\?.*?){' . $placeholderNum . '}(((?:&|\||^|~|\+|-|\*|/|%|\(|,|<|>|=|(?<=\W|^)(?:REGEXP|ALL|AND|ANY|BETWEEN|EXISTS|IN|[IR]?LIKE|OR|NOT|SOME|INTERVAL))\s*)?(?:\(\?\)|\?))#s', $condition, $match, PREG_OFFSET_CAPTURE); $hasOperator = ($match[1][0] === '?' && $match[1][1] === 0) ? true : !empty($match[2][0]); @@ -353,8 +354,11 @@ protected function addCondition($condition, array $params, array &$conditions, a if ($this->driver->isSupported(ISupplementalDriver::SUPPORT_SUBSELECT)) { $arg = null; - $replace = $match[2][0] . '(' . $clone->getSql() . ')'; - $conditionsParameters = array_merge($conditionsParameters, $clone->getSqlBuilder()->getParameters()); + $subSelectPlaceholderCount = substr_count($clone->getSql(), '?'); + $replace = $match[2][0] . '(' . $clone->getSql() . (!$subSelectPlaceholderCount && count($clone->getSqlBuilder()->getParameters()) === 1 ? ' ?' : '') . ')'; + if (count($clone->getSqlBuilder()->getParameters())) { + array_unshift($params, ...$clone->getSqlBuilder()->getParameters()); + } } else { $arg = []; foreach ($clone as $row) { diff --git a/tests/Database/Table/SqlBuilder.addWhere().phpt b/tests/Database/Table/SqlBuilder.addWhere().phpt index c23f97361..75fc23c37 100644 --- a/tests/Database/Table/SqlBuilder.addWhere().phpt +++ b/tests/Database/Table/SqlBuilder.addWhere().phpt @@ -56,6 +56,16 @@ test(function () use ($context) { // test more Selection as a parameter }); +test(function () use ($context) { // test more Selection as one of more argument + $sqlBuilder = new SqlBuilder('book', $context); + $sqlBuilder->addWhere('id ? AND id ?', $context->table('book')->where('id', 2), $context->table('book_tag')->select('book_id')); + Assert::equal(reformat([ + 'mysql' => 'SELECT * FROM `book` WHERE (`id` IN (?) AND `id` IN (?))', + 'SELECT * FROM [book] WHERE ([id] IN (SELECT [id] FROM [book] WHERE ([id] = ?)) AND [id] IN (SELECT [book_id] FROM [book_tag]))', + ]), $sqlBuilder->buildSelectQuery()); +}); + + test(function () use ($context) { // test more ActiveRow as a parameter $sqlBuilder = new SqlBuilder('book', $context); $books = $context->table('book')->where('id', [1, 2])->fetchPairs('id'); @@ -73,7 +83,7 @@ test(function () use ($context) { // test Selection with parameters as a paramet $schemaSupported = $context->getConnection()->getSupplementalDriver()->isSupported(ISupplementalDriver::SUPPORT_SCHEMA); Assert::equal(reformat([ 'mysql' => 'SELECT * FROM `book` WHERE (`id` IN (?))', - 'SELECT * FROM [book] WHERE ([id] IN (SELECT [id] FROM [book] LEFT JOIN ' . ($schemaSupported ? '[public].[book_tag] ' : '') . '[book_tag] ON [book].[id] = [book_tag].[book_id] HAVING COUNT([book_tag].[tag_id]) >))', + 'SELECT * FROM [book] WHERE ([id] IN (SELECT [id] FROM [book] LEFT JOIN ' . ($schemaSupported ? '[public].[book_tag] ' : '') . '[book_tag] ON [book].[id] = [book_tag].[book_id] HAVING COUNT([book_tag].[tag_id]) > ?))', ]), $sqlBuilder->buildSelectQuery()); Assert::count(1, $sqlBuilder->getParameters()); });