Ok, copied to https://bitbucket.org/zzzeek/sqlalchemy/issues/3941

W dniu piątek, 17 marca 2017 15:34:11 UTC+1 użytkownik Mike Bayer napisał:
>
> that's not a bad idea at all can you transfer this to a bug report at 
> https://bitbucket.org/zzzeek/sqlalchemy/issues?status=new&status=open ? 
> that would be helpful. 
>
>
>
> On 03/17/2017 09:11 AM, bartwo...@gmail.com <javascript:> wrote: 
> > I've run into autoflush issue while using AssociationProxy with 
> > sqlalchemy-1.1.6. Appending to association list fails, because object is 
> > flushed before it is appended (and appending sets primary key value). I 
> > can avoid it with session.no_autoflush context manager, but I wonder if 
> > it's not worth slightly changing proxy behaviour to make it work with 
> > autoflush enabled. 
> > 
> > Minimal example of this issue below: 
> > 
> > | 
> > engine =engine_from_config(CONFIG) 
> > DBSession=scoped_session(sessionmaker()) 
> > DBSession.configure(bind=engine) 
> > Base=declarative_base() 
> > 
> > 
> > classUserAlias(Base): 
> >     __tablename__ ='user_aliases' 
> >     user_id =Column(Integer,ForeignKey('user.id'),primary_key=True) 
> >     alias_id =Column(Integer,ForeignKey('aliases.id'),primary_key=True) 
> >     valid =Column(Boolean) 
> > 
> >     
> alias=relationship('Alias',backref=backref('user_assocs',uselist=False)) 
> >     user =relationship('User',backref=backref('alias_assocs')) 
> > 
> >     def__init__(self,alias,valid=True): 
> >         self.alias=alias 
> >         self.valid =valid 
> > 
> > 
> > classAlias(Base): 
> >     __tablename__ ='aliases' 
> >     id =Column(Integer,primary_key=True) 
> >     name =Column('name',String(64)) 
> > 
> >     user =association_proxy('user_assocs','user') 
> > 
> >     def__init__(self,name): 
> >         self.name =name 
> > 
> > 
> > classUser(Base): 
> >     __tablename__ ='user' 
> >     id =Column(Integer,primary_key=True) 
> >     name =Column(String(64)) 
> > 
> >     aliases =association_proxy('alias_assocs','alias') 
> > 
> >     def__init__(self,name): 
> >         self.name =name 
> > 
> > 
> > deftest_assoc(): 
> >     user =User(name='John') 
> >     DBSession.add(user) 
> >     DBSession.commit() 
> > 
> >     johny =Alias(name='Johny') 
> >     user.aliases.append(johny) 
> >     DBSession.commit() 
> > 
> >     jan =Alias(name='Jan') 
> >     DBSession.add(jan) # in my real use case proxied object is already 
> > attached to session before appending, here I simulate it with 
> DBSession.add 
> >     user.aliases.append(jan) # autoflush fails here 
> > 
> >     DBSession.commit() 
> >     returnuser 
> > | 
> > 
> > and stacktrace: 
> > 
> > | 
> > 
> /home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/sql/crud.py:692:SAWarning:Column'user_aliases.user_id'ismarked
>  
>
> > asa member of the primary key fortable 'user_aliases',but has 
> > noPython-side orserver-side defaultgenerator indicated,nor does it 
> > indicate 'autoincrement=True'or'nullable=True',andnoexplicitvalue 
> > ispassed. Primarykey columns typically may notstore NULL.Notethat asof 
> > SQLAlchemy1.1,'autoincrement=True'must be indicated explicitly 
> > forcomposite (e.g.multicolumn)primary keys 
> > ifAUTO_INCREMENT/SERIAL/IDENTITY behavior isexpected forone of the 
> > columns inthe primary key.CREATE TABLE statements are impacted 
> > bythischange aswell on most backends. 
> >   util.warn(msg) 
> > Traceback(most recent call last): 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 1182,in_execute_context 
> >     context) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/default.py",line
>  
>
> > 470,indo_execute 
> >     cursor.execute(statement,parameters) 
> > psycopg2.IntegrityError:nullvalue incolumn "user_id"violates 
> > not-nullconstraint 
> > DETAIL: Failingrow contains (null,50,t). 
> > 
> > 
> > Theabove exception was the direct cause of the following exception: 
> > 
> > Traceback(most recent call last): 
> >   File"/home/bartek/dev/sqlalchemy-test/sqlalchemy_test/models.py",line 
> > 111,in<module> 
> >     test_assoc() 
> >   File"/home/bartek/dev/sqlalchemy-test/sqlalchemy_test/models.py",line 
> > 105,intest_assoc 
> >     user.aliases.append(jan) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line
>  
>
> > 610,inappend 
> >     self.col.append(item) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line
>  
>
> > 509,in<lambda> 
> >     col =property(lambdaself:self.lazy_collection()) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line
>  
>
> > 467,in__call__ 
> >     returngetattr(obj,self.target) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py",line
>  
>
> > 237,in__get__ 
> >     returnself.impl.get(instance_state(instance),dict_) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py",line
>  
>
> > 584,inget 
> >     value =self.callable_(state,passive) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py",line
>  
>
> > 557,in_load_for_state 
> >     returnself._emit_lazyload(session,state,ident_key,passive) 
> >   File"<string>",line 1,in<lambda> 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py",line
>  
>
> > 635,in_emit_lazyload 
> >     result =q.all() 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/query.py",line
>  
>
> > 2679,inall 
> >     returnlist(self) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/query.py",line
>  
>
> > 2830,in__iter__ 
> >     self.session._autoflush() 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line
>  
>
> > 1375,in_autoflush 
> >     util.raise_from_cause(e) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line
>  
>
> > 203,inraise_from_cause 
> >     reraise(type(exception),exception,tb=exc_tb,cause=cause) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line
>  
>
> > 187,inreraise 
> >     raisevalue 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line
>  
>
> > 1365,in_autoflush 
> >     self.flush() 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line
>  
>
> > 2139,inflush 
> >     self._flush(objects) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line
>  
>
> > 2259,in_flush 
> >     transaction.rollback(_capture_exception=True) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/langhelpers.py",line
>  
>
> > 60,in__exit__ 
> >     compat.reraise(exc_type,exc_value,exc_tb) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line
>  
>
> > 187,inreraise 
> >     raisevalue 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line
>  
>
> > 2223,in_flush 
> >     flush_context.execute() 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py",line
>  
>
> > 389,inexecute 
> >     rec.execute(self) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py",line
>  
>
> > 548,inexecute 
> >     uow 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py",line
>  
>
> > 181,insave_obj 
> >     mapper,table,insert) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py",line
>  
>
> > 835,in_emit_insert_statements 
> >     execute(statement,params) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 945,inexecute 
> >     returnmeth(self,multiparams,params) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/sql/elements.py",line
>  
>
> > 263,in_execute_on_connection 
> >     returnconnection._execute_clauseelement(self,multiparams,params) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 1053,in_execute_clauseelement 
> >     compiled_sql,distilled_params 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 1189,in_execute_context 
> >     context) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 1393,in_handle_dbapi_exception 
> >     exc_info 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line
>  
>
> > 203,inraise_from_cause 
> >     reraise(type(exception),exception,tb=exc_tb,cause=cause) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line
>  
>
> > 186,inreraise 
> >     raisevalue.with_traceback(tb) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line
>  
>
> > 1182,in_execute_context 
> >     context) 
> > 
> > 
> File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/default.py",line
>  
>
> > 470,indo_execute 
> >     cursor.execute(statement,parameters) 
> > sqlalchemy.exc.IntegrityError:(raised asa result of Query-invoked 
> > autoflush;consider usinga session.no_autoflush block ifthisflush 
> > isoccurring prematurely)(psycopg2.IntegrityError)nullvalue incolumn 
> > "user_id"violates not-nullconstraint 
> > DETAIL: Failingrow contains (null,50,t). 
> >  [SQL:'INSERT INTO user_aliases (alias_id, valid) VALUES (%(alias_id)s, 
> > %(valid)s)'][parameters:{'alias_id':50,'valid':True}] 
> > | 
> > 
> > Autoflush occurs in _AssociationList append method: 
> > 
> > | 
> >     defappend(self,value): 
> >         item =self._create(value) 
> >         self.col.append(item) 
> > | 
> > 
> > If _create was called before self.col is evaluted created object would 
> > not be autoflushed prematurely. Maybe it is worth changing it if it does 
> > not break anything else. 
> > 
> > -- 
> > 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 <javascript:> 
> > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:> 
> > <mailto:sqlal...@googlegroups.com <javascript:>>. 
> > 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.

Reply via email to