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 #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 #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 #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)
|
- 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;
|
return false;
|
||||||
}
|
}
|
||||||
$values = $this->getDirtyAttributes($attributes);
|
$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) {
|
if (($primaryKeys = static::getDb()->schema->insert($this->tableName(), $values)) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ class QueryBuilder extends \yii\base\Object
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 'INSERT INTO ' . $schema->quoteTableName($table)
|
return 'INSERT INTO ' . $schema->quoteTableName($table)
|
||||||
. ' (' . implode(', ', $names) . ') VALUES ('
|
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
|
||||||
. implode(', ', $placeholders) . ')';
|
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -164,4 +164,43 @@ class QueryBuilder extends \yii\db\QueryBuilder
|
|||||||
|
|
||||||
return $sql;
|
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;
|
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.
|
* Generates a batch INSERT SQL statement.
|
||||||
* For example,
|
* 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 "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_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 "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 "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;--
|
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,
|
"stringcol" varchar2(32) DEFAULT NULL,
|
||||||
CONSTRAINT "null_values_PK" PRIMARY KEY ("id") ENABLE
|
CONSTRAINT "null_values_PK" PRIMARY KEY ("id") ENABLE
|
||||||
);
|
);
|
||||||
|
CREATE SEQUENCE "null_values_SEQ";
|
||||||
|
|
||||||
CREATE TABLE "type" (
|
CREATE TABLE "type" (
|
||||||
"int_col" integer NOT NULL,
|
"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 COLUMN_SEQUENCES;
|
||||||
END;
|
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
|
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;
|
IF INSERTING AND :NEW."id" IS NULL THEN SELECT "bool_values_SEQ".NEXTVAL INTO :NEW."id" FROM SYS.DUAL; END IF;
|
||||||
END COLUMN_SEQUENCES;
|
END COLUMN_SEQUENCES;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ CREATE TABLE "composite_fk" (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE "null_values" (
|
CREATE TABLE "null_values" (
|
||||||
id INT NOT NULL,
|
id serial NOT NULL,
|
||||||
var1 INT NULL,
|
var1 INT NULL,
|
||||||
var2 INT NULL,
|
var2 INT NULL,
|
||||||
var3 INT DEFAULT NULL,
|
var3 INT DEFAULT NULL,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ CREATE TABLE "composite_fk" (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE "null_values" (
|
CREATE TABLE "null_values" (
|
||||||
id INTEGER UNSIGNED PRIMARY KEY NOT NULL,
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
var1 INTEGER UNSIGNED,
|
var1 INTEGER UNSIGNED,
|
||||||
var2 INTEGER,
|
var2 INTEGER,
|
||||||
var3 INTEGER DEFAULT NULL,
|
var3 INTEGER DEFAULT NULL,
|
||||||
|
|||||||
@@ -699,4 +699,11 @@ class ActiveRecordTest extends DatabaseTestCase
|
|||||||
$animal = Animal::find()->where(['type' => Cat::className()])->one();
|
$animal = Animal::find()->where(['type' => Cat::className()])->one();
|
||||||
$this->assertEquals('meow', $animal->getDoes());
|
$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