Fixed yii\db\ActiveRecord does not updates attribute specified at optimisticLock() after save

This commit is contained in:
Klimov Paul
2015-05-26 11:53:34 +03:00
parent 2434511c6e
commit 51a442d6c8
10 changed files with 107 additions and 1 deletions

View File

@ -11,6 +11,7 @@ Yii Framework 2 Change Log
- 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)
- Bug #8483: sequence name in `Schema::getLastInsertId()` was not properly quoted (nineinchnick) - Bug #8483: sequence name in `Schema::getLastInsertId()` was not properly quoted (nineinchnick)
- Bug #8506: Cleaning of output buffer in `Widget::run()` conflicts with `Pjax` widget which did the cleanup itself (cebe, joester89) - Bug #8506: Cleaning of output buffer in `Widget::run()` conflicts with `Pjax` widget which did the cleanup itself (cebe, joester89)
- Bug #8544: Fixed `yii\db\ActiveRecord` does not updates attribute specified at `optimisticLock()` after save (klimov-paul)
- Bug: Fixed string comparison in `BaseActiveRecord::unlink()` which may result in wrong comparison result for hash valued primary keys starting with `0e` (cebe) - Bug: Fixed string comparison in `BaseActiveRecord::unlink()` which may result in wrong comparison result for hash valued primary keys starting with `0e` (cebe)
- Enh #7169: `yii\widgets\ActiveField` now uses corresponding methods for default parts rendering (klimov-paul) - Enh #7169: `yii\widgets\ActiveField` now uses corresponding methods for default parts rendering (klimov-paul)
- Enh #8070: `yii\console\controllers\MessageController` now sorts created messages, even if there is no new one, while saving to PHP file (klimov-paul) - Enh #8070: `yii\console\controllers\MessageController` now sorts created messages, even if there is no new one, while saving to PHP file (klimov-paul)

View File

@ -725,6 +725,9 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
$changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null; $changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null;
$this->_oldAttributes[$name] = $value; $this->_oldAttributes[$name] = $value;
if ($name === $lock) {
$this->$lock = $value;
}
} }
$this->afterSave(false, $changedAttributes); $this->afterSave(false, $changedAttributes);

View File

@ -0,0 +1,17 @@
<?php
namespace yiiunit\data\ar;
/**
* @property integer $id
* @property string $title
* @property string $content
* @property integer $version
*/
class Document extends ActiveRecord
{
public function optimisticLock()
{
return 'version';
}
}

View File

@ -17,6 +17,7 @@ DROP TABLE IF EXISTS "type";
DROP TABLE IF EXISTS "constraints"; DROP TABLE IF EXISTS "constraints";
DROP TABLE IF EXISTS "animal"; DROP TABLE IF EXISTS "animal";
DROP TABLE IF EXISTS "default_pk"; DROP TABLE IF EXISTS "default_pk";
DROP TABLE IF EXISTS "document";
DROP VIEW IF EXISTS "animal_view"; DROP VIEW IF EXISTS "animal_view";
CREATE TABLE "constraints" CREATE TABLE "constraints"
@ -139,6 +140,14 @@ CREATE TABLE "default_pk" (
PRIMARY KEY ("id") PRIMARY KEY ("id")
); );
CREATE TABLE "document" (
"id" int(11) NOT NULL AUTO_INCREMENT,
"title" varchar(255) NOT NULL,
"content" string,
"version" int(11) NOT NULL DEFAULT 0,
PRIMARY KEY ("id")
);
CREATE VIEW "animal_view" AS SELECT * FROM "animal"; CREATE VIEW "animal_view" AS SELECT * FROM "animal";
INSERT INTO "animal" ("type") VALUES ('yiiunit\data\ar\Cat'); INSERT INTO "animal" ("type") VALUES ('yiiunit\data\ar\Cat');
@ -181,3 +190,5 @@ INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VA
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0);
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0);
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0);
INSERT INTO "document" (title, content, version) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);

View File

