postgres syntax error in associative proxy
Issue #1290
resolved
On a site using psycopg2 and SQLAlchemy 0.5.0 I just got this traceback in the logs:
Module tostyle4you.controllers.retailer:367 in edit
<< for img_id in self.form_result.get("deleteImage", [])](]))
for image in article.images:
if image.id in toDelete:
meta.Session.delete(image)
>> for image in article.images:
Module sqlalchemy.orm.attributes:160 in __get__
<< if instance is None:
return self
return self.impl.get(instance_state(instance))
class _ProxyImpl(object):
>> return self.impl.get(instance_state(instance))
Module sqlalchemy.orm.attributes:366 in get
<< if passive is not PASSIVE_OFF:
return PASSIVE_NORESULT
value = callable_()
if value is not ATTR_WAS_SET:
return self.set_committed_value(state, value)
>> value = callable_()
Module sqlalchemy.orm.strategies:557 in __call__
<< q = q.filter(strategy.lazy_clause(state))
result = q.all()
if strategy.uselist:
return result
>> result = q.all()
Module sqlalchemy.orm.query:1018 in all
<< """
return list(self)
@_generative(__no_clauseelement_condition)
>> return list(self)
Module sqlalchemy.orm.query:1111 in __iter__
<< context.statement.use_labels = True
if self._autoflush and not self._populate_existing:
self.session._autoflush()
return self._execute_and_instances(context)
>> self.session._autoflush()
Module sqlalchemy.orm.session:904 in _autoflush
<< def _autoflush(self):
if self.autoflush and not self._flushing:
self.flush()
def _finalize_loaded(self, states):
>> self.flush()
Module sqlalchemy.orm.session:1349 in flush
<< try:
self._flushing = True
self._flush(objects)
finally:
self._flushing = False
>> self._flush(objects)
Module sqlalchemy.orm.session:1419 in _flush
<< subtransactions=True)
try:
flush_context.execute()
for ext in self.extensions:
>> flush_context.execute()
Module sqlalchemy.orm.unitofwork:260 in execute
<< if self._should_log_info:
self.logger.info("Task dump:\n" + self._dump(tasks))
UOWExecutor().execute(self, tasks)
if self._should_log_info:
self.logger.info("Execute Complete")
>> UOWExecutor().execute(self, tasks)
Module sqlalchemy.orm.unitofwork:723 in execute
<< if isdelete is not True:
for task in tasks:
self.execute_save_steps(trans, task)
if isdelete is not False:
for task in reversed(tasks):
>> self.execute_save_steps(trans, task)
Module sqlalchemy.orm.unitofwork:738 in execute_save_steps
<< def execute_save_steps(self, trans, task):
self.save_objects(trans, task)
self.execute_cyclical_dependencies(trans, task, False)
self.execute_dependencies(trans, task)
>> self.save_objects(trans, task)
Module sqlalchemy.orm.unitofwork:729 in save_objects
<< def save_objects(self, trans, task):
task.mapper._save_obj(task.polymorphic_tosave_objects, trans)
def delete_objects(self, trans, task):
>> task.mapper._save_obj(task.polymorphic_tosave_objects, trans)
Module sqlalchemy.orm.mapper:1358 in _save_obj
<< rows = 0
for state, params, mapper, connection, value_params in update:
c = connection.execute(statement.values(value_params), params)
mapper._postfetch(uowtransaction, connection, table, state, c, c.last_updated_params(), value_params)
>> c = connection.execute(statement.values(value_params), params)
Module sqlalchemy.engine.base:824 in execute
<< for c in type(object).__mro__:
if c in Connection.executors:
return Connection.executors[c](c)(self, object, multiparams, params)
else:
raise exc.InvalidRequestError("Unexecutable object type: " + str(type(object)))
>> return Connection.executors[c](c)(self, object, multiparams, params)
Module sqlalchemy.engine.base:874 in _execute_clauseelement
<< parameters=params
)
return self.__execute_context(context)
def _execute_compiled(self, compiled, multiparams, params):
>> return self.__execute_context(context)
Module sqlalchemy.engine.base:896 in __execute_context
<< self._cursor_executemany(context.cursor, context.statement, context.parameters, context=context)
else:
self._cursor_execute(context.cursor, context.statement, context.parameters[0](0), context=context)
if context.compiled:
context.post_exec()
>> self._cursor_execute(context.cursor, context.statement, context.parameters[0](0), context=context)
Module sqlalchemy.engine.base:950 in _cursor_execute
<< self.dialect.do_execute(cursor, statement, parameters, context=context)
except Exception, e:
self._handle_dbapi_exception(e, statement, parameters, cursor, context)
raise
>> self._handle_dbapi_exception(e, statement, parameters, cursor, context)
Module sqlalchemy.engine.base:931 in _handle_dbapi_exception
<< if self.__close_with_result:
self.close()
raise exc.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect)
finally:
del self._reentrant_error
>> raise exc.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect)
ProgrammingError: (ProgrammingError) syntax error at or near "WHERE" LINE 1: UPDATE clothing_size SET WHERE clothing_size.article_id = 7... ^ 'UPDATE clothing_size SET WHERE clothing_size.article_id = %(clothing_size_article_id)s AND clothing_size.size = %(clothing_size_size)s' {'clothing_size_article_id': 73830, 'clothing_size_size': u'14'}
the relevant models look this this:
class ArticleSize(BaseObject):
__tablename__ = "clothing_size"
article_id = schema.Column(types.Integer(),
schema.ForeignKey("clothing_article.id", onupdate="CASCADE", ondelete="CASCADE"),
primary_key=True, index=True)
size = schema.Column(types.String(8), primary_key=True)
def __init__(self, size, article_id=None):
self.size=size
if article_id is not None:
self.article_id=article_id
class ClothingArticle(BaseObject):
"""An article of clothing
"""
__tablename__ = "clothing_article"
id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)
_sizes = orm.relation(ArticleSize, lazy=True, collection_class=set,
cascade="all, delete, delete-orphan")
sizes = association_proxy("_sizes", "size")
Comments (3)
-
Account Deleted -
Account Deleted And indeed it turns out I was assigning None to the proxy instance. After fixing that things are working as expected.
-
repo owner - changed status to invalid
- Log in to comment
In 0.5.1 the problem manifests itself in a different way, which makes me suspect the problem might be in my code: