-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support not Insertable/Updateable columns for entities with JOINED
inheritance type
#10598
Support not Insertable/Updateable columns for entities with JOINED
inheritance type
#10598
Conversation
P.S. This is replacement for PR #9486 but with functional tests and covered more problem of combination cases (like nonInsertable column in parent entity) which not worked even after apply fixes from previous PR. |
@greg0ire Can you approve workflow runs checks on this? |
Based on the title, it's not really a fix, but a new feature, so I'd say 2.15.x |
c9bf2a7
to
134e175
Compare
@greg0ire Done. Please approve CI again (also failed tests for php7.2 was fixed). |
@mehldau please review. Also please advise on whether this is a patch or an improvement. When reading the description, I'm now on the verge of considering this as a fix, since it's a special case of something supposed to work, and not something extra you did not do deliberately. |
@mehldau doesn't seem to respond, so let's not wait for them. |
tests/Doctrine/Tests/Models/Upsertable/JoinedInheritanceRoot.php
Outdated
Show resolved
Hide resolved
tests/Doctrine/Tests/Models/Upsertable/JoinedInheritanceNonUpdatableColumn.php
Outdated
Show resolved
Hide resolved
31354d5
to
2c9f10f
Compare
Please address the coding standard issues. |
I think they are not caused by you, I'll handle them separately. |
Fixed. You just need to rebase. |
2c9f10f
to
5b264de
Compare
Rebased. |
@@ -556,6 +560,60 @@ protected function assignDefaultVersionAndUpsertableValues($entity, array $id) | |||
} | |||
} | |||
|
|||
/** | |||
* {@inheritdoc} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* {@inheritdoc} | |
* {@inheritDoc} |
5b264de
to
623af8f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes you use clear
and find
in the tests and sometimes you don't. Could you please use them all the same in the test methods?
$this->_em->persist($entity); | ||
$this->_em->flush(); | ||
|
||
// check fetch generated values override prefilled for notUpdatable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// check fetch generated values override prefilled for notUpdatable | |
$this->_em->clear(); | |
$entity = $this->_em->find(JoinedInheritanceChild::class, $entity->id); | |
// check fetch generated values override prefilled for notUpdatable |
$this->_em->persist($entity); | ||
$this->_em->flush(); | ||
|
||
// check no any changes for writable value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Check for no changes for ..."?
$this->_em->clear(); | ||
$cleanEntity = $this->_em->find(JoinedInheritanceNonWritableColumn::class, $entity->id); | ||
self::assertInstanceOf(JoinedInheritanceNonWritableColumn::class, $cleanEntity); | ||
self::assertEquals('dbDefault', $cleanEntity->nonWritableContent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But rootField
should have changed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I'll add this check, just tried to keep the test methods short
Ok. Testing before |
623af8f
to
7fb0634
Compare
So guys, what's next step on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SenseException @derrabus @greg0ire
Maybe already need rebase this to 2.16.x branch? What you think (how long you will hold it)?
If it is not a bugfix then yes, it should be rebased on 2.16.x. I don't understand your second question. |
I'm not sure what it is: bugfix or improvement (as you mention it 2 month ago about it). |
@SenseException please give this another review. |
@SenseException @greg0ire so what you decided with it, remain 2.15.x branch (release in next v2.15.4?) or should rebase to 2.16 branch? |
…inheritance type 1. Postgres gives error when insert root entity ($rootTableStmt->executeStatement()) in JoinedSubclassPersister::executeInserts(): PDOException: SQLSTATE[08P01]: <<Unknown error>>: 7 ERROR: bind message supplies 4 parameters, but prepared statement "" requires 6 so exclude notInsertable columns from JoinedSubclassPersister::getInsertColumnList() like it done in parent::prepareInsertData() which call BasicEntityPersister::prepareUpdateData(isInsert: true) where we have condition: if ($isInsert && isset($fieldMapping['notInsertable'])) 2. Try to get generated (notInsertable|notUpdatable) column value on flush() with JoinedSubclassPersister::executeInserts() also fails: Unexpected empty result for database query. because method it calls $this->assignDefaultVersionAndUpsertableValues() after insert root entity row, while generated columns in child-entity table, so move call just after insert child row 3. Use option['default'] = 'dbDefault' in functional test entities, to emulate generated value on insert, but declare as generated = 'ALWAYS' for tests purpose (correctness of JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() sql-query) 4. Use JoinedInheritanceRoot::rootField to skip JoinedSubclassPersister::update() optimization for empty changeset in updatable:false columns tests
…d inheritance type 1. Inherit ClassMetadataInfo::requiresFetchAfterChange flag from root entity when process parent columns mapping (see ClassMetadataInfo::addInheritedFieldMapping(), it uses same condition as ClassMetadataInfo::mapField()) so JoinedSubclassPersister::assignDefaultVersionAndUpsertableValues() to be called in JoinedSubclassPersister::executeInserts(). 2. Override JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() to fetch all parent tables (see $this->getJoinSql() call) generated columns. So make protected BasicEntityPersister::identifierFlattener stateless service (use it flattenIdentifier() method) and BasicEntityPersister::extractIdentifierTypes() (to avoid copy-paste). 3. JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() doesnt check empty $columnNames because it would be an error if ClassMetadataInfo::requiresFetchAfterChange is true while no generated columns in inheritance hierarchy. 4. Initialize JoinedInheritanceRoot not-nullable string properties with insertable=false attribute to avoid attempt to insert default null data which cause error: PDOException: SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "rootwritablecontent" of relation "joined_inheritance_root" violates not-null constraint DETAIL: Failing row contains (5, null, dbDefault, dbDefault, , nonUpdatable). while $rootTableStmt->executeStatement() because JoinedSubclassPersister::getInsertColumnList() have no $insertData (prepared later) to decide is generated column provided by client code or not (so need to skip column)
Co-authored-by: Grégoire Paris <[email protected]>
7fb0634
to
3b3056f
Compare
@SenseException rebased to 2.16 |
Thanks everyone! |
I had similar issue, however setting the for example.
|
Fix for #9467 when insert and update entity with
joined
inheritance + update values from database#[InheritanceType('JOINED')]
attribute process byJoinedSubclassPersister
, according toUnitOfWork::getEntityPersister()
:orm/lib/Doctrine/ORM/UnitOfWork.php
Lines 3227 to 3228 in da9b9de
getInsertColumnList()
without excludingnotInsertable
columns like parent do:orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
Line 1478 in da9b9de
so when it use prepared sql-statement with parameters prepared by parent (
AbstractEntityInheritancePersister::prepareInsertData()
reuseBasicEntityPersister::prepareInsertData()
reuseBasicEntityPersister::prepareUpdateData()
with$isInsert
mode):orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
Lines 640 to 659 in da9b9de
we get error from database, e.g. postgresql:
JoinedSubclassPersister::getInsertColumnList()
. There is no such error for update queries, because parent methods used inJoinedSubclassPersister::update()
:BasicEntityPersister::prepareUpdateData()
andBasicEntityPersister::updateTable()
.notInsertable
|notUpdatable
|version
) after flush -JoinedSubclassPersister::assignDefaultVersionAndUpsertableValues()
:orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
Lines 548 to 555 in da9b9de
ClassMetadataInfo::$requiresFetchAfterChange
) in both cases (executeInserts() and update()) doesnt inherited from entity parent-class. This fixed by tracking of parent mappings inClassMetadataInfo::addInheritedFieldMapping()
like it done for child entity inmapField()
(may be add setter for factory):orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Lines 2814 to 2820 in da9b9de
JoinedSubclassPersister::fetchVersionAndNotUpsertableValues()
- where added join (reuseJoinedSubclassPersister::getJoinSql()
) and column aliases. Make parentextractIdentifierTypes()
and$identifierFlattener
make them protected.insert()
method to avoidLengthException('Unexpected empty result for database query.')
.JoinedInheritanceRoot
entity, with children for each case andJoinedInheritanceChild
to test root entity columns. Declare database default column values to avoid platform-specificcolumnDefinition
. Usegenerated: 'ALWAYS'
in hope to obtain error fromupdate()
method