that error can be fixed using correlate_except: @classmethod def hybrid_type_name_subquery(cls): return select([HybridType.name]).\ where(HybridType.id == cls.hybrid_type_id).\ correlate_except(HybridType).as_scalar()
but now that we're looking at your queries in full, the comparator makes no sense. It just pulls in HybridType into the FROM clause and makes a broken query with "FROM hybrids, hybrid_types" without them being joined. your tests pass just using plain @expression and keeping the subqueries contained: @hybrid_property def hybrid_type_name(self): return self.hybrid_type.name @hybrid_type_name.setter def hybrid_type_name(self, value): self.hybrid_type_id = ( select([HybridType.id]). where(HybridType.name == value) ) @hybrid_type_name.expression def hybrid_type_name(cls): return cls.hybrid_type_name_subquery() @classmethod def hybrid_type_name_subquery(cls): return select([HybridType.name]).\ where(HybridType.id == cls.hybrid_type_id).as_scalar() for extra protection with correlation, correlate_except looks like this: @classmethod def hybrid_type_name_subquery(cls): return select([HybridType.name]).\ where(HybridType.id == cls.hybrid_type_id).\ correlate_except(HybridType).as_scalar() On Tue, Oct 31, 2017 at 12:18 PM, Tucker Beck <tucker.b...@gmail.com> wrote: > Thanks so much for getting back so fast, Mike! > > For some background: we started with the expression, but then discovered > that the performance we were getting was pretty bad on queries when the > table was large and we were filtering by the hybrid attribute. Postgres was > doing a sequence-scan, and the plan was pretty bad. So, I learned about > custom comparators, and that helped the performance for those kind of > queries really dramatically. I didn't realize that the comparator was not > meant to be used along-side an expression; I thought they served different > purposes. > > Trying your suggestion worked great for order_by. However, filtering on the > hybrid attribute is failing with complaints about correlation. > > I revised the code as: > > from sqlalchemy import * > from sqlalchemy.orm import * > from sqlalchemy.ext.declarative import declarative_base, declared_attr > from sqlalchemy.ext.hybrid import hybrid_property, Comparator > > Base = declarative_base() > > class classproperty(property): > """A decorator that behaves like @property except that operates > on classes rather than instances. > > The decorator is currently special when using the declarative > module, but note that the > :class:`~.sqlalchemy.ext.declarative.declared_attr` > decorator should be used for this purpose with declarative. > > """ > > def __init__(self, fget, *arg, **kw): > super(classproperty, self).__init__(fget, *arg, **kw) > self.__doc__ = fget.__doc__ > > def __get__(desc, self, cls): > return desc.fget(cls) > > > class ModelBase(Base): > __abstract__ = True > > def __repr__(self): > return "{} ({}:{})".format(type(self).__name__, self.name, self.id) > > > class HybridType(ModelBase): > __tablename__ = 'hybrid_types' > id = Column(Integer, primary_key=True) > name = Column(Text) > > > class HybridModel(ModelBase): > __tablename__ = 'hybrids' > > id = Column(Integer, primary_key=True) > name = Column(Text) > hybrid_type_id = Column(Integer, ForeignKey('hybrid_types.id'), > nullable=False) > hybrid_type = relationship('HybridType') > > def __init__(self, *args, **kwargs): > self.hybrid_type_name = self.hybrid_type_identity > return super().__init__(*args, **kwargs) > > @classproperty > def hybrid_type_identity(cls): > return cls.__name__ > > @declared_attr > def __mapper_args__(cls): > return dict( > polymorphic_on=cls.hybrid_type_name_subquery(), > polymorphic_identity=cls.hybrid_type_identity, > ) > > @hybrid_property > def hybrid_type_name(self): > return self.hybrid_type.name > > @hybrid_type_name.setter > def hybrid_type_name(self, value): > self.hybrid_type_id = ( > select([HybridType.id]). > where(HybridType.name == value) > ) > > @classmethod > def hybrid_type_name_subquery(cls): > return select([HybridType.name]).where(HybridType.id == > cls.hybrid_type_id).as_scalar() > > class HybridComparator(Comparator): > > def __clause_element__(self): > return self.expression.hybrid_type_name_subquery() > > def operate(self, op, other): > return op(HybridType.id, > select([HybridType.id]).where(HybridType.name == other).as_scalar()) > > @hybrid_type_name.comparator > def hybrid_type_name(cls): > return cls.HybridComparator(cls) > > > class HybridAlpha(HybridModel): > pass > > > class HybridBeta(HybridModel): > pass > > > e = create_engine("sqlite://", echo=False) > Base.metadata.create_all(e) > session = Session(e) > > > session.add(HybridType(name=HybridAlpha.hybrid_type_identity)) > session.add(HybridType(name=HybridBeta.hybrid_type_identity)) > session.add(HybridAlpha(name='alpha_instance')) > session.add(HybridBeta(name='beta_instance')) > > > print("--- Test query from base hybrid model ---") > assert session.query(HybridModel).count() == 2 > print("passed") > print("--- Test query from base derived hybrid model ---") > assert session.query(HybridAlpha).count() == 1 > assert session.query(HybridBeta).count() == 1 > print("passed") > print("--- Test query order_by on hybrid attribute ---") > assert [ > x.hybrid_type_name for x > in session.query(HybridModel).order_by(HybridModel.hybrid_type_name) > ] == [HybridAlpha.hybrid_type_identity, HybridBeta.hybrid_type_identity] > print("passed") > print("--- Test query filter_by on hybrid attribute ---") > assert > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).count() > == 1 > print("passed") > print("--- Test query filtered on hybrid attribute ---") > assert session.query(HybridModel).filter(HybridAlpha.hybrid_type_name == > HybridAlpha.hybrid_type_identity).count() == 1 > print("passed") > > > And here's the output > > /venv:cem/ $ python demo.py > --- Test query from base hybrid model --- > passed > --- Test query from base derived hybrid model --- > passed > --- Test query order_by on hybrid attribute --- > passed > --- Test query filter_by on hybrid attribute --- > Traceback (most recent call last): > File "demo.py", line 124, in <module> > assert > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).correlate(HybridModel).count() > == 1 > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 3089, in count > return self.from_self(col).scalar() > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 2843, in scalar > ret = self.one() > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 2814, in one > ret = self.one_or_none() > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 2784, in one_or_none > ret = list(self) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 2855, in __iter__ > return self._execute_and_instances(context) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", > line 2878, in _execute_and_instances > result = conn.execute(querycontext.statement, self._params) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/engine/base.py", > line 945, in execute > return meth(self, multiparams, params) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", > line 263, in _execute_on_connection > return connection._execute_clauseelement(self, multiparams, params) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/engine/base.py", > line 1046, in _execute_clauseelement > if not self.schema_for_object.is_default else None) > File "<string>", line 1, in <lambda> > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", > line 436, in compile > return self._compiler(dialect, bind=bind, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", > line 442, in _compiler > return dialect.statement_compiler(dialect, self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 435, in __init__ > Compiled.__init__(self, dialect, statement, **kwargs) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 216, in __init__ > self.string = self.process(self.statement, **compile_kwargs) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 242, in process > return obj._compiler_dispatch(self, **kwargs) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1738, in visit_select > text, select, inner_columns, froms, byfrom, kwargs) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1817, in _compose_select_body > for f in froms]) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1817, in <listcomp> > for f in froms]) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1379, in visit_alias > asfrom=True, **kwargs) + \ > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/annotation.py", > line 80, in _compiler_dispatch > self, visitor, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1716, in visit_select > for name, column in select._columns_plus_names > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1716, in <listcomp> > for name, column in select._columns_plus_names > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1488, in _label_select_column > **column_clause_args > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 664, in visit_label > OPERATORS[operators.as_] + \ > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 576, in visit_grouping > return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")" > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", > line 81, in _compiler_dispatch > return meth(self, **kw) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1685, in visit_select > froms = self._setup_select_stack(select, entry, asfrom, lateral) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", > line 1788, in _setup_select_stack > implicit_correlate_froms=asfrom_froms) > File > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/selectable.py", > line 2843, in _get_display_froms > "manually." % self) > sqlalchemy.exc.InvalidRequestError: Select statement 'SELECT > hybrid_types.name > FROM hybrid_types, hybrids > WHERE hybrid_types.id = hybrids.hybrid_type_id' returned no FROM clauses due > to auto-correlation; specify correlate(<tables>) to control correlation > manually. > > I've tried looking for some examples for how to use correlate and tried > stuffing it in a few places and still haven't gotten around this error. What > am I missing? > > (Thanks again so much for the quick response) > > > On Mon, Oct 30, 2017 at 4:58 PM, Mike Bayer <mike...@zzzcomputing.com> > wrote: >> >> On Mon, Oct 30, 2017 at 6:43 PM, Tucker Beck <tucker.b...@gmail.com> >> wrote: >> > I wrestled through getting a model heirarchy to work with single-table >> > inheritance that is polymorphic on a hybrid attribute on this mailing >> > list a >> > while ago. >> > >> > see: https://groups.google.com/d/topic/sqlalchemy/KJXSHwbhbLA/discussion >> > >> > The problem I'm running into now is that it doesn't seem to work >> > correctly >> > when I want to use the hybrid property for filtering or ordering. >> > This seems to be an issue with auto-correlation, but I can't seem to >> > figure >> > out how to get it working. >> > >> > Here is a runnable example: >> >> OK so lets pdb: >> >> class HybridBeta(HybridModel): >> pass >> >> >> session = Session() >> >> import pdb >> pdb.set_trace() >> >> >> >> what are we getting from HybridModel.hybrid_type_name: >> >> (Pdb) HybridModel.hybrid_type_name >> <sqlalchemy.orm.attributes.create_proxied_attribute.<locals>.Proxy >> object at 0x7f95594ca200> >> >> >> that's not right. I see there's a @comparator and also an >> @expression. Those actually aren't designed to be used together, >> you'd use one or the other. I'm not sure what you're trying to do >> but based on the organization of what I see you'd want to do this: >> >> @classmethod >> def hybrid_type_name_subquery(cls): >> return select([HybridType.name]).where(HybridType.id == >> cls.hybrid_type_id).as_scalar() >> >> class HybridComparator(Comparator): >> >> def __clause_element__(self): >> return self.expression.hybrid_type_name_subquery() >> >> def operate(self, op, other): >> return op(HybridType.id, >> select([HybridType.id]).where(HybridType.name == other).as_scalar()) >> >> @hybrid_type_name.comparator >> def hybrid_type_name(cls): >> return cls.HybridComparator(cls) >> >> >> which gives you a query: >> >> print(session.query(HybridModel).order_by(HybridModel.hybrid_type_name)) >> >> SELECT hybrids.id AS hybrids_id, hybrids.name AS hybrids_name, >> hybrids.hybrid_type_id AS hybrids_hybrid_type_id, (SELECT >> hybrid_types.name >> FROM hybrid_types >> WHERE hybrid_types.id = hybrids.hybrid_type_id) AS _sa_polymorphic_on >> FROM hybrids ORDER BY (SELECT hybrid_types.name >> FROM hybrid_types >> WHERE hybrid_types.id = hybrids.hybrid_type_id) >> >> >> >> >> >> > >> > from sqlalchemy import * >> > from sqlalchemy.orm import * >> > from sqlalchemy.ext.declarative import declarative_base, declared_attr >> > from sqlalchemy.ext.hybrid import hybrid_property, Comparator >> > >> > Base = declarative_base() >> > >> > class classproperty(property): >> > """A decorator that behaves like @property except that operates >> > on classes rather than instances. >> > >> > The decorator is currently special when using the declarative >> > module, but note that the >> > :class:`~.sqlalchemy.ext.declarative.declared_attr` >> > decorator should be used for this purpose with declarative. >> > >> > """ >> > >> > def __init__(self, fget, *arg, **kw): >> > super(classproperty, self).__init__(fget, *arg, **kw) >> > self.__doc__ = fget.__doc__ >> > >> > def __get__(desc, self, cls): >> > return desc.fget(cls) >> > >> > >> > class ModelBase(Base): >> > __abstract__ = True >> > >> > def __repr__(self): >> > return "{} ({}:{})".format(type(self).__name__, self.name, >> > self.id) >> > >> > >> > class HybridType(ModelBase): >> > __tablename__ = 'hybrid_types' >> > id = Column(Integer, primary_key=True) >> > name = Column(Text) >> > >> > >> > class HybridModel(ModelBase): >> > __tablename__ = 'hybrids' >> > >> > id = Column(Integer, primary_key=True) >> > name = Column(Text) >> > hybrid_type_id = Column(Integer, ForeignKey('hybrid_types.id'), >> > nullable=False) >> > hybrid_type = relationship('HybridType') >> > >> > def __init__(self, *args, **kwargs): >> > self.hybrid_type_name = self.hybrid_type_identity >> > return super().__init__(*args, **kwargs) >> > >> > @classproperty >> > def hybrid_type_identity(cls): >> > return cls.__name__ >> > >> > @declared_attr >> > def __mapper_args__(cls): >> > return dict( >> > polymorphic_on=cls.hybrid_type_name_subquery(), >> > polymorphic_identity=cls.hybrid_type_identity, >> > ) >> > >> > @hybrid_property >> > def hybrid_type_name(self): >> > return self.hybrid_type.name >> > >> > @hybrid_type_name.setter >> > def hybrid_type_name(self, value): >> > self.hybrid_type_id = ( >> > select([HybridType.id]). >> > where(HybridType.name == value) >> > ) >> > >> > @hybrid_type_name.expression >> > def hybrid_type_name(cls): >> > return cls.hybrid_type_name_subquery() >> > >> > @classmethod >> > def hybrid_type_name_subquery(cls): >> > return select([HybridType.name]).where(HybridType.id == >> > cls.hybrid_type_id).as_scalar() >> > >> > class HybridComparator(Comparator): >> > >> > def operate(self, op, other): >> > return op(HybridType.id, >> > select([HybridType.id]).where(HybridType.name == other).as_scalar()) >> > >> > @hybrid_type_name.comparator >> > def hybrid_type_name(cls): >> > return cls.HybridComparator(cls) >> > >> > >> > class HybridAlpha(HybridModel): >> > pass >> > >> > >> > class HybridBeta(HybridModel): >> > pass >> > >> > >> > e = create_engine("sqlite://", echo=False) >> > Base.metadata.create_all(e) >> > session = Session(e) >> > >> > >> > session.add(HybridType(name=HybridAlpha.hybrid_type_identity)) >> > session.add(HybridType(name=HybridBeta.hybrid_type_identity)) >> > session.add(HybridAlpha(name='alpha_instance')) >> > session.add(HybridBeta(name='beta_instance')) >> > >> > >> > print("--- Test query from base hybrid model ---") >> > assert session.query(HybridModel).count() == 2 >> > print("passed") >> > print("--- Test query from base derived hybrid model ---") >> > assert session.query(HybridAlpha).count() == 1 >> > assert session.query(HybridBeta).count() == 1 >> > print("passed") >> > print("--- Test query order_by on hybrid attribute ---") >> > assert [ >> > x.hybrid_type_name for x >> > in session.query(HybridModel).order_by(HybridModel.hybrid_type_name) >> > ] == [HybridAlpha.hybrid_type_identity, HybridBeta.hybrid_type_identity] >> > print("passed") >> > print("--- Test query filter_by on hybrid attribute ---") >> > assert >> > >> > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).count() >> > == 1 >> > print("passed") >> > print("--- Test query filtered on hybrid attribute ---") >> > assert session.query(HybridModel).filter(HybridAlpha.hybrid_type_name == >> > HybridAlpha.hybrid_type_identity).count() == 1 >> > print("passed") >> > >> > >> > >> > Running this results in the following out put: >> > $ python demo.py >> > --- Test query from base hybrid model --- >> > passed >> > --- Test query from base derived hybrid model --- >> > passed >> > --- Test query order_by on hybrid attribute --- >> > Traceback (most recent call last): >> > File "demo.py", line 121, in <module> >> > in session.query(HybridModel).order_by(HybridModel.hybrid_type_name) >> > File "<string>", line 2, in order_by >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/base.py", >> > line 201, in generate >> > fn(self, *args[1:], **kw) >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 1589, in order_by >> > criterion = self._adapt_col_list(criterion) >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 256, in _adapt_col_list >> > for o in cols >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 256, in <listcomp> >> > for o in cols >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> > line 4191, in _literal_as_label_reference >> > return _literal_as_text(element) >> > File >> > >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> > line 4230, in _literal_as_text >> > "instead" % type(element) >> > sqlalchemy.exc.ArgumentError: SQL expression object or string expected, >> > got >> > object of type <class 'sqlalchemy.ext.declarative.api.DeclarativeMeta'> >> > instead >> > >> > -- >> > 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 post to this group, send email to sqlalchemy@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> 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 a topic in the >> Google Groups "sqlalchemy" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/sqlalchemy/M4b5y_d69u0/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> sqlalchemy+unsubscr...@googlegroups.com. >> To post to this group, send email to sqlalchemy@googlegroups.com. >> Visit this group at https://groups.google.com/group/sqlalchemy. >> For more options, visit https://groups.google.com/d/optout. > > > > > -- > -=Tucker A. Beck=- > > Illustrious Writer > Devious Coder > Last Hope for the Free World > Also, Modest > > -- > 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 post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- 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 post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.