@ -10,6 +10,7 @@ IF OBJECT_ID('[dbo].[type]', 'U') IS NOT NULL DROP TABLE [dbo].[type];
IF OBJECT_ID('[dbo].[null_values]', 'U') IS NOT NULL DROP TABLE [dbo].[null_values]; IF OBJECT_ID('[dbo].[null_values]', 'U') IS NOT NULL DROP TABLE [dbo].[null_values];
IF OBJECT_ID('[dbo].[animal]', 'U') IS NOT NULL DROP TABLE [dbo].[animal]; IF OBJECT_ID('[dbo].[animal]', 'U') IS NOT NULL DROP TABLE [dbo].[animal];
IF OBJECT_ID('[dbo].[default_pk]', 'U') IS NOT NULL DROP TABLE [dbo].[default_pk]; IF OBJECT_ID('[dbo].[default_pk]', 'U') IS NOT NULL DROP TABLE [dbo].[default_pk];
IF OBJECT_ID('[dbo].[document]', 'U') IS NOT NULL DROP TABLE [dbo].[document];
IF OBJECT_ID('[dbo].[animal_view]', 'V') IS NOT NULL DROP VIEW [dbo].[animal_view]; IF OBJECT_ID('[dbo].[animal_view]', 'V') IS NOT NULL DROP VIEW [dbo].[animal_view];
CREATE TABLE [dbo].[profile] ( CREATE TABLE [dbo].[profile] (
@ -124,6 +125,16 @@ CREATE TABLE [dbo].[default_pk] (
) ON [PRIMARY] ) ON [PRIMARY]
); );
CREATE TABLE [dbo].[document] (
[id] [int] IDENTITY(1,1) NOT NULL,
[title] [varchar](255) NOT NULL,
[content] [text],
[version] [int] NOT NULL DEFAULT 0,
CONSTRAINT [PK_default_pk] PRIMARY KEY CLUSTERED (
[id] ASC
) ON [PRIMARY]
);
CREATE VIEW [dbo].[animal_view] AS SELECT * FROM [dbo].[animal]; CREATE VIEW [dbo].[animal_view] AS SELECT * FROM [dbo].[animal];
INSERT INTO [dbo].[animal] (type) VALUES ('yiiunit\data\ar\Cat'); INSERT INTO [dbo].[animal] (type) VALUES ('yiiunit\data\ar\Cat');
@ -166,3 +177,5 @@ INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity],
INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 5, 1, 15.0); INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 5, 1, 15.0);
INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 3, 1, 8.0); INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 3, 1, 8.0);
INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (3, 2, 1, 40.0); INSERT INTO [dbo].[order_item_with_null_fk] ([order_id], [item_id], [quantity], [subtotal]) VALUES (3, 2, 1, 40.0);
INSERT INTO [dbo].[document] ([title], [content], [version]) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);

View File

@ -17,6 +17,7 @@ DROP TABLE IF EXISTS `type` CASCADE;
DROP TABLE IF EXISTS `constraints` CASCADE; DROP TABLE IF EXISTS `constraints` CASCADE;
DROP TABLE IF EXISTS `animal` CASCADE; DROP TABLE IF EXISTS `animal` CASCADE;
DROP TABLE IF EXISTS `default_pk` CASCADE; DROP TABLE IF EXISTS `default_pk` CASCADE;
DROP TABLE IF EXISTS `document` CASCADE;
DROP VIEW IF EXISTS `animal_view`; DROP VIEW IF EXISTS `animal_view`;
CREATE TABLE `constraints` CREATE TABLE `constraints`
@ -141,6 +142,14 @@ CREATE TABLE `default_pk` (
PRIMARY KEY (id) PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `document` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`content` TEXT,
`version` INT(11) NOT NULL DEFAULT 0,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE VIEW `animal_view` AS SELECT * FROM `animal`; CREATE VIEW `animal_view` AS SELECT * FROM `animal`;
INSERT INTO `animal` (`type`) VALUES ('yiiunit\data\ar\Cat'); INSERT INTO `animal` (`type`) VALUES ('yiiunit\data\ar\Cat');
@ -184,6 +193,8 @@ INSERT INTO `order_item_with_null_fk` (order_id, item_id, quantity, subtotal) VA
INSERT INTO `order_item_with_null_fk` (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); INSERT INTO `order_item_with_null_fk` (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0);
INSERT INTO `order_item_with_null_fk` (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); INSERT INTO `order_item_with_null_fk` (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0);
INSERT INTO `document` (title, content, version) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);
/** /**
* (MySQL-)Database Schema for validator tests * (MySQL-)Database Schema for validator tests

View File

@ -19,6 +19,7 @@ BEGIN EXECUTE IMMEDIATE 'DROP TABLE "constraints"'; EXCEPTION WHEN OTHERS THEN I
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "bool_values"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "bool_values"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "animal"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "animal"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "default_pk"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "default_pk"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "document"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP VIEW "animal_view"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP VIEW "animal_view"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_main"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_main"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_ref"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_ref"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;--
@ -32,6 +33,7 @@ BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "order_with_null_fk_SEQ"'; EXCEPTION WHEN
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 "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;--
BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE "document_SEQ"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -2289 THEN RAISE; END IF; END;--
/* STATEMENTS */ /* STATEMENTS */
@ -171,6 +173,15 @@ CREATE TABLE "default_pk" (
CONSTRAINT "default_pk_PK" PRIMARY KEY ("id") ENABLE CONSTRAINT "default_pk_PK" PRIMARY KEY ("id") ENABLE
); );
CREATE TABLE "document" (
"id" integer,
"title" varchar2(255) not null,
"content" varchar(4000),
"version" integer default 0 not null,
CONSTRAINT "document_PK" PRIMARY KEY ("id") ENABLE
);
CREATE SEQUENCE "document_SEQ";
CREATE VIEW "animal_view" AS SELECT * FROM "animal"; CREATE VIEW "animal_view" AS SELECT * FROM "animal";
/** /**
@ -282,6 +293,8 @@ INSERT INTO "order_item_with_null_fk" ("order_id", "item_id", "quantity", "subto
INSERT INTO "order_item_with_null_fk" ("order_id", "item_id", "quantity", "subtotal") VALUES (2, 3, 1, 8.0); INSERT INTO "order_item_with_null_fk" ("order_id", "item_id", "quantity", "subtotal") VALUES (2, 3, 1, 8.0);
INSERT INTO "order_item_with_null_fk" ("order_id", "item_id", "quantity", "subtotal") VALUES (3, 2, 1, 40.0); INSERT INTO "order_item_with_null_fk" ("order_id", "item_id", "quantity", "subtotal") VALUES (3, 2, 1, 40.0);
INSERT INTO "document" ("title", "content", "version") VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);
INSERT INTO "validator_main" ("id", "field1") VALUES (1, 'just a string1'); INSERT INTO "validator_main" ("id", "field1") VALUES (1, 'just a string1');
INSERT INTO "validator_main" ("id", "field1") VALUES (2, 'just a string2'); INSERT INTO "validator_main" ("id", "field1") VALUES (2, 'just a string2');
INSERT INTO "validator_main" ("id", "field1") VALUES (3, 'just a string3'); INSERT INTO "validator_main" ("id", "field1") VALUES (3, 'just a string3');

View File

@ -19,6 +19,7 @@ DROP TABLE IF EXISTS "constraints" CASCADE;
DROP TABLE IF EXISTS "bool_values" CASCADE; DROP TABLE IF EXISTS "bool_values" CASCADE;
DROP TABLE IF EXISTS "animal" CASCADE; DROP TABLE IF EXISTS "animal" CASCADE;
DROP TABLE IF EXISTS "default_pk" CASCADE; DROP TABLE IF EXISTS "default_pk" CASCADE;
DROP TABLE IF EXISTS "document" CASCADE;
DROP VIEW IF EXISTS "animal_view"; DROP VIEW IF EXISTS "animal_view";
DROP SCHEMA IF EXISTS "schema1" CASCADE; DROP SCHEMA IF EXISTS "schema1" CASCADE;
DROP SCHEMA IF EXISTS "schema2" CASCADE; DROP SCHEMA IF EXISTS "schema2" CASCADE;
@ -136,7 +137,6 @@ CREATE TABLE "bool_values" (
default_false boolean not null default false default_false boolean not null default false
); );
CREATE TABLE "animal" ( CREATE TABLE "animal" (
id serial primary key, id serial primary key,
type varchar(255) not null type varchar(255) not null
@ -147,6 +147,13 @@ CREATE TABLE "default_pk" (
type varchar(255) not null type varchar(255) not null
); );
CREATE TABLE "animal" (
id serial primary key,
title varchar(255) not null,
content text not null,
version integer not null default 0
);
CREATE VIEW "animal_view" AS SELECT * FROM "animal"; CREATE VIEW "animal_view" AS SELECT * FROM "animal";
INSERT INTO "animal" (type) VALUES ('yiiunit\data\ar\Cat'); INSERT INTO "animal" (type) VALUES ('yiiunit\data\ar\Cat');
@ -194,6 +201,8 @@ INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VA
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0);
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0);
INSERT INTO "document" (title, content, version) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);
/** /**
* (Postgres-)Database Schema for validator tests * (Postgres-)Database Schema for validator tests
*/ */

View File

@ -16,6 +16,7 @@ DROP TABLE IF EXISTS "type";
DROP TABLE IF EXISTS "null_values"; DROP TABLE IF EXISTS "null_values";
DROP TABLE IF EXISTS "animal"; DROP TABLE IF EXISTS "animal";
DROP TABLE IF EXISTS "default_pk"; DROP TABLE IF EXISTS "default_pk";
DROP TABLE IF EXISTS "document";
DROP VIEW IF EXISTS "animal_view"; DROP VIEW IF EXISTS "animal_view";
CREATE TABLE "profile" ( CREATE TABLE "profile" (
@ -123,6 +124,14 @@ CREATE TABLE "default_pk" (
PRIMARY KEY (id) PRIMARY KEY (id)
); );
CREATE TABLE "document" (
id INTEGER NOT NULL,
title VARCHAR(255) NOT NULL,
content text,
version INTEGER NOT NULL DEFAULT '0',
PRIMARY KEY (id)
);
CREATE VIEW "animal_view" AS SELECT * FROM "animal"; CREATE VIEW "animal_view" AS SELECT * FROM "animal";
INSERT INTO "animal" ("type") VALUES ('yiiunit\data\ar\Cat'); INSERT INTO "animal" ("type") VALUES ('yiiunit\data\ar\Cat');
@ -166,6 +175,8 @@ INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VA
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0);
INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0);
INSERT INTO "document" (title, content, version) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0);
/** /**
* (SqLite-)Database Schema for validator tests * (SqLite-)Database Schema for validator tests
*/ */

View File

@ -4,6 +4,7 @@ namespace yiiunit\framework\db;
use yiiunit\data\ar\ActiveRecord; use yiiunit\data\ar\ActiveRecord;
use yiiunit\data\ar\Category; use yiiunit\data\ar\Category;
use yiiunit\data\ar\Customer; use yiiunit\data\ar\Customer;
use yiiunit\data\ar\Document;
use yiiunit\data\ar\NullValues; use yiiunit\data\ar\NullValues;
use yiiunit\data\ar\OrderItem; use yiiunit\data\ar\OrderItem;
use yiiunit\data\ar\Order; use yiiunit\data\ar\Order;
@ -706,4 +707,20 @@ class ActiveRecordTest extends DatabaseTestCase
$this->assertTrue($record->save(false)); $this->assertTrue($record->save(false));
$this->assertEquals(1, $record->id); $this->assertEquals(1, $record->id);
} }
public function testOptimisticLock()
{
/* @var $record Document */
$record = Document::findOne(1);
$record->content = 'New Content';
$record->save(false);
$this->assertEquals(1, $record->version);
$record = Document::findOne(1);
$record->content = 'Rewrite attempt content';
$record->version = 0;
$this->setExpectedException('yii\db\StaleObjectException');
$record->save(false);
}
} }