On Tue, Jun 01, 2021 at 08:36:38AM -0400, Mike Bayer wrote:
> I can't make out your "ideal" SQL due to bad formatting however, if you want 
> the query to have an additional JOIN tacked onto it whenever you refer to 
> this hybrid property in the COLUMNS clause, you need to use query.join() 
> explicitly, either up front or by using something like a query builder 
> function or the do_orm_execute event to automatically alter the query.

Thank you Mike, I'm still wondering why with when I'm joining the 
row-limited relationship (through a window function) called 
"current_translation" in my case the generated FROM is wrong. It looks
like there is an issue when the aliased class is joined through
inheritance.

Attached my updated POC, the issue is in test_six and test_seven

(pytest -s poc.py)

you can clearly see that the FROM clause is wrong
(https://gist.github.com/silenius/3c090ee9470a4889e9812f7d8da64f56#file-gistfile1-txt-L28-L31),
although the .current_translation relationship is properly loaded
(https://gist.github.com/silenius/3c090ee9470a4889e9812f7d8da64f56#file-gistfile1-txt-L28-L31)

(and I'm sorry, but I'm still don't see how could I subselect from this
row-limited current_translation relationship in my hybrid property
expression ..)

Have a good day,
Julien

> 
> On Tue, Jun 1, 2021, at 6:58 AM, Julien Cigar wrote:
> > On Fri, May 28, 2021 at 10:53:26AM -0400, Mike Bayer wrote:
> > > the hybrid here is pulling in additional tables which are causing a 
> > > cartesian product since there is nothing joining the Document entity to 
> > > this other entity which seems to be DocumentTranslation.    Run this in 
> > > 1.4 and you will see the warnings generated.     an ORDER BY etc. has to 
> > > either produce a self-contained scalar expression, like a correlated 
> > > subquery, or you otherwise need to make sure the query has JOIN/WHERE to 
> > > link them together, such as:
> > > 
> > >         q = (
> > >             s.query(Document)
> > >             .join(DocumentTranslation)
> > >             .filter(Document.title.like("doc3%"))
> > >             .order_by(Document.title)
> > >         )
> > 
> > Thank you for your quick reply and help.                                    
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > It works with: .join(DocumentTranslation) or                                
> >                                                                             
> >                                                                             
> >                                                         
> > .join(Document.translations). However it doesn't work with                  
> >                                                                             
> >                                                                             
> >                                                         
> > .join(Document.current_translation), the FROM clause is wrong (as you       
> >                                                                             
> >                                                                             
> >                                                         
> > can see in my test_six()). This is because my Translation-like classes      
> >                                                                             
> >                                                                             
> >                                                         
> > are polymorphic too I think.           
> > 
> > > 
> > > 
> > > seems like you'd be better off making sure Document.title returns a 
> > > correlated scalar subquery rather than what it does now which seems to be 
> > > :
> > > 
> > 
> > yes, this would be really the best, but I don't see how could I             
> >                                                                             
> >                                                                             
> >                                                         
> > subselect from the .current_translation relationship (which is a            
> >                                                                             
> >                                                                             
> >                                                         
> > relationship on an orm.aliased filtered by a primaryjoin). Ideally I'd      
> >                                                                             
> >                                                                             
> >                                                         
> > like to get something like:                                                 
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > with                                                                        
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > q = (                                                                       
> >                                                                             
> >                                                                             
> >                                                         
> >     s.query(Document)                                                       
> >                                                                             
> >                                                                             
> >                                                         
> >     .join(Document.current_translation)                                     
> >                                                                             
> >                                                                             
> >                                                         
> >     .filter(Document.title.like("doc3%"))                                   
> >                                                                             
> >                                                                             
> >                                                         
> >     .order_by(Document.title)                                               
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > )                                                                           
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > I should have something like:                                               
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > SELECT (                                                                    
> >                                                                             
> >                                                                             
> >                                                         
> >     SELECT sub.title FROM sub                                               
> >                                                                             
> >                                                                             
> >                                                         
> > ) AS title, (                                                               
> >                                                                             
> >                                                                             
> >                                                         
> >     SELECT sub.description FROM sub                                         
> >                                                                             
> >                                                                             
> >                                                         
> > ) AS description                                                            
> >                                                                             
> >                                                                             
> >                                                         
> > FROM                                                                        
> >                                                                             
> >                                                                             
> >                                                         
> >     content c                                                               
> >                                                                             
> >                                                                             
> >                                                         
> > JOIN                                                                        
> >                                                                             
> >                                                                             
> >                                                         
> >     document d ON c.id = d.content_id                                       
> >                                                                             
> >                                                                             
> >                                                         
> > JOIN (                                                                      
> >                                                                             
> >                                                                             
> >                                                         
> >     SELECT                                                                  
> >                                                                             
> >                                                                             
> >                                                         
> >     (...)                                                                   
> >                                                                             
> >                                                                             
> >                                                         
> >     row_number() OVER (                                                     
> >                                                                             
> >                                                                             
> >                                                         
> >         PARTITION BY                                                        
> >                                                                             
> >                                                                             
> >                                                         
> >             document_translation.content_id                                 
> >                                                                             
> >                                                                             
> >                                                         
> >         ORDER BY                                                            
> >                                                                             
> >                                                                             
> >                                                         
> >             document_translation.language_id = 'fr' DESC,                   
> >                                                                             
> >                                                                             
> >                                                         
> >             document_translation.language_id = 'en' DESC                    
> >                                                                             
> >                                                                             
> >                                                         
> >     ) AS "index"                                                            
> >                                                                             
> >                                                                             
> >                                                         
> >     FROM                                                                    
> >                                                                             
> >                                                                             
> >                                                         
> >     content_translation                                                     
> >                                                                             
> >                                                                             
> >                                                         
> >     JOIN                                                                    
> >                                                                             
> >                                                                             
> >                                                         
> >        document_translation                                                 
> >                                                                             
> >                                                                             
> >                                                         
> >        ON content_translation.language_id = 
> > document_translation.language_id                                            
> >                                                                             
> >                                                                             
> >             
> >        AND content_translation.content_id = document_translation.content_id 
> >                                                                             
> >                                                                             
> >                                                         
> >     WHERE                                                                   
> >                                                                             
> >                                                                             
> >                                                         
> >         document_translation.language_id IN ('fr', 'en')                    
> >                                                                             
> >                                                                             
> >                                                         
> > ) AS sub                                                                    
> >                                                                             
> >                                                                             
> >                                                         
> >     ON sub.document_translation_content_id = content.id                     
> >                                                                             
> >                                                                             
> >                                                         
> >     AND sub."index" = 1                                                     
> >                                                                             
> >                                                                             
> >                                                         
> > WHERE                                                                       
> >                                                                             
> >                                                                             
> >                                                         
> >     title LIKE 'doc3%'                                                      
> >                                                                             
> >                                                                             
> >                                                         
> > ORDER BY                                                                    
> >                                                                             
> >                                                                             
> >                                                         
> >     title                                                                   
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > but I don't see any way in the hybrid property expression to subselect      
> >                                                                             
> >                                                                             
> >                                                         
> > from the outer .current_translation query ..                                
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > (I've updated my POC on                                                     
> >                                                                             
> >                                                                             
> >                                                         
> > https://gist.github.com/silenius/77466fc260a9cb0f25025bffbf3339cd)          
> >                                                                             
> >                                                                             
> >                                                         
> >                                                                             
> >                                                                             
> >                                                                             
> >                                                         
> > Julien                                                                     
> > 
> > 
> > > (Pdb) print(select(Document.title))
> > > SELECT content_translation.title
> > > FROM content_translation JOIN document_translation ON 
> > > content_translation.language_id = document_translation.language_id AND 
> > > content_translation.content_id = document_translation.content_id
> > > 
> > > I know you've had this model working for many years now.
> > > 
> > > 
> > > 
> > > 
> > > 
> > > 
> > > On Fri, May 28, 2021, at 8:25 AM, Julien Cigar wrote:
> > > > Hello,
> > > > 
> > > > I have a project heavily based on joinedload inheritance. It's a
> > > > CMS-like for which I've added a translation feature some months ago. It
> > > > worked more or less, but some things are still not working properly.
> > > > 
> > > > The situation is the following:
> > > > 
> > > > I have a joinedload inheritance for which the base class is "Content", 
> > > > with subclasses like Folder, Document, etc. Nothing really complicated.
> > > > 
> > > > I'm also having another joinedload inheritance for which the base class
> > > > is "ContentTranslation", with subclasses like FolderTranslation,
> > > > DocumentTranslation, etc.
> > > > 
> > > > The idea is that each Content-like class has a corresponding
> > > > -Translation class (with common attributes for all Content-like stuff,
> > > > like "title", "description", "language_id", etc, located in 
> > > > ContentTranslation class)
> > > > 
> > > > On each Content-like class, there is "xxx_current_translation" and a
> > > > "xxx_translations" relationships and I've added hybrid properties which
> > > > map to the corresponding -Translation class.
> > > > 
> > > > The problem I have is that I can't .order_by() or .filter() on the
> > > > hybrid properties. Instead of making a JOIN on the
> > > > "xxx_current_translation" (which is joinedload) SQLAlchemy adds the base
> > > > ContentTranslation class. I've also tried with .join() manually and add
> > > > it with orm.contains_eager() but it doesn't work either..
> > > > 
> > > > I've made a full POC on 
> > > > https://gist.github.com/silenius/77466fc260a9cb0f25025bffbf3339cd
> > > > 
> > > > Any idea ? :)
> > > > 
> > > > Thanks,
> > > > Julien
> > > > 
> > > > -- 
> > > > Julien Cigar
> > > > Belgian Biodiversity Platform (http://www.biodiversity.be)
> > > > PGP fingerprint: EEF9 F697 4B68 D275 7B11  6A25 B2BB 3710 A204 23C0
> > > > No trees were killed in the creation of this message.
> > > > However, many electrons were terribly inconvenienced.
> > > > 
> > > > -- 
> > > > SQLAlchemy - 
> > > > The Python SQL Toolkit and Object Relational Mapper
> > > > 
> > > > http://www.sqlalchemy.org/
> > > > 
> > > > To post example code, please provide an MCVE: Minimal, Complete, and 
> > > > Verifiable Example.  See  http://stackoverflow.com/help/mcve for a full 
> > > > description.
> > > > --- 
> > > > You received this message because you are subscribed to the Google 
> > > > Groups "sqlalchemy" group.
> > > > To unsubscribe from this group and stop receiving emails from it, send 
> > > > an email to sqlalchemy+unsubscr...@googlegroups.com 
> > > > <mailto:sqlalchemy%2Bunsubscribe%40googlegroups.com> 
> > > > <mailto:sqlalchemy%2Bunsubscribe%40googlegroups.com>.
> > > > To view this discussion on the web visit 
> > > > https://groups.google.com/d/msgid/sqlalchemy/20210528122520.4gzwrf2w4b6cqno5%40x1.
> > > > 
> > > 
> > > -- 
> > > SQLAlchemy - 
> > > The Python SQL Toolkit and Object Relational Mapper
> > > 
> > > http://www.sqlalchemy.org/
> > > 
> > > To post example code, please provide an MCVE: Minimal, Complete, and 
> > > Verifiable Example.  See  http://stackoverflow.com/help/mcve for a full 
> > > description.
> > > --- 
> > > You received this message because you are subscribed to the Google Groups 
> > > "sqlalchemy" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an 
> > > email to sqlalchemy+unsubscr...@googlegroups.com 
> > > <mailto:sqlalchemy%2Bunsubscribe%40googlegroups.com>.
> > > To view this discussion on the web visit 
> > > https://groups.google.com/d/msgid/sqlalchemy/fb68178f-16ac-45ec-b8c0-c1d5dde8b78a%40www.fastmail.com.
> > 
> > -- 
> > Julien Cigar
> > Belgian Biodiversity Platform (http://www.biodiversity.be)
> > PGP fingerprint: EEF9 F697 4B68 D275 7B11  6A25 B2BB 3710 A204 23C0
> > No trees were killed in the creation of this message.
> > However, many electrons were terribly inconvenienced.
> > 

-- 
Julien Cigar
Belgian Biodiversity Platform (http://www.biodiversity.be)
PGP fingerprint: EEF9 F697 4B68 D275 7B11  6A25 B2BB 3710 A204 23C0
No trees were killed in the creation of this message.
However, many electrons were terribly inconvenienced.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/20210614102045.vz5xgrkalxa5dil3%40x1.
import logging

from sqlalchemy import orm
from sqlalchemy import sql
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.hybrid import hybrid_property
import unittest

Base = declarative_base()

log = logging.getLogger(__name__)


# Fake stuff for testing

_fake_ids = {
    'document': 1,
    'event': 2,
    'folder': 3
}

def get_current_locale():
    return 'fr'


def get_default_locale():
    return 'en'


def setup_relationships(content_cls, translation_cls,
                        current_locale=get_current_locale,
                        default_locale=get_default_locale):
    '''Helper to setup translations'''

    log.info('Adding translation properties: %s to %s', content_cls,
             translation_cls)

    content_mapper = orm.class_mapper(content_cls)
    translation_mapper = orm.class_mapper(translation_cls)

    current_locale = sql.bindparam(None, callable_=current_locale,
                                   type_=String())

    default_locale = sql.bindparam(None, callable_=default_locale,
                                   type_=String())

    partition = sql.select([
        translation_cls,
        sql.func.row_number().over(
            order_by=[
                sql.desc(translation_cls.language_id == current_locale),
                sql.desc(translation_cls.language_id == default_locale)
            ],
            partition_by=translation_cls.content_id
        ).label('index')
    ], use_labels=True).where(
        sql.and_(
            translation_cls.language_id.in_((current_locale, default_locale))
        )
    ).alias()

    partition_alias = orm.aliased(translation_cls, partition)

    # First, add properties on the Content-like class

    content_name = content_cls.__name__.lower()

    content_current_translation = (
        '{}_current_translation'.format(content_name)
    )

    content_translations = (
        '{}_translations'.format(content_name)
    )

    is_base_mapper = content_mapper.base_mapper is content_mapper

    content_mapper.add_properties({
        content_current_translation: orm.relationship(
            partition_alias,
            primaryjoin=sql.and_(
                orm.foreign(partition_alias.content_id) == content_cls.id,
                partition.c.index == 1,
            ),
            lazy='noload' if is_base_mapper else 'joined',
            uselist=False,
            innerjoin=True,
            viewonly=True,
            bake_queries=False,
        ),

        content_translations: orm.relationship(
            lambda: translation_cls,
            cascade='all, delete-orphan',
            innerjoin=True,
            lazy='noload' if is_base_mapper else 'select',
            bake_queries=False,
            backref=orm.backref(
                content_name,
                innerjoin=True,
                uselist=False,
            ),
            collection_class=attribute_mapped_collection('language_id')
        )
    })

    language_name = '{}_language'.format(content_name)

    translation_mapper.add_properties({
        language_name: orm.relationship(
            Language,
            lazy='noload' if is_base_mapper else 'select',
            innerjoin=True,
            uselist=False,
            backref=orm.backref(
                content_translations,
                cascade='all, delete-orphan'
            )
        )
    })

    content_cls.translations = getattr(content_cls, content_translations)
    content_cls.current_translation = getattr(content_cls, content_current_translation)
    translation_cls.language = getattr(translation_cls, language_name)

def setup_hybrids(cls, name, translation_cls,
                  current_locale=get_current_locale, default=None):

    def _fget(self):
        return getattr(self.current_translation, name, default)

    def _fset(self, value):
        locale_name = current_locale()

        trans = self.translations.setdefault(
            locale_name,
            translation_cls(language_id=locale_name)
        )

        setattr(trans, name, value)

    def _expr(_cls):
        return getattr(translation_cls, name)
        #foo = orm.aliased(cls.document_current_translation)
        #q = sql.select([getattr(foo, name)]).as_scalar()
        #return q

    log.info('Adding hybrid attribute: %s.%s', cls, name)

    prop = hybrid_property(fget=_fget, fset=_fset, expr=_expr)

    setattr(cls, name, prop)


############
# ENTITIES #
############

class ContentType(Base):

    __tablename__ = 'content_type'

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)

    def __init__(self, id, name):
        self.id = id
        self.name = name


class Language(Base):

    __tablename__ = 'language'

    id = Column(String(2), primary_key=True)
    name = Column(String(50), nullable=False)

    def __init__(self, id, name):
        self.id = id
        self.name = name


class Content(Base):

    __tablename__ = 'content'

    id = Column(Integer, primary_key=True)
    content_type_id = Column(Integer, ForeignKey('content_type.id'),
                             nullable=False)
    container_id = Column(Integer, ForeignKey('folder.content_id'))

    parent = orm.relationship(
        lambda: Folder,
        foreign_keys=lambda: Content.container_id,
        innerjoin=True,
        uselist=False,
        backref=orm.backref('children', cascade='all, delete-orphan')
    )

    content_type = orm.relationship(
        ContentType,
        lazy='joined',
        innerjoin=True,
        uselist=False
    )

    __mapper_args__ = {
        'polymorphic_on': content_type_id
    }


class Folder(Content):

    __tablename__ = 'folder'

    content_id = Column(Integer, ForeignKey('content.id'), primary_key=True)
    some_folder_col = Column(Integer, nullable=True)

    __mapper_args__ = {
        'polymorphic_identity': _fake_ids['folder'],
        'inherit_condition': content_id == Content.id
    }

    def __init__(self, title, description=None, some_folder_col=None):
        self.some_folder_col = some_folder_col
        locale = get_current_locale()
        self.translations[locale] = FolderTranslation(
            title=title, content_type_id=_fake_ids['folder'],
            description=description
        )


class Document(Content):

    __tablename__ = 'document'

    content_id = Column(Integer, ForeignKey('content.id'), primary_key=True)
    some_doc_col = Column(String, nullable=True)

    __mapper_args__ = {
        'polymorphic_identity': _fake_ids['document'],
    }

    def __init__(self, title, body, description=None, locale=None):
        if locale is None:
            locale = get_current_locale()

        self.translations[locale] = DocumentTranslation(
            body=body, title=title, content_type_id=_fake_ids['document'],
            description=description, language_id=locale
        )

#######################
# TRANSLATION CLASSES #
#######################

class ContentTranslation(Base):

    __tablename__ = 'content_translation'

    language_id = Column(String(2), ForeignKey('language.id'),
                         primary_key=True)
    content_id = Column(Integer, ForeignKey('content.id'), primary_key=True)

    title = Column(String, nullable=False)
    description = Column(String)

    content_type = association_proxy("content", "content_type")

    __mapper_args__ = {
        'polymorphic_on':
            select([Content.content_type_id]).where(content_id == Content.id).\
            correlate_except(Content).as_scalar()
    }

    def __init__(self, **kwargs):
        if 'language_id' not in kwargs:
            self.language_id = get_current_locale()

        for k, v in kwargs.items():
            setattr(self, k, v)


class FolderTranslation(ContentTranslation):

    __tablename__ = 'folder_translation'

    language_id = Column(String(2), ForeignKey('language.id'),
                         primary_key=True)
    content_id = Column(Integer, ForeignKey('folder.content_id'), primary_key=True)

    __table_args__ = (
        ForeignKeyConstraint(
            ['language_id', 'content_id'],
            ['content_translation.language_id',
             'content_translation.content_id']
        ),
    )

    __mapper_args__ = {
        'polymorphic_identity': _fake_ids['folder'],
    }


class DocumentTranslation(ContentTranslation):

    __tablename__ = 'document_translation'

    language_id = Column(String(2), ForeignKey('language.id'),
                         primary_key=True)
    content_id = Column(Integer, ForeignKey('document.content_id'),
                        primary_key=True)

    body = Column(String, nullable=False)

    __table_args__ = (
        ForeignKeyConstraint(
            ['language_id', 'content_id'],
            ['content_translation.language_id',
             'content_translation.content_id']
        ),
    )

    __mapper_args__ = {
        'polymorphic_identity': _fake_ids['document']
    }


e = create_engine("sqlite://", echo=False)

Base.metadata.create_all(e)

setup_relationships(Content, ContentTranslation)
setup_relationships(Folder, FolderTranslation)
setup_relationships(Document, DocumentTranslation)

for col in ('title', 'description'):
    setup_hybrids(Content, col, ContentTranslation)

for col in ('title', 'description'):
    setup_hybrids(Folder, col, FolderTranslation)

for col in ('title', 'description', 'body'):
    setup_hybrids(Document, col, DocumentTranslation)

class FooTest(unittest.TestCase):
    @classmethod
    def setup_class(cls):
        s = Session(e)

        for name, fake_id in _fake_ids.items():
            s.add(ContentType(fake_id, name))

        s.add(Language('fr', 'Français'))
        s.add(Language('en', 'English'))

        root = Folder('root')
        s.add(root)

        subroot = Folder('subroot')
        root.children.append(subroot)

        doc1 = Document('doc1_title_fr', 'doc1_body_fr')
        doc2 = Document('doc2_title_fr', 'doc2_body_fr')
        doc3 = Document('doc3_title_en', 'doc3_body_en', locale='en')
        subroot.children.append(doc1)
        subroot.children.append(doc2)
        subroot.children.append(doc3)

        trans_fr = DocumentTranslation(
            title='doc3_title_fr',
            description='doc3_description_fr',
            body='doc3_body_fr'
        )

        doc3.translations['fr'] = trans_fr

        s.flush()

        s.commit()
        cls.doc3_id = doc3.id
        s.close()

    def test_one(self):
        s = Session(e)
        foo = s.query(Document).get(self.doc3_id)

        assert foo.translations['fr'].title == 'doc3_title_fr'
        assert foo.translations['en'].title == 'doc3_title_en'
        assert foo.translations['fr'].body == 'doc3_body_fr'
        assert foo.translations['en'].body == 'doc3_body_en'
        assert foo.description == 'doc3_description_fr'

        s.close()

    def test_two(self):
        s = Session(e)
        q = s.query(Document).join(Document.translations).filter(Document.title=='doc1_title_fr')
        foo = q.one()
        assert foo.title == 'doc1_title_fr'
        s.close()

    def test_three(self):
        s = Session(e)
        q = s.query(Document).join(DocumentTranslation).filter(Document.title.like('doc3%')).order_by(Document.title)
        foo = q.all()
        assert len(foo) == 1
        assert foo[0].title == 'doc3_title_fr'
        assert foo[0].translations['en'].title == 'doc3_title_en'
        assert foo[0].translations['fr'].title == 'doc3_title_fr'
        s.close()

    def test_four(self):
        s = Session(e)
        foo = s.query(Document).filter(Document.translations.any(language_id='fr')).all()
        assert len(foo) == 3
        s.close()

    def test_five(self):
        s = Session(e)
        foo = DocumentTranslation(
            title='doc2_title_nl', body='doc2_body_nl', language_id='nl'
        )
        doc2 = s.query(Document).filter(Document.translations.any(title='doc2_title_fr')).one()

        assert doc2.title == 'doc2_title_fr'
        doc2.translations['nl'] = foo
        s.close()

    def test_six(self):
        s = Session(e)
        q = (
            s.query(Document)
            .join(Document.current_translation)
            .filter(Document.title.like('doc3%'))
            .order_by(Document.title)
        )
        print(q)
        print('***********************')
        foo = q.all()
        assert len(foo) == 1
        assert foo[0].title == 'doc3_title_fr'
        assert foo[0].translations['en'].title == 'doc3_title_en'
        assert foo[0].translations['fr'].title == 'doc3_title_fr'
        s.close()

    def test_seven(self):
        s = Session(e)
        q = (
            s.query(Document)
            .join(Document.current_translation)
            .options(
                orm.contains_eager(Document.current_translation)
            )
            .filter(Document.title.like('doc3%'))
            .order_by(Document.title)
        )
        print(q)
        print('***********************')
        foo = q.all()
        assert len(foo) == 1
        assert foo[0].title == 'doc3_title_fr'
        assert foo[0].translations['en'].title == 'doc3_title_en'
        assert foo[0].translations['fr'].title == 'doc3_title_fr'
        s.close()

Reply via email to