Oracle mapper against select with inheritance and having properties for relations fails in conjunction with normal mapper query
Issue #308
resolved
Page inherits from content. lang_data has a foreign key to language and content. Making a normal mapper for content/page and making a mapper for a custom select works. Querying the custom select mapper works, but only if the normal mapper hasn't been queried first.
The test programm:
from sqlalchemy import (
Table, Column,
BoundMetaData,
Integer,
Sequence, ForeignKey,
create_session,
mapper, relation,
)
metadata = BoundMetaData('oracle://test:test@myoracle')
language = Table(
'language',
metadata,
Column('id', Integer, Sequence('language_seq'), primary_key=True),
)
content = Table(
'content',
metadata,
Column('id', Integer, Sequence('content_seq'), primary_key=True),
)
lang_data = Table(
'lang_data',
metadata,
Column('id', Integer, Sequence('lang_data_seq'), primary_key=True),
Column('content_id', Integer, ForeignKey('content.id')),
Column('language_id', Integer, ForeignKey('language.id')),
)
page = Table(
'page',
metadata,
Column('id', Integer, ForeignKey('content.id'), primary_key=True),
)
class ContentType(object): pass
class Content(object): pass
class Page(Content): pass
class Language(object): pass
class LangData(object): pass
languages = mapper(Language, language)
lang_datas = mapper(LangData, lang_data)
lang_datas.add_property('language', relation(languages, lazy=False))
contents = mapper(Content, content)
contents.add_property('lang_data', relation(lang_datas, lazy=False))
pages = mapper(Page, page, inherits=contents)
try:
metadata.create_all()
r = content.insert().execute()
page.insert().execute(id=r.last_inserted_ids()[0](0))
session = create_session()
obj = session.query(pages).select() #remove to make error go away
m = mapper(Page, content.select().alias('foobar'), non_primary=True)
session.query(m).select()[0](0).lang_data
finally:
metadata.drop_all()
The error message:
Traceback (most recent call last):
File "test_inheritance.py", line 59, in ?
session.query(m).select()[0](0).lang_data
File "build/bdist.linux-i686/egg/sqlalchemy/attributes.py", line 32, in __get__
File "build/bdist.linux-i686/egg/sqlalchemy/attributes.py", line 137, in get
File "build/bdist.linux-i686/egg/sqlalchemy/orm/properties.py", line 408, in lazyload
File "build/bdist.linux-i686/egg/sqlalchemy/orm/query.py", line 232, in select_whereclause
File "build/bdist.linux-i686/egg/sqlalchemy/orm/query.py", line 302, in _select_statement
File "build/bdist.linux-i686/egg/sqlalchemy/orm/query.py", line 264, in instances
File "build/bdist.linux-i686/egg/sqlalchemy/orm/session.py", line 114, in execute
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 244, in execute
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 268, in execute_clauseelement
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 284, in execute_compiled
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 280, in proxy
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 319, in _execute_raw
File "build/bdist.linux-i686/egg/sqlalchemy/engine/base.py", line 338, in _execute
sqlalchemy.exceptions.SQLError: (DatabaseError) ORA-00904: "LANG_DATA_59FB"."LANGUAGE_ID": invalid identifier
'SELECT lang_data.content_id AS lang_data_content_id, lang_data.id AS lang_data_id, language_8eca.id AS language_8eca_id, lang_data.language_id AS lang_data_language_id \nFROM lang_data lang_data_59fb, lang_data LEFT OUTER JOIN language language_8eca ON language_8eca.id = lang_data_59fb.language_id \nWHERE :lazy_9f71 = lang_data.content_id ORDER BY lang_data.rowid, language_8eca.rowid' {'lazy_9f71': 1}
The wrong sql reformatted:
SELECT
lang_data.content_id AS lang_data_content_id,
lang_data.id AS lang_data_id,
language_8eca.id AS language_8eca_id,
lang_data.language_id AS lang_data_language_id
FROM
lang_data lang_data_59fb,
lang_data LEFT OUTER JOIN language language_8eca ON language_8eca.id = lang_data_59fb.language_id
WHERE
:lazy_9f71 = lang_data.content_id ORDER BY lang_data.rowid, language_8eca.rowid
{'lazy_9f71': 1}
Comments (2)
-
repo owner -
repo owner - changed status to resolved
changeset:1877 adds a unit test for deep eager loaders degrading properly to a lazy loader. while its "failure" condition without the fixes from changeset:1876 is not quite as complicated as the test case on this ticket, it still relies on the concept of the eager chain not polluting the default chain of mappers/properties.
- Log in to comment
this is a very complicated bug, which comes down to a failure of the eager loaders on "lang_data" to properly degrade to a lazy loader when the parent object has been loaded by a mapper that does not include columns required by the eager loaders.
i believe the change made in changeset:1876 addreses it, by moving away the "eager chain" of relations/mappers used to create the join query from the normal chain of mappers that is needed for lazy loading...test case then passes.
also need to add unit tests to the "eager degrade" set of tests, so keeping it open.
finding this bug also revealed
#309.