mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-21 00:54:53 +08:00
Merge pull request #8034 from nineinchnick/7374-inserting-ar-without-values
Saving AR without values / calling Command::insert without columns
This commit is contained in:
@@ -5,6 +5,7 @@ Yii Framework 2 Change Log
|
||||
-----------------------
|
||||
|
||||
- Bug #7305: Logging of Exception objects resulted in failure of the logger i.e. no logs being written (cebe)
|
||||
- Bug #7374: Use proper INSERT syntax with default values when no values are specified (nineinchnick)
|
||||
- Bug #7707: client-side `trim` validator now passes the trimmed value to subsequent validators (nkovacs)
|
||||
- Bug #8322: `yii\behaviors\TimestampBehavior::touch()` now throws an exception if owner is new record (klimov-paul)
|
||||
- Bug #8451: `yii\i18n\Formatter` did not allow negative unix timestamps as input for date formatting (cebe)
|
||||
|
||||
@@ -449,11 +449,6 @@ class ActiveRecord extends BaseActiveRecord
|
||||
return false;
|
||||
}
|
||||
$values = $this->getDirtyAttributes($attributes);
|
||||
if (empty($values)) {
|
||||
foreach ($this->getPrimaryKey(true) as $key => $value) {
|
||||
$values[$key] = $value;
|
||||
}
|
||||
}
|
||||
if (($primaryKeys = static::getDb()->schema->insert($this->tableName(), $values)) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -153,8 +153,8 @@ class QueryBuilder extends \yii\base\Object
|
||||
}
|
||||
|
||||
return 'INSERT INTO ' . $schema->quoteTableName($table)
|
||||
. ' (' . implode(', ', $names) . ') VALUES ('
|
||||
. implode(', ', $placeholders) . ')';
|
||||
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
|
||||
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -164,4 +164,43 @@ class QueryBuilder extends \yii\db\QueryBuilder
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function insert($table, $columns, &$params)
|
||||
{
|
||||
$schema = $this->db->getSchema();
|
||||
if (($tableSchema = $schema->getTableSchema($table)) !== null) {
|
||||
$columnSchemas = $tableSchema->columns;
|
||||
} else {
|
||||
$columnSchemas = [];
|
||||
}
|
||||
$names = [];
|
||||
$placeholders = [];
|
||||
foreach ($columns as $name => $value) {
|
||||
$names[] = $schema->quoteColumnName($name);
|
||||
if ($value instanceof Expression) {
|
||||
$placeholders[] = $value->expression;
|
||||
foreach ($value->params as $n => $v) {
|
||||
$params[$n] = $v;
|
||||
}
|
||||
} else {
|
||||
$phName = self::PARAM_PREFIX . count($params);
|
||||
$placeholders[] = $phName;
|
||||
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
|
||||
}
|
||||
}
|
||||
if (empty($names) && $tableSchema !== null) {
|
||||
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : reset($tableSchema->columns)->name;
|
||||
foreach ($columns as $name) {
|
||||
$names[] = $schema->quoteColumnName($name);
|
||||
$placeholders[] = 'DEFAULT';
|
||||
}
|
||||
}
|
||||
|
||||
return 'INSERT INTO ' . $schema->quoteTableName($table)
|
||||
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
|
||||
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,45 @@ EOD;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function insert($table, $columns, &$params)
|
||||
{
|
||||
$schema = $this->db->getSchema();
|
||||
if (($tableSchema = $schema->getTableSchema($table)) !== null) {
|
||||
$columnSchemas = $tableSchema->columns;
|
||||
} else {
|
||||
$columnSchemas = [];
|
||||
}
|
||||
$names = [];
|
||||
$placeholders = [];
|
||||
foreach ($columns as $name => $value) {
|
||||
$names[] = $schema->quoteColumnName($name);
|
||||
if ($value instanceof Expression) {
|
||||
$placeholders[] = $value->expression;
|
||||
foreach ($value->params as $n => $v) {
|
||||
$params[$n] = $v;
|
||||
}
|
||||
} else {
|
||||
$phName = self::PARAM_PREFIX . count($params);
|
||||
$placeholders[] = $phName;
|
||||
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
|
||||
}
|
||||
}
|
||||
if (empty($names) && $tableSchema !== null) {
|
||||
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : reset($tableSchema->columns)->name;
|
||||
foreach ($columns as $name) {
|
||||
$names[] = $schema->quoteColumnName($name);
|
||||
$placeholders[] = 'DEFAULT';
|
||||
}
|
||||
}
|
||||
|
||||
return 'INSERT INTO ' . $schema->quoteTableName($table)
|
||||
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
|
||||
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a batch INSERT SQL statement.
|
||||
* For example,
|
||||
|
||||
@@ -29,6 +29,7 @@ BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "category_SEQ"'; EXCEPTION WHEN OTHERS TH
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "item_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "order_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "order_with_null_fk_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "null_values_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "bool_values_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "animal_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
|
||||
|
||||
@@ -127,6 +128,7 @@ CREATE TABLE "null_values" (
|
||||
"stringcol" varchar2(32) DEFAULT NULL,
|
||||
CONSTRAINT "null_values_PK" PRIMARY KEY ("id") ENABLE
|
||||
);
|
||||
CREATE SEQUENCE "null_values_SEQ";
|
||||
|
||||
CREATE TABLE "type" (
|
||||
"int_col" integer NOT NULL,
|
||||
@@ -220,6 +222,11 @@ CREATE TRIGGER "order_with_null_fk_TRG" BEFORE INSERT ON "order_with_null_fk" FO
|
||||
END COLUMN_SEQUENCES;
|
||||
END;
|
||||
/
|
||||
CREATE TRIGGER "null_values_TRG" BEFORE INSERT ON "null_values" FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN
|
||||
IF INSERTING AND :NEW."id" IS NULL THEN SELECT "null_values_SEQ".NEXTVAL INTO :NEW."id" FROM SYS.DUAL; END IF;
|
||||
END COLUMN_SEQUENCES;
|
||||
END;
|
||||
/
|
||||
CREATE TRIGGER "bool_values_TRG" BEFORE INSERT ON "bool_values" FOR EACH ROW BEGIN <<COLUMN_SEQUENCES>> BEGIN
|
||||
IF INSERTING AND :NEW."id" IS NULL THEN SELECT "bool_values_SEQ".NEXTVAL INTO :NEW."id" FROM SYS.DUAL; END IF;
|
||||
END COLUMN_SEQUENCES;
|
||||
|
||||
@@ -103,7 +103,7 @@ CREATE TABLE "composite_fk" (
|
||||
);
|
||||
|
||||
CREATE TABLE "null_values" (
|
||||
id INT NOT NULL,
|
||||
id serial NOT NULL,
|
||||
var1 INT NULL,
|
||||
var2 INT NULL,
|
||||
var3 INT DEFAULT NULL,
|
||||
|
||||
@@ -87,7 +87,7 @@ CREATE TABLE "composite_fk" (
|
||||
);
|
||||
|
||||
CREATE TABLE "null_values" (
|
||||
id INTEGER UNSIGNED PRIMARY KEY NOT NULL,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
var1 INTEGER UNSIGNED,
|
||||
var2 INTEGER,
|
||||
var3 INTEGER DEFAULT NULL,
|
||||
|
||||
@@ -699,4 +699,11 @@ class ActiveRecordTest extends DatabaseTestCase
|
||||
$animal = Animal::find()->where(['type' => Cat::className()])->one();
|
||||
$this->assertEquals('meow', $animal->getDoes());
|
||||
}
|
||||
|
||||
public function testSaveEmpty()
|
||||
{
|
||||
$record = new NullValues;
|
||||
$this->assertTrue($record->save(false));
|
||||
$this->assertEquals(1, $record->id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user