mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-03 22:12:37 +08:00
Fixed excess escaping in Command::batchInsert() (#13236)
This commit is contained in:
@ -19,6 +19,7 @@ Yii Framework 2 Change Log
|
||||
- Enh #14087: Added `yii\web\View::registerCsrfMetaTags()` method that registers CSRF tags dynamically ensuring that caching doesn't interfere (RobinKamps)
|
||||
- Bug #6526: Fixed `yii\db\Command::batchInsert()` casting of double values correctly independent of the locale (cebe, leammas)
|
||||
- Bug #7890: Allow `migrate/mark` to mark history at the point of the base migration (cebe)
|
||||
- Bug #11242: Fixed excess escaping in `yii\db\Command::batchInsert()` (silverfire)
|
||||
- Bug #11825: User can login by cookie only once when `autoRenewCookie` is set to false (shirase, silverfire)
|
||||
- Bug #12860: Fixed possible race conditions in `yii\mutex\FileMutex` (kidol)
|
||||
- Bug #13720: Improve `yii\helpers\FormatConverter::convertDatePhpToIcu()` to handle escaped chars correctly (rob006)
|
||||
|
||||
@ -137,19 +137,43 @@ class Command extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the SQL statement to be executed.
|
||||
* The previous SQL execution (if any) will be cancelled, and [[params]] will be cleared as well.
|
||||
* Specifies the SQL statement to be executed. The SQL statement will be quoted using [[Connection::quoteSql()]].
|
||||
* The previous SQL (if any) will be discarded, and [[params]] will be cleared as well. See [[reset()]]
|
||||
* for details.
|
||||
*
|
||||
* @param string $sql the SQL statement to be set.
|
||||
* @return $this this command instance
|
||||
* @see reset()
|
||||
* @see cancel()
|
||||
*/
|
||||
public function setSql($sql)
|
||||
{
|
||||
if ($sql !== $this->_sql) {
|
||||
$this->cancel();
|
||||
$this->reset();
|
||||
$this->_sql = $this->db->quoteSql($sql);
|
||||
$this->_pendingParams = [];
|
||||
$this->params = [];
|
||||
$this->_refreshTableName = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the SQL statement to be executed. The SQL statement will not be modified in any way.
|
||||
* The previous SQL (if any) will be discarded, and [[params]] will be cleared as well. See [[reset()]]
|
||||
* for details.
|
||||
*
|
||||
* @param string $sql the SQL statement to be set.
|
||||
* @return $this this command instance
|
||||
* @since 2.0.13
|
||||
* @see reset()
|
||||
* @see cancel()
|
||||
*/
|
||||
public function setRawSql($sql)
|
||||
{
|
||||
if ($sql !== $this->_sql) {
|
||||
$this->cancel();
|
||||
$this->reset();
|
||||
$this->_sql = $sql;
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -461,9 +485,16 @@ class Command extends Component
|
||||
*/
|
||||
public function batchInsert($table, $columns, $rows)
|
||||
{
|
||||
$table = $this->db->quoteSql($table);
|
||||
$columns = array_map(function ($column) {
|
||||
return $this->db->quoteSql($column);
|
||||
}, $columns);
|
||||
|
||||
$sql = $this->db->getQueryBuilder()->batchInsert($table, $columns, $rows);
|
||||
|
||||
return $this->setSql($sql);
|
||||
$this->setRawSql($sql);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1081,4 +1112,17 @@ class Command extends Component
|
||||
$this->db->getSchema()->refreshTableSchema($this->_refreshTableName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets [[sql]] and [[params]] properties.
|
||||
*
|
||||
* @since 2.0.13
|
||||
*/
|
||||
protected function reset()
|
||||
{
|
||||
$this->_sql = null;
|
||||
$this->_pendingParams = [];
|
||||
$this->params = [];
|
||||
$this->_refreshTableName = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,6 +368,47 @@ SQL;
|
||||
setlocale(LC_NUMERIC, $locale);
|
||||
}
|
||||
|
||||
public function batchInsertSqlProvider()
|
||||
{
|
||||
return [
|
||||
'issue11242' => [
|
||||
'type',
|
||||
['int_col', 'float_col', 'char_col'],
|
||||
[['', '', 'Kyiv {{city}}, Ukraine']],
|
||||
|
||||
'expected' => "INSERT INTO `type` (`int_col`, `float_col`, `char_col`) VALUES (NULL, NULL, 'Kyiv {{city}}, Ukraine')"
|
||||
// See https://github.com/yiisoft/yii2/issues/11242
|
||||
// Make sure curly bracelets (`{{..}}`) in values will not be escaped
|
||||
],
|
||||
'wrongBehavior' => [
|
||||
'{{%type}}',
|
||||
['{{%type}}.[[int_col]]', '[[float_col]]', 'char_col'],
|
||||
[['', '', 'Kyiv {{city}}, Ukraine']],
|
||||
|
||||
'expected' => "INSERT INTO `type` (`type`.`int_col`, `float_col`, `char_col`) VALUES ('', '', 'Kyiv {{city}}, Ukraine')"
|
||||
/* 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.
|
||||
* TODO: make it work. Impossible without BC breaking for public methods.
|
||||
*/
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that `{{something}}` in values will not be encoded
|
||||
* https://github.com/yiisoft/yii2/issues/11242
|
||||
*
|
||||
* @dataProvider batchInsertSqlProvider
|
||||
*/
|
||||
public function testBatchInsertSQL($table, $columns, $values, $expected)
|
||||
{
|
||||
$command = $this->getConnection()->createCommand();
|
||||
$command->batchInsert($table, $columns, $values);
|
||||
$this->assertEquals($expected, $command->getSql());
|
||||
|
||||
}
|
||||
|
||||
public function testInsert()
|
||||
{
|
||||
$db = $this->getConnection();
|
||||
|
||||
@ -84,6 +84,15 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
|
||||
$this->assertEquals('SELECT "id", "t"."name" FROM "customer" t', $command->sql);
|
||||
}
|
||||
|
||||
public function batchInsertSqlProvider()
|
||||
{
|
||||
$data = parent::batchInsertSqlProvider();
|
||||
$data['issue11242']['expected'] = 'INSERT INTO "type" ("int_col", "float_col", "char_col") VALUES (NULL, NULL, \'Kyiv {{city}}, Ukraine\')';
|
||||
$data['wrongBehavior']['expected'] = 'INSERT INTO "type" ("int_col", "float_col", "char_col") VALUES (\'\', \'\', \'Kyiv {{city}}, Ukraine\')';
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function testAddDropCheck()
|
||||
{
|
||||
$this->markTestSkipped('CUBRID does not support adding/dropping check constraints.');
|
||||
|
||||
@ -116,4 +116,13 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
|
||||
$db->createCommand()->dropDefaultValue($name, $tableName)->execute();
|
||||
$this->assertEmpty($schema->getTableDefaultValues($tableName, true));
|
||||
}
|
||||
|
||||
public function batchInsertSqlProvider()
|
||||
{
|
||||
$data = parent::batchInsertSqlProvider();
|
||||
$data['issue11242']['expected'] = 'INSERT INTO [type] ([int_col], [float_col], [char_col]) VALUES (NULL, NULL, \'Kyiv {{city}}, Ukraine\')';
|
||||
$data['wrongBehavior']['expected'] = 'INSERT INTO [type] ([int_col], [float_col], [char_col]) VALUES (\'\', \'\', \'Kyiv {{city}}, Ukraine\')';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,4 +33,13 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
|
||||
$command->execute();
|
||||
$this->assertEquals(3, $db->getSchema()->getLastInsertID('profile_SEQ'));
|
||||
}
|
||||
|
||||
public function batchInsertSqlProvider()
|
||||
{
|
||||
$data = parent::batchInsertSqlProvider();
|
||||
$data['issue11242']['expected'] = 'INSERT INTO "type" ("int_col", "float_col", "char_col") VALUES (NULL, NULL, \'Kyiv {{city}}, Ukraine\')';
|
||||
$data['wrongBehavior']['expected'] = 'INSERT INTO "type" ("type"."int_col", "float_col", "char_col") VALUES (\'\', \'\', \'Kyiv {{city}}, Ukraine\')';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,4 +99,13 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
|
||||
], ['char_col' => 'serialize']);
|
||||
$this->assertEquals(1, $command->execute());
|
||||
}
|
||||
|
||||
public function batchInsertSqlProvider()
|
||||
{
|
||||
$data = parent::batchInsertSqlProvider();
|
||||
$data['issue11242']['expected'] = 'INSERT INTO "type" ("int_col", "float_col", "char_col") VALUES (NULL, NULL, \'Kyiv {{city}}, Ukraine\')';
|
||||
$data['wrongBehavior']['expected'] = 'INSERT INTO "type" ("type"."int_col", "float_col", "char_col") VALUES (\'\', \'\', \'Kyiv {{city}}, Ukraine\')';
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user