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:
Alexander Makarov
2015-05-25 01:42:46 +03:00
9 changed files with 98 additions and 10 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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');
}
/**

View File

@@ -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');
}
}

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);
}
}