Skip to content
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

index-by and order-by do not work for abstract entities with inheritance type "JOINED" in many-to-many relations #6327

Open
BonBonSlick opened this issue Mar 6, 2024 · 3 comments

Comments

@BonBonSlick
Copy link

BonBonSlick commented Mar 6, 2024

Bug Report

Inheritance type "JOINED" is NOT joined when initializing relations. INDEX-BY and ORDER-BY throws error that column is missing.

  • Driver - PGSQL 11

  • PHP 8.1

  • "doctrine/collections": "^1.6",
    
  • "doctrine/common": "^3.3.0"
    
  • "doctrine/dbal": "^2.11"
    
  • "doctrine/doctrine-bundle": "^2.2"
    
  • "doctrine/doctrine-migrations-bundle": "^3.0"
    
  • "doctrine/orm": "^2.7.4"
    

Summary

  • index-by and order-by on mappings of inheritance type JOINED is possible only on inverse side or if table per
    model, exception primary key of abstract class child eg AbstractTag - SomeTag - id, because joined child table is
    missing abstract field eg SomeTag - has no "SLUG" field, column and there is no additional join on parent abstract
    table. Missing field is indie parent, abstract class table.

Current behaviour

Error in my project. but should be reproducible:

  An exception occurred while executing 'SELECT 1 FROM post_abstract_tags t JOIN post_tag tr ON 
t.post_abstract_tags_id = tr.id WHERE tr.name = ? AND t.role_id = ?' with params ["tag_name", 1234]:                                                                                                                                                                                      
                                                                                                                                                                                                                                       
  SQLSTATE[42703]: Undefined column: 7 ERROR:  column tr.name does not exist                                                                                                                                                           
  LINE 1: ... t.post_abstract_tag_uuid = tr.id WHERE tr.name = ...    

How to reproduce

Test case scenario from real world:
3 entities, Post, AbstractTag, PostTag.
Relations Post to PostTag bidirectional Many to Many.
Providing mappings (skipped such things as ID and other relations, configs, fields discriminator column etc):

    <entity name="App\AbstractTag"
            inheritance-type="JOINED"
    >
 ...
      <field name="name">
 ...
        <discriminator-column name="discriminator"
                              type="text"
        />
        <discriminator-map>
            <discriminator-mapping value="post"
                                   class="App\Entity\PostTag"
            />
        </discriminator-map>
    <entity name="App\PostTag">

        <many-to-many target-entity="App\Post"
                      field="taggedModels"
                      mapped-by="tags"
                      index-by="title"
                      fetch="EXTRA_LAZY"
        >
            <cascade>
                <cascade-persist/>
            </cascade>
            <order-by>
                <order-by-field name="title" direction="DESC"/>
            </order-by>
        </many-to-many>
<entity name="App\Post">

   <many-to-many target-entity="App\PostTag"
                      field="tags"
                      inversed-by="taggedModels"
                      
                      index-by="name"     <<< -------- THIS IS **NOT** POSSIBLE, because name does not exist on "post_tag" table, column is in  "abstract_tag" table
                      
                      fetch="EXTRA_LAZY"
        >
            <cascade>
                <cascade-persist/>
            </cascade>

            <join-table name="posts_abstract_tags">
                <join-columns>
                    <join-column name="post_id"
                                 referenced-column-name="id"
                                 nullable="false"
                                 on-delete="CASCADE"
                    />
                </join-columns>
                <inverse-join-columns>
                    <join-column name="post_abstract_tag_id"
                                 referenced-column-name="id"
                                 nullable="false"
                                 on-delete="CASCADE"
                    />
                </inverse-join-columns>
            </join-table>


            <order-by>
                <order-by-field name="name" direction="DESC"/> <<<< --- NOT possible, name column is missing on joined entity
            </order-by>

        </many-to-many>

Approximate place which where issue occurs:

var/cache/dev/doctrine/orm/Proxies/__CG__AppPost.php

    public function addTag(\App\AbstractTag $entity): void
    {
        $this->__initializer__ && $this->__initializer__->__invoke($this, 'addTag', [$entity]);

        parent::addTag($entity);
    }

vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php::176
I am getting error when running with XDEBUG this place, cant really say at this moment where it fails.
Segmentation fault

Expected behaviour

Extra join performed on parent model if inheritance type JOINED.

So when we INDEX-BY or ORDER-BY tags inside POST entity mapping, Doctrine should add perform extra join on AbstractTag table columns, with tag name. That will result in tags to be ordered / indexed in POST relations to tags.

On inverse side everything seems ok because Post is not Abstract, but if it would, that complicates things. Actually I have this scenario and still testing it, need just to make it work. For now we sort and index by tag id.

Thank you for you time reading it.

@BonBonSlick
Copy link
Author

BonBonSlick commented Mar 7, 2024

UPD. I found what was causing XDEBUG failure during POST entity initialization, it happens in
vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php

caused by

        <many-to-many target-entity="App\PostTag"
                      field="tags"
                      inversed-by="taggedModels"
                      index-by="id.uuid"

                       fetch="EXTRA_LAZY"   <<< ------- "fetch" IS CAUSING "Segmentation fault" for PHP 8.1
 >
            <cascade>
                <cascade-persist/>
            </cascade>

Might be additional bug that initializer cant initialize "fetch" relations for child entity with inheritance type "JOINED".
Removing "fetch" mapping configuration options removes error.

Running fixtures load without xdebug works fine, I call "fl" command

alias fl="XDEBUG_TRIGGER=1 php bin/console doctrine:fixtures:load -n"

Segfaults might be caused by initializer trying to read or write an illegal memory location. It requires to debug php process itself, C language and use additional tools. Might be XDEBUG + PHP bug.

@BonBonSlick BonBonSlick changed the title index-by and order-by do not work for abstract entities with inheritance type "JOINED" index-by and order-by do not work for abstract entities with inheritance type "JOINED" in many-to-many relations Mar 7, 2024
@BonBonSlick
Copy link
Author

UPD. after some trials I fixed "SEGMENTATION FAULT" PHP error by linking both models inside Child Tag entity following

class PostTag  {

    public function __construct(TagCreateDTO $dto) {
...
        $dto->taggedModel->addTag($this);
        $this->addTaggedModel($dto->taggedModel);
}

@BonBonSlick
Copy link
Author

BonBonSlick commented Mar 7, 2024

Additional solution to first issue with index and order by is to use inheritance type table per entity, or dont order and use id for indexing. Decided to go for a second workaround for now, because there are lots of relations on abstract entity to avoid lots of duplications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant