I recently upgraded from SQLAlchemy 1.2 to 1.3 and one of the relationships
I have no longer works. I'm trying to reflect an existing schema and
provide a base class that provides some helper methods to all of my ORM
classes. I'm also trying to defer reflection to after the ORM classes are
prepared.
The error I'm seeing is:
File "scratch.py", line 98, in <module>
a = session.query(A)
File "lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1544,
in query
return self._query_cls(entities, self, **kwargs)
File "lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 168, in
__init__
self._set_entities(entities)
File "lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 200, in
_set_entities
self._set_entity_selectables(self._entities)
File "lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 231, in
_set_entity_selectables
ent.setup_entity(*d[entity])
File "lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 4121, in
setup_entity
self._with_polymorphic = ext_info.with_polymorphic_mappers
File "lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line
855, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2135, in
_with_polymorphic_mappers
configure_mappers()
File "lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 3248, in
configure_mappers
mapper._post_configure_properties()
File "lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1947, in
_post_configure_properties
prop.init()
File "lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 196,
in init
self.do_init()
File "lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line
1860, in do_init
self._process_dependent_arguments()
File "lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line
1889, in _process_dependent_arguments
setattr(self, attr, attr_value())
File
"lib/python2.7/site-packages/sqlalchemy/ext/declarative/clsregistry.py",
line 294, in __call__
x = eval(self.arg, globals(), self._dict)
File "<string>", line 1, in <module>
File "lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line
734, in __missing__
self[key] = val = self.creator(key)
File
"lib/python2.7/site-packages/sqlalchemy/ext/declarative/clsregistry.py",
line 286, in _access_cls
value = resolv(key)
File "lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py",
line 778, in _resolve
cls._reflect_table(t1, engine)
File "lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py",
line 811, in _reflect_table
schema=table.schema,
File "<string>", line 2, in __new__
File "lib/python2.7/site-packages/sqlalchemy/util/deprecations.py", line
128, in warned
return fn(*args, **kwargs)
File "lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 492, in
__new__
table._init_existing(*args, **kw)
File "lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 708, in
_init_existing
_extend_on=_extend_on,
File "lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 619, in
_autoload
_extend_on=_extend_on,
File "lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2160,
in run_callable
return conn.run_callable(callable_, *args, **kwargs)
File "lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1612,
in run_callable
return callable_(self, *args, **kwargs)
File "lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 459,
in reflecttable
table, include_columns, exclude_columns, resolve_fks, **opts
File "lib/python2.7/site-packages/sqlalchemy/engine/reflection.py", line
629, in reflecttable
table_name, schema, **table.dialect_kwargs
File "lib/python2.7/site-packages/sqlalchemy/engine/reflection.py", line
314, in get_table_options
self.bind, table_name, schema, info_cache=self.info_cache, **kw
File "<string>", line 2, in get_table_options
File "lib/python2.7/site-packages/sqlalchemy/engine/reflection.py", line
56, in cache
ret = fn(self, con, *args, **kw)
File "lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py",
line 2499, in get_table_options
connection, table_name, schema, **kw
File "lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py",
line 2745, in _parsed_state_or_create
info_cache=kw.get("info_cache", None),
File "<string>", line 2, in _setup_parser
File "lib/python2.7/site-packages/sqlalchemy/engine/reflection.py", line
56, in cache
ret = fn(self, con, *args, **kw)
File "lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py",
line 2773, in _setup_parser
connection, None, charset, full_name=full_name
File "lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py",
line 2876, in _show_create_table
raise exc.NoSuchTableError(full_name)
sqlalchemy.exc.NoSuchTableError: `join`
Here's a repro based on the example from the docs (
https://docs.sqlalchemy.org/en/13/orm/join_conditions.html?highlight=secondary%20composite#composite-secondary-joins
)
from sqlalchemy import Column, Integer, ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import relationship, Session
_Base = declarative_base()
class Base(_Base, DeferredReflection):
__abstract__ = True
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
b_id = Column(ForeignKey('b.id'))
d = relationship("D",
secondary="join(B, D, B.d_id == D.id)."
"join(C, C.d_id == D.id)",
primaryjoin="and_(A.b_id == B.id, A.id == C.a_id)",
secondaryjoin="D.id == B.d_id",
uselist=True
)
class B(Base):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
d_id = Column(ForeignKey('d.id'))
class C(Base):
__tablename__ = 'c'
id = Column(Integer, primary_key=True)
a_id = Column(ForeignKey('a.id'))
d_id = Column(ForeignKey('d.id'))
class D(Base):
__tablename__ = 'd'
id = Column(Integer, primary_key=True)
engine =
create_engine("mysql+mysqldb://[email protected]:3306/testing?charset=utf8mb4&binary_prefix=true",
echo=True)
engine.execute("""
DROP DATABASE testing;
CREATE DATABASE testing;
USE testing;
CREATE TABLE d (
id int unsigned auto_increment,
primary key (id)
) engine=innodb;
CREATE TABLE b (
id int unsigned auto_increment,
d_id int unsigned default null,
primary key (id),
foreign key (d_id) references `d` (id)
) engine=innodb;
CREATE TABLE a (
id int unsigned auto_increment,
b_id int unsigned default null,
primary key (id),
foreign key (b_id) references `b` (id)
) engine=innodb;
CREATE TABLE c (
id int unsigned auto_increment,
a_id int unsigned default null,
d_id int unsigned default null,
primary key (id),
foreign key (a_id) references `a` (id),
foreign key (d_id) references `d` (id)
) engine=innodb;
INSERT INTO d (id) values (1), (2), (3);
INSERT INTO b (d_id) values (1), (1), (2);
INSERT INTO a (b_id) values (2), (3), (1);
INSERT INTO c (a_id, d_id) values (1, 1), (1, 2), (2, 3);
""")
Base.metadata.reflect(bind=engine)
A.prepare(engine)
B.prepare(engine)
C.prepare(engine)
D.prepare(engine)
engine =
create_engine("mysql+mysqldb://[email protected]:3306/testing?charset=utf8mb4&binary_prefix=true",
echo=True)
session = Session(engine)
a = session.query(A)
for _a in a:
print(a)
if _a.d:
print(list(_a.d))
I've verified that the error only happens when I defer reflection. I.e. I
remove the DefferedReflection base class from _Base and I comment out the
A.prepare(engine)... lines.
Has anyone else run into this?
Thanks!
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sqlalchemy/b6e3e875-3d17-49c0-b5f6-70d7215ea3f0%40googlegroups.com.