diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63bf93448..34e983ff2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
## 1.1.2 under development
+- Enh #746: Refactor `AbstractDMLQueryBuilder` (@Tigrov)
+- Bug #746: Fix `AbstractDMLQueryBuilder::upsert()` when unique index is not at the first position of inserted values (@Tigrov)
+- Bug #746: Typecast values in `AbstractDMLQueryBuilder::batchInsert()` if column names with table name and brackets (@Tigrov)
+- Bug #746, #61: Typecast values in `AbstractDMLQueryBuilder::batchInsert()` if values with string keys (@Tigrov)
+- Enh #746: Enhanced documentation of `batchInsert()` and `update()` methods of `DMLQueryBuilderInterface` interface (@Tigrov)
- Bug #751: Fix collected debug actions (@xepozz)
- Chg #755: Deprecate `TableSchemaInterface::compositeForeignKey()` (@Tigrov)
- Enh #756: Refactor `Quoter` (@Tigrov)
diff --git a/psalm.xml b/psalm.xml
index 23bfcce17..54a52e176 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -14,4 +14,7 @@
+
+
+
diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php
index 955e28c3b..9c3244201 100644
--- a/src/Command/CommandInterface.php
+++ b/src/Command/CommandInterface.php
@@ -177,6 +177,8 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
* @throws Exception
* @throws InvalidArgumentException
*
+ * @psalm-param iterable> $rows
+ *
* Note: The method will quote the `table` and `column` parameters before using them in the generated SQL.
*/
public function batchInsert(string $table, array $columns, iterable $rows): static;
@@ -820,6 +822,8 @@ public function update(string $table, array $columns, array|string $condition =
* @throws JsonException
* @throws NotSupportedException
*
+ * @psalm-param array|QueryInterface $insertColumns
+ *
* Note: The method will quote the `table` and `insertColumns`, `updateColumns` parameters before using it in the
* generated SQL.
*/
diff --git a/src/QueryBuilder/AbstractDMLQueryBuilder.php b/src/QueryBuilder/AbstractDMLQueryBuilder.php
index fad42c957..1224e503f 100644
--- a/src/QueryBuilder/AbstractDMLQueryBuilder.php
+++ b/src/QueryBuilder/AbstractDMLQueryBuilder.php
@@ -4,7 +4,6 @@
namespace Yiisoft\Db\QueryBuilder;
-use Generator;
use JsonException;
use Yiisoft\Db\Constraint\Constraint;
use Yiisoft\Db\Constraint\IndexConstraint;
@@ -26,10 +25,8 @@
use function array_merge;
use function array_unique;
use function array_values;
-use function count;
use function implode;
use function in_array;
-use function is_array;
use function is_string;
use function json_encode;
use function preg_match;
@@ -52,28 +49,23 @@ public function __construct(
) {
}
- public function batchInsert(string $table, array $columns, iterable|Generator $rows, array &$params = []): string
+ public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string
{
if (empty($rows)) {
return '';
}
- if (($tableSchema = $this->schema->getTableSchema($table)) !== null) {
- $columnSchemas = $tableSchema->getColumns();
- } else {
- $columnSchemas = [];
- }
-
- $mappedNames = $this->getNormalizeColumnNames($table, $columns);
$values = [];
+ $columns = $this->getNormalizeColumnNames('', $columns);
+ $columnSchemas = $this->schema->getTableSchema($table)?->getColumns() ?? [];
- /** @psalm-var array> $rows */
foreach ($rows as $row) {
+ $i = 0;
$placeholders = [];
- foreach ($row as $index => $value) {
- if (isset($columns[$index], $mappedNames[$columns[$index]], $columnSchemas[$mappedNames[$columns[$index]]])) {
- /** @psalm-var mixed $value */
- $value = $this->getTypecastValue($value, $columnSchemas[$mappedNames[$columns[$index]]]);
+
+ foreach ($row as $value) {
+ if (isset($columns[$i], $columnSchemas[$columns[$i]])) {
+ $value = $columnSchemas[$columns[$i]]->dbTypecast($value);
}
if ($value instanceof ExpressionInterface) {
@@ -81,6 +73,8 @@ public function batchInsert(string $table, array $columns, iterable|Generator $r
} else {
$placeholders[] = $this->queryBuilder->bindParam($value, $params);
}
+
+ ++$i;
}
$values[] = '(' . implode(', ', $placeholders) . ')';
}
@@ -89,12 +83,12 @@ public function batchInsert(string $table, array $columns, iterable|Generator $r
return '';
}
- foreach ($columns as $i => $name) {
- $columns[$i] = $this->quoter->quoteColumnName($mappedNames[$name]);
- }
+ $columns = array_map(
+ [$this->quoter, 'quoteColumnName'],
+ $columns,
+ );
- return 'INSERT INTO '
- . $this->quoter->quoteTableName($table)
+ return 'INSERT INTO ' . $this->quoter->quoteTableName($table)
. ' (' . implode(', ', $columns) . ') VALUES ' . implode(', ', $values);
}
@@ -108,17 +102,11 @@ public function delete(string $table, array|string $condition, array &$params):
public function insert(string $table, QueryInterface|array $columns, array &$params = []): string
{
- /**
- * @psalm-var string[] $names
- * @psalm-var string[] $placeholders
- * @psalm-var string $values
- */
[$names, $placeholders, $values, $params] = $this->prepareInsertValues($table, $columns, $params);
- return 'INSERT INTO '
- . $this->quoter->quoteTableName($table)
+ return 'INSERT INTO ' . $this->quoter->quoteTableName($table)
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
- . (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : $values);
+ . (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' ' . $values);
}
public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
@@ -133,10 +121,9 @@ public function resetSequence(string $table, int|string|null $value = null): str
public function update(string $table, array $columns, array|string $condition, array &$params = []): string
{
- /** @psalm-var string[] $lines */
[$lines, $params] = $this->prepareUpdateSets($table, $columns, $params);
+
$sql = 'UPDATE ' . $this->quoter->quoteTableName($table) . ' SET ' . implode(', ', $lines);
- /** @psalm-var array $params */
$where = $this->queryBuilder->buildWhere($condition, $params);
return $where === '' ? $sql : $sql . ' ' . $where;
@@ -163,20 +150,21 @@ public function upsert(
* @throws InvalidConfigException
* @throws NotSupportedException
*
- * @return array Array of column names, values, and params.
+ * @return array Array of quoted column names, values, and params.
+ * @psalm-return array{0: string[], 1: string, 2: array}
*/
protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $params = []): array
{
- if (empty($columns->getSelect()) || in_array('*', $columns->getSelect(), true)) {
+ /** @psalm-var string[] $select */
+ $select = $columns->getSelect();
+
+ if (empty($select) || in_array('*', $select, true)) {
throw new InvalidArgumentException('Expected select query object with enumerated (named) parameters');
}
[$values, $params] = $this->queryBuilder->build($columns, $params);
$names = [];
- $values = ' ' . $values;
- /** @psalm-var string[] $select */
- $select = $columns->getSelect();
foreach ($select as $title => $field) {
if (is_string($title)) {
@@ -204,37 +192,41 @@ protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $p
* @throws InvalidConfigException
* @throws InvalidArgumentException
* @throws NotSupportedException
+ *
+ * @return array Array of quoted column names, placeholders, values, and params.
+ * @psalm-return array{0: string[], 1: string[], 2: string, 3: array}
*/
protected function prepareInsertValues(string $table, array|QueryInterface $columns, array $params = []): array
{
- $tableSchema = $this->schema->getTableSchema($table);
- $columnSchemas = $tableSchema !== null ? $tableSchema->getColumns() : [];
- $names = [];
- $placeholders = [];
- $values = ' DEFAULT VALUES';
+ if (empty($columns)) {
+ return [[], [], 'DEFAULT VALUES', []];
+ }
if ($columns instanceof QueryInterface) {
[$names, $values, $params] = $this->prepareInsertSelectSubQuery($columns, $params);
- } else {
- $columns = $this->normalizeColumnNames($table, $columns);
- /**
- * @psalm-var mixed $value
- * @psalm-var array $columns
- */
- foreach ($columns as $name => $value) {
- $names[] = $this->quoter->quoteColumnName($name);
- /** @var mixed $value */
- $value = $this->getTypecastValue($value, $columnSchemas[$name] ?? null);
+ return [$names, [], $values, $params];
+ }
- if ($value instanceof ExpressionInterface) {
- $placeholders[] = $this->queryBuilder->buildExpression($value, $params);
- } else {
- $placeholders[] = $this->queryBuilder->bindParam($value, $params);
- }
+ $names = [];
+ $placeholders = [];
+ $columns = $this->normalizeColumnNames('', $columns);
+ $columnSchemas = $this->schema->getTableSchema($table)?->getColumns() ?? [];
+
+ foreach ($columns as $name => $value) {
+ $names[] = $this->quoter->quoteColumnName($name);
+
+ if (isset($columnSchemas[$name])) {
+ $value = $columnSchemas[$name]->dbTypecast($value);
+ }
+
+ if ($value instanceof ExpressionInterface) {
+ $placeholders[] = $this->queryBuilder->buildExpression($value, $params);
+ } else {
+ $placeholders[] = $this->queryBuilder->bindParam($value, $params);
}
}
- return [$names, $placeholders, $values, $params];
+ return [$names, $placeholders, '', $params];
}
/**
@@ -244,21 +236,20 @@ protected function prepareInsertValues(string $table, array|QueryInterface $colu
* @throws InvalidConfigException
* @throws InvalidArgumentException
* @throws NotSupportedException
+ *
+ * @psalm-return array{0: string[], 1: array}
*/
protected function prepareUpdateSets(string $table, array $columns, array $params = []): array
{
- $tableSchema = $this->schema->getTableSchema($table);
- $columnSchemas = $tableSchema !== null ? $tableSchema->getColumns() : [];
$sets = [];
- $columns = $this->normalizeColumnNames($table, $columns);
+ $columns = $this->normalizeColumnNames('', $columns);
+ $columnSchemas = $this->schema->getTableSchema($table)?->getColumns() ?? [];
- /**
- * @psalm-var array $columns
- * @psalm-var mixed $value
- */
foreach ($columns as $name => $value) {
- /** @psalm-var mixed $value */
- $value = isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
+ if (isset($columnSchemas[$name])) {
+ $value = $columnSchemas[$name]->dbTypecast($value);
+ }
+
if ($value instanceof ExpressionInterface) {
$placeholder = $this->queryBuilder->buildExpression($value, $params);
} else {
@@ -272,7 +263,7 @@ protected function prepareUpdateSets(string $table, array $columns, array $param
}
/**
- * Prepare column names and placeholders for "upsert" operation.
+ * Prepare column names and constraints for "upsert" operation.
*
* @throws Exception
* @throws InvalidArgumentException
@@ -280,7 +271,11 @@ protected function prepareUpdateSets(string $table, array $columns, array $param
* @throws JsonException
* @throws NotSupportedException
*
+ * @psalm-param array|QueryInterface $insertColumns
* @psalm-param Constraint[] $constraints
+ *
+ * @return array Array of unique, insert and update quoted column names.
+ * @psalm-return array{0: string[], 1: string[], 2: string[]|null}
*/
protected function prepareUpsertColumns(
string $table,
@@ -288,42 +283,28 @@ protected function prepareUpsertColumns(
QueryInterface|bool|array $updateColumns,
array &$constraints = []
): array {
- $insertNames = [];
-
- if (!$insertColumns instanceof QueryInterface) {
- $insertColumns = $this->normalizeColumnNames($table, $insertColumns);
- }
-
- if (is_array($updateColumns)) {
- $updateColumns = $this->normalizeColumnNames($table, $updateColumns);
- }
-
if ($insertColumns instanceof QueryInterface) {
- /** @psalm-var list $insertNames */
[$insertNames] = $this->prepareInsertSelectSubQuery($insertColumns);
} else {
- /** @psalm-var array $insertColumns */
- foreach ($insertColumns as $key => $_value) {
- $insertNames[] = $this->quoter->quoteColumnName($key);
- }
+ $insertNames = $this->getNormalizeColumnNames('', array_keys($insertColumns));
+
+ $insertNames = array_map(
+ [$this->quoter, 'quoteColumnName'],
+ $insertNames,
+ );
}
- /** @psalm-var string[] $uniqueNames */
$uniqueNames = $this->getTableUniqueColumnNames($table, $insertNames, $constraints);
- foreach ($uniqueNames as $key => $name) {
- $insertNames[$key] = $this->quoter->quoteColumnName($name);
+ if ($updateColumns === true) {
+ return [$uniqueNames, $insertNames, array_diff($insertNames, $uniqueNames)];
}
- if ($updateColumns !== true) {
- return [$uniqueNames, $insertNames, null];
- }
-
- return [$uniqueNames, $insertNames, array_diff($insertNames, $uniqueNames)];
+ return [$uniqueNames, $insertNames, null];
}
/**
- * Returns all column names belonging to constraints enforcing uniqueness (`PRIMARY KEY`, `UNIQUE INDEX`, etc.)
+ * Returns all quoted column names belonging to constraints enforcing uniqueness (`PRIMARY KEY`, `UNIQUE INDEX`, etc.)
* for the named table removing constraints which didn't cover the specified column list.
*
* The column list will be unique by column names.
@@ -335,7 +316,7 @@ protected function prepareUpsertColumns(
*
* @throws JsonException
*
- * @return array The column list.
+ * @return string[] The quoted column names.
*
* @psalm-param Constraint[] $constraints
*/
@@ -365,9 +346,8 @@ private function getTableUniqueColumnNames(string $name, array $columns, array &
*/
$constraints = array_combine(
array_map(
- static function (Constraint $constraint) {
- $columns = $constraint->getColumnNames() ?? [];
- $columns = is_array($columns) ? $columns : [$columns];
+ static function (Constraint $constraint): string {
+ $columns = (array) $constraint->getColumnNames();
sort($columns, SORT_STRING);
return json_encode($columns, JSON_THROW_ON_ERROR);
},
@@ -383,18 +363,16 @@ static function (Constraint $constraint) {
$constraints = array_values(
array_filter(
$constraints,
- static function (Constraint $constraint) use ($quoter, $columns, &$columnNames) {
- /** @psalm-var string[]|string $getColumnNames */
- $getColumnNames = $constraint->getColumnNames() ?? [];
- $constraintColumnNames = [];
-
- if (is_array($getColumnNames)) {
- foreach ($getColumnNames as $columnName) {
- $constraintColumnNames[] = $quoter->quoteColumnName($columnName);
- }
- }
+ static function (Constraint $constraint) use ($quoter, $columns, &$columnNames): bool {
+ /** @psalm-var string[] $constraintColumnNames */
+ $constraintColumnNames = (array) $constraint->getColumnNames();
+
+ $constraintColumnNames = array_map(
+ [$quoter, 'quoteColumnName'],
+ $constraintColumnNames,
+ );
- $result = !array_diff($constraintColumnNames, $columns);
+ $result = empty(array_diff($constraintColumnNames, $columns));
if ($result) {
$columnNames = array_merge((array) $columnNames, $constraintColumnNames);
@@ -405,12 +383,14 @@ static function (Constraint $constraint) use ($quoter, $columns, &$columnNames)
)
);
- /** @psalm-var Constraint[] $columnNames */
+ /** @psalm-var string[] $columnNames */
return array_unique($columnNames);
}
/**
* @return mixed The typecast value of the given column.
+ *
+ * @deprecated will be removed in version 2.0.0
*/
protected function getTypecastValue(mixed $value, ColumnSchemaInterface $columnSchema = null): mixed
{
@@ -422,61 +402,39 @@ protected function getTypecastValue(mixed $value, ColumnSchemaInterface $columnS
}
/**
- * Normalizes the column names for the given table.
+ * Normalizes the column names.
*
- * @param string $table The table to save the data into.
- * @param array $columns The column data (name => value) to save into the table or instance of
- * {@see QueryInterface} to perform `INSERT INTO ... SELECT` SQL statement. Passing of {@see QueryInterface}.
+ * @param string $table Not used. Could be empty string. Will be removed in version 2.0.0.
+ * @param array $columns The column data (name => value).
*
* @return array The normalized column names (name => value).
+ *
+ * @psalm-return array
*/
protected function normalizeColumnNames(string $table, array $columns): array
{
- /** @var string[] $columnList */
- $columnList = array_keys($columns);
- $mappedNames = $this->getNormalizeColumnNames($table, $columnList);
-
- /** @psalm-var array $normalizedColumns */
- $normalizedColumns = [];
-
- /**
- * @psalm-var string $name
- * @psalm-var mixed $value
- */
- foreach ($columns as $name => $value) {
- $mappedName = $mappedNames[$name] ?? $name;
- /** @psalm-var mixed */
- $normalizedColumns[$mappedName] = $value;
- }
+ /** @var string[] $columnNames */
+ $columnNames = array_keys($columns);
+ $normalizedNames = $this->getNormalizeColumnNames('', $columnNames);
- return $normalizedColumns;
+ return array_combine($normalizedNames, $columns);
}
/**
- * Get a map of normalized columns
+ * Get normalized column names
*
- * @param string $table The table to save the data into.
- * @param string[] $columns The column data (name => value) to save into the table or instance of
- * {@see QueryInterface} to perform `INSERT INTO ... SELECT` SQL statement. Passing of {@see QueryInterface}.
+ * @param string $table Not used. Could be empty string. Will be removed in version 2.0.0.
+ * @param string[] $columns The column names.
*
- * @return string[] Map of normalized columns.
+ * @return string[] Normalized column names.
*/
protected function getNormalizeColumnNames(string $table, array $columns): array
{
$normalizedNames = [];
- $rawTableName = $this->schema->getRawTableName($table);
foreach ($columns as $name) {
- $parts = $this->quoter->getTableNameParts($name, true);
-
- if (count($parts) === 2 && $this->schema->getRawTableName($parts[0]) === $rawTableName) {
- $normalizedName = $parts[count($parts) - 1];
- } else {
- $normalizedName = $name;
- }
- $normalizedName = $this->quoter->ensureColumnName($normalizedName);
-
- $normalizedNames[$name] = $normalizedName;
+ $normalizedName = $this->quoter->ensureColumnName($name);
+ $normalizedNames[] = $this->quoter->unquoteSimpleColumnName($normalizedName);
}
return $normalizedNames;
diff --git a/src/QueryBuilder/AbstractQueryBuilder.php b/src/QueryBuilder/AbstractQueryBuilder.php
index f93c13bc9..53971f27b 100644
--- a/src/QueryBuilder/AbstractQueryBuilder.php
+++ b/src/QueryBuilder/AbstractQueryBuilder.php
@@ -4,7 +4,6 @@
namespace Yiisoft\Db\QueryBuilder;
-use Generator;
use Yiisoft\Db\Command\CommandInterface;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Query\QueryInterface;
@@ -109,7 +108,7 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
return $this->ddlBuilder->alterColumn($table, $column, $type);
}
- public function batchInsert(string $table, array $columns, iterable|Generator $rows, array &$params = []): string
+ public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string
{
return $this->dmlBuilder->batchInsert($table, $columns, $rows, $params);
}
diff --git a/src/QueryBuilder/DMLQueryBuilderInterface.php b/src/QueryBuilder/DMLQueryBuilderInterface.php
index 060682381..fdac752aa 100644
--- a/src/QueryBuilder/DMLQueryBuilderInterface.php
+++ b/src/QueryBuilder/DMLQueryBuilderInterface.php
@@ -4,7 +4,6 @@
namespace Yiisoft\Db\QueryBuilder;
-use Generator;
use JsonException;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
@@ -33,8 +32,8 @@ interface DMLQueryBuilderInterface
* ```
*
* @param string $table The table to insert new rows into.
- * @param string[] $columns The column names.
- * @param Generator|iterable $rows The rows to batch-insert into the table.
+ * @param string[] $columns The column names of the table.
+ * @param iterable $rows The rows to batch-insert into the table.
* @param array $params The binding parameters. This parameter exists.
*
* @throws Exception
@@ -43,12 +42,13 @@ interface DMLQueryBuilderInterface
* @return string The batch INSERT SQL statement.
*
* @psalm-param string[] $columns
+ * @psalm-param iterable> $rows
*
* Note:
* - That the values in each row must match the corresponding column names.
* - The method will escape the column names, and quote the values to insert.
*/
- public function batchInsert(string $table, array $columns, iterable|Generator $rows, array &$params = []): string;
+ public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string;
/**
* Creates a `DELETE` SQL statement.
@@ -149,7 +149,7 @@ public function resetSequence(string $table, int|string|null $value = null): str
* ```
*
* @param string $table The table to update.
- * @param array $columns The column data (name => value) to update.
+ * @param array $columns The column data (name => value) to update the table.
* @param array|string $condition The condition to put in the `WHERE` part. Please refer to
* {@see Query::where()} On how to specify condition.
* @param array $params The binding parameters that will be modified by this method so that they can be bound to
@@ -194,6 +194,8 @@ public function update(string $table, array $columns, array|string $condition, a
* @throws JsonException
* @throws NotSupportedException If this isn't supported by the underlying DBMS.
*
+ * @psalm-param array|QueryInterface $insertColumns
+ *
* Note: The method will escape the table and column names.
*/
public function upsert(
diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php
index 31de64c71..d6de07f63 100644
--- a/tests/AbstractQueryBuilderTest.php
+++ b/tests/AbstractQueryBuilderTest.php
@@ -5,7 +5,6 @@
namespace Yiisoft\Db\Tests;
use Closure;
-use Generator;
use JsonException;
use PHPUnit\Framework\TestCase;
use stdClass;
@@ -211,7 +210,7 @@ public function testAlterColumn(): void
*
* @psalm-param array $columns
*/
- public function testBatchInsert(string $table, array $columns, iterable|Generator $rows, string $expected): void
+ public function testBatchInsert(string $table, array $columns, iterable $rows, string $expected): void
{
$db = $this->getConnection();
diff --git a/tests/Db/QueryBuilder/QueryBuilderTest.php b/tests/Db/QueryBuilder/QueryBuilderTest.php
index 79a1e382b..93356917f 100644
--- a/tests/Db/QueryBuilder/QueryBuilderTest.php
+++ b/tests/Db/QueryBuilder/QueryBuilderTest.php
@@ -4,7 +4,6 @@
namespace Yiisoft\Db\Tests\Db\QueryBuilder;
-use Generator;
use JsonException;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
@@ -48,7 +47,7 @@ public function testAddDefaultValue(): void
/**
* @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::batchInsert
*/
- public function testBatchInsert(string $table, array $columns, iterable|Generator $rows, string $expected): void
+ public function testBatchInsert(string $table, array $columns, iterable $rows, string $expected): void
{
$db = $this->getConnection();
diff --git a/tests/Provider/CommandProvider.php b/tests/Provider/CommandProvider.php
index 7f6999d80..5d2ae6176 100644
--- a/tests/Provider/CommandProvider.php
+++ b/tests/Provider/CommandProvider.php
@@ -301,16 +301,10 @@ public static function batchInsert(): array
':qp3' => true,
],
],
- 'wrongBehavior' => [
+ 'table name with column name with brackets' => [
'{{%type}}',
['{{%type}}.[[int_col]]', '[[float_col]]', 'char_col', 'bool_col'],
'values' => [['0', '0.0', 'Kyiv {{city}}, Ukraine', false]],
- /**
- * Test covers potentially wrong behavior and marks it as expected!.
- *
- * In case table name or table column is passed with curly or square bracelets, QueryBuilder can not
- * determine the table schema and typecast values properly.
- */
'expected' => DbHelper::replaceQuotes(
<< [
- ':qp0' => '0',
- ':qp1' => '0.0',
+ ':qp0' => 0,
+ ':qp1' => 0.0,
':qp2' => 'Kyiv {{city}}, Ukraine',
':qp3' => false,
],
@@ -345,6 +339,23 @@ public static function batchInsert(): array
':qp3' => false,
],
],
+ 'with associative values' => [
+ 'type',
+ ['int_col', 'float_col', 'char_col', 'bool_col'],
+ 'values' => [['int' => '1.0', 'float' => '2', 'char' => 10, 'bool' => 1]],
+ 'expected' => DbHelper::replaceQuotes(
+ << [
+ ':qp0' => 1,
+ ':qp1' => 2.0,
+ ':qp2' => '10',
+ ':qp3' => true,
+ ],
+ ],
];
}
diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php
index 0871a113b..8e04fc7b5 100644
--- a/tests/Provider/QueryBuilderProvider.php
+++ b/tests/Provider/QueryBuilderProvider.php
@@ -213,6 +213,18 @@ public static function batchInsert(): array
),
[':qp0' => null],
],
+ 'column table names are not checked' => [
+ '{{%type}}',
+ ['{{%type}}.[[bool_col]]', '{{%another_table}}.[[bool_col2]]'],
+ [[true, false]],
+ 'expected' => DbHelper::replaceQuotes(
+ << null, ':qp1' => null],
+ ],
'empty-sql' => [
'{{%type}}',
[],
@@ -1107,6 +1119,13 @@ public static function upsert(): array
'',
[':qp0' => 'test@example.com', ':qp1' => 'bar {{city}}', ':qp2' => 1, ':qp3' => null],
],
+ 'regular values with unique at not the first position' => [
+ 'T_upsert',
+ ['address' => 'bar {{city}}', 'email' => 'test@example.com', 'status' => 1, 'profile_id' => null],
+ true,
+ '',
+ [':qp0' => 'bar {{city}}', ':qp1' => 'test@example.com', ':qp2' => 1, ':qp3' => null],
+ ],
'regular values with update part' => [
'T_upsert',
['email' => 'test@example.com', 'address' => 'bar {{city}}', 'status' => 1, 'profile_id' => null],