active-record icon indicating copy to clipboard operation
active-record copied to clipboard

\yii\db\BaseActiveRecord::save() returns false if \PDOStatement::rowCount() is falsy after insert

Open tom-- opened this issue 9 years ago • 3 comments
trafficstars

Docs for \yii\db\BaseActiveRecord::save()

@return boolean whether the saving succeeded (i.e. no validation errors occurred)

As far as I can tell there are three ways that it can return false

  1. validation fails
  2. beforeSave() returns false
  3. after an INSERT command is executed, \PDOStatement::rowCount() is falsy, e.g. integer zero. (This branch is only on insert and does not exist if save() calls update()).

It seems to me that an INSERT command that executes without an exception but that affects zero rows is an exceptional condition that the app will want to handle differently from validation failure or beforeSave() returning false. If this happens I would probably want to rollback the transaction. But it can be complicated for the app code to discriminate this condition and throw an exception.

If \yii\db\Schema::insert would instead throw an exception then application scripts can more easily deal with save() returning false. Validation and beforeSave() are entirely the app's responsibility. Zero rows affected after insert, otoh, is very weird and better processed via an exception.

It's unusual for false return in the Yii 2 API to be so ambiguous.

Porposal: change \yii\db\Schema::insert to throw an exception if !$command->execute().

tom-- avatar May 06 '16 18:05 tom--

Could be done in 2.1.

samdark avatar May 06 '16 21:05 samdark

What can cause \PDOStatement::rowCount() to return zero after an INSERT command is executed successfully?

tom-- avatar May 06 '16 22:05 tom--

I see no reason for that if PDO driver is implemented correctly.

samdark avatar May 06 '16 23:05 samdark