Okay, thanks a lot.

2017-10-28 13:36 GMT-04:00 Mike Bayer <mike...@zzzcomputing.com>:

> On Fri, Oct 27, 2017 at 9:54 PM,  <char...@konversion.ca> wrote:
> > I'm not querying polymorphically.
> >
> > Let me restate the problem with more details(my post as done in haste).
> >
> > With something like the example I gave(completed with what's missing,
> e.g.
> > table names, definition for related table),
>
> thank you, with the stack trace I can construct what is going on.
>
> There is a bug that needs a patch to work, in terms of the descriptor,
> this is up at https://bitbucket.org/zzzeek/sqlalchemy/issues/4124/
> abstractconcretebase-transmitting
> and the patch you see here:
> https://gerrit.sqlalchemy.org/#/c/590/1/lib/sqlalchemy/orm/loading.py
> fixes it.
>
> Also, your Concrete1 and Concrete2 classes should specify
> __mapper_args__ = {"concrete": True}, without that, you can also get
> this problem even without the start/end descriptors, but the fix in
> 4124 above will also prevent this scenario from occurring.
>
> However this part:
>
> >
> > MyBase.start, MyBase.end # that's weird, the Abstract base also has those
> > attributes now
>
> that part is normal.   The AbstractConcreteBase indicates you'd like
> to query across all subclasses at once, and the way it works out at
> the moment is that you'll see every column mapped get associated with
> it and you do have start/end columns mapped.   if you don't need to
> query in this way (which in general it's inefficient from a SQL
> perspective), you should not use AbstractConcreteBase.  Polymorphic
> querying across concrete subclasses is a worst case scenario and ACB
> is still pretty hacky.
>
>
>
>
>
> >
> > session.expire(results[0])
> > results[0].start
> >
> > Traceback (most recent call last):
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/IPython/core/interactiveshell.py",
> > line 3035, in run_code
> >     exec(code_obj, self.user_global_ns, self.user_ns)
> >   File "<ipython-input-14-25b20252b355>", line 1, in <module>
> >     results[0].start
> >   File "/home/charles/PycharmProjects/MyProject/my_models.py", line
> 456, in
> > start
> >     return self.details.start
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/attributes.py",
> > line 237, in __get__
> >     return self.impl.get(instance_state(instance), dict_)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/attributes.py",
> > line 584, in get
> >     value = self.callable_(state, passive)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/strategies.py",
> > line 539, in _load_for_state
> >     passive
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/strategies.py",
> > line 575, in _get_ident_for_use_get
> >     for pk in self.mapper.primary_key
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/strategies.py",
> > line 575, in <listcomp>
> >     for pk in self.mapper.primary_key
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/mapper.py",
> > line 2564, in _get_state_attr_by_column
> >     return state.manager[prop.key].impl.get(state, dict_,
> passive=passive)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/attributes.py",
> > line 579, in get
> >     value = state._load_expired(state, passive)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/state.py",
> > line 592, in _load_expired
> >     self.manager.deferred_scalar_loader(self, toload)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 713, in load_scalar_attributes
> >     only_load_props=attribute_names)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 223, in load_on_ident
> >     return q.one()
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/query.py",
> > line 2814, in one
> >     ret = self.one_or_none()
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/query.py",
> > line 2784, in one_or_none
> >     ret = list(self)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 90, in instances
> >     util.raise_from_cause(err)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/util/compat.py",
> > line 203, in raise_from_cause
> >     reraise(type(exception), exception, tb=exc_tb, cause=cause)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/util/compat.py",
> > line 187, in reraise
> >     raise value
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 57, in instances
> >     for query_entity in query._entities
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 57, in <listcomp>
> >     for query_entity in query._entities
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/query.py",
> > line 3700, in row_processor
> >     polymorphic_discriminator=self._polymorphic_discriminator
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 299, in _instance_processor
> >     mapper._props[k] for k in only_load_props)
> >   File
> > "/home/charles/PycharmProjects/MyProject/env/
> lib/python3.6/site-packages/sqlalchemy/orm/loading.py",
> > line 299, in <genexpr>
> >     mapper._props[k] for k in only_load_props)
> > KeyError: 'start'
> >
> >
> > So on refresh, the loading process seems to expect 'start' and 'end' to
> be
> > registered by the mappers(which they would be if they were columns, I
> > guess).
> >
> >
> > Le vendredi 27 octobre 2017 13:36:53 UTC-4, Mike Bayer a écrit :
> >>
> >> On Fri, Oct 27, 2017 at 11:57 AM,  <cha...@konversion.ca> wrote:
> >> > My SQLAlchemy version is 1.1.14.
> >> >
> >> > I'm having difficulty understanding behaviours around a polymorphic
> >> > hierarchy.
> >> >
> >> > I have an AbstractConcreteBase and two subclasses.
> >> >
> >> > The ACB declares some attributes shared by the two subclasses, and the
> >> > subclasses have attributes of their own that are not shared(i.e. they
> >> > are
> >> > not part of the shared identity represented by the ACB).
> >> >
> >> > class MyBase(AbstractConcreteBase, Base, Mixin):
> >> >     shared_id = Column(Integer,
> >> > default=Sequence("database_shared_id_seq",
> >> > start=0, increment=1), primary_key=True)
> >> >
> >> >     @declared_attr
> >> >     def name(self):
> >> >         return Column(String(100), nullable=False)
> >> >
> >> >     @declared_attr
> >> >     def foreign_key(self):
> >> >         return Column(Integer, ForeignKey("MyOtherTable.id"))
> >> >
> >> >     ...
> >> >
> >> >
> >> > class Concrete1(MyBase):
> >> >     start = Column(Date)
> >> >     end = Column(Date)
> >> >
> >> >
> >> > class Concrete2(MyBase):
> >> >
> >> >     @property
> >> >     def start(self):
> >> >         return self.details.start
> >> >
> >> >     @property
> >> >     def end(self):
> >> >         return self.details.end
> >> >
> >> >     details = relationship("Concrete2Detail", uselist=False,
> >> > viewonly=True)
> >> >
> >> >
> >> > As you can see, "start" and "end" are not declared in the ACB and are
> >> > implemented differently between the table. I don't want them to be
> >> > shared by
> >> > the subclasses.
> >> >
> >> > When I query one of the Concretes, the ACB mapper is updated with the
> >> > "start" and "end" attributes, and then the Concretes are expected to
> >> > implement the attributes on the mapper level(which is not the case for
> >> > Concrete2).
> >>
> >> This is a natural effect of using an "abstract" base.   When you try
> >> to query polymorphically across Concrete1 and Concrete2, you're asking
> >> it to query for the Concrete1.start and end columns.   However it
> >> should not in any way be modifying the Concrete2 mapper itself.   I'm
> >> not sure without running it what "are expected to implement" means.
> >> An error is raised?
> >>
> >>
> >> >
> >> > How can I prevent this from happening?
> >> >
> >> > --
> >> > 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+...@googlegroups.com.
> >> > To post to this group, send email to sqlal...@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.
>
> --
> 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/9uFXrbPMlXI/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.
>



-- 
*Charles Langlois*

*     Programmeur-analyste - Programmer Analyst*


5605 avenue de Gaspé
<https://maps.google.com/?q=5605+avenue+de+Gasp%C3%A9&entry=gmail&source=g>,
Suite 902
Montréal, QC, Canada - H2T 2A4

-- 
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.

Reply via email to