question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

sqlalchemy.ext.serializer fail with column_property in query condition

See original GitHub issue

Deserialization of query with column_property fail with error

Traceback (most recent call last):
  File "/home/mzhukov/projects/test_sqa/test_sql/main.py", line 53, in <module>
    assert str(orig_req) == str(deserialized_obj)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3379, in __str__
    return str(context.statement.compile(bind))
  File "<string>", line 1, in <lambda>
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 462, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 468, in _compiler
    return dialect.statement_compiler(dialect, self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 571, in __init__
    Compiled.__init__(self, dialect, statement, **kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 319, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 350, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 2140, in visit_select
    text, select, inner_columns, froms, byfrom, kwargs
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 2239, in _compose_select_body
    t = select._whereclause._compiler_dispatch(self, **kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1299, in visit_binary
    return self._generate_generic_binary(binary, opstring, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1346, in _generate_generic_binary
    + binary.right._compiler_dispatch(
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/annotation.py", line 79, in _compiler_dispatch
    return self.__element.__class__._compiler_dispatch(self, visitor, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 836, in visit_label
    self, within_columns_clause=False, **kw
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/dialects/sqlite/base.py", line 990, in visit_cast
    return super(SQLiteCompiler, self).visit_cast(cast, **kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1015, in visit_cast
    cast.clause._compiler_dispatch(self, **kwargs),
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1119, in visit_function
    ) % {"expr": self.function_argspec(func, **kwargs)}
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1131, in function_argspec
    return func.clause_expr._compiler_dispatch(self, **kwargs)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 727, in visit_grouping
    return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 983, in visit_clauselist
    c._compiler_dispatch(self, **kw) for c in clauselist.clauses
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 981, in <genexpr>
    s
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 983, in <genexpr>
    c._compiler_dispatch(self, **kw) for c in clauselist.clauses
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 92, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/mzhukov/.local/share/virtualenvs/test_sqa-05qMtTeV/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 1503, in visit_bindparam
    % bindparam.key
sqlalchemy.exc.CompileError: Bind parameter '%(140081294316096 left)s' conflicts with unique bind parameter of the same name

I test this error with Python3.7 + SQLAlchemy 1.3.12 In Python2.7 + SQLAlchemy 1.1.18 deserialization does not work too, but with other exception

For reproducing this bug I make simple test file:

# -*- coding: utf-8 -*-
import pickle
import sys
import traceback

from sqlalchemy import create_engine, Integer, Column, String, exc as sa_exc
from sqlalchemy.ext import serializer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import sessionmaker, scoped_session, column_property
from sqlalchemy.sql import func

Base = declarative_base()
db_engine = create_engine('sqlite:///:memory:')
Session = scoped_session(sessionmaker(bind=db_engine))


class TestTable(Base):
    __tablename__ = 'test'

    id = Column(Integer, primary_key=True, autoincrement=True)
    _some_id = Column('some_id', String)
    some_primary_id = column_property(func.left(_some_id, 6).cast(Integer))


class SecondTestTable(Base):
    __tablename__ = 'test2'

    id = Column(Integer, primary_key=True, autoincrement=True)
    _some_id = Column('some_id', String)

    @hybrid_property
    def some_primary_id(self):
        return int(self._some_id[:6])

    @some_primary_id.expression
    def some_primary_id(cls):
        return func.left(cls._some_id, 6).cast(Integer)


#  Create tables and two records
Base.metadata.create_all(bind=db_engine)
db_session = Session()
db_session.add(TestTable(_some_id="1234567890"))
db_session.add(SecondTestTable(_some_id="1234567890"))
db_session.commit()

#  Query without column_property in condition work
orig_req = db_session.query(TestTable)
serialised_obj = serializer.dumps(orig_req, pickle.HIGHEST_PROTOCOL)
deserialized_obj = serializer.loads(serialised_obj, metadata=Base.metadata, scoped_session=Session)
assert str(orig_req) == str(deserialized_obj)

#  Query with column_property in condition fail
orig_req = db_session.query(TestTable).filter(TestTable.some_primary_id == 123456)
serialised_obj = serializer.dumps(orig_req, pickle.HIGHEST_PROTOCOL)
deserialized_obj = serializer.loads(serialised_obj, metadata=Base.metadata, scoped_session=Session)
try:
    assert str(orig_req) == str(deserialized_obj)
except sa_exc.SQLAlchemyError as exc:
    print('Error: %r' % exc)
    traceback.print_exc(file=sys.stdout)

#  Query with hybrid_property in condition work
orig_req = db_session.query(SecondTestTable).filter(SecondTestTable.some_primary_id == 123456)
serialised_obj = serializer.dumps(orig_req, pickle.HIGHEST_PROTOCOL)
deserialized_obj = serializer.loads(serialised_obj, metadata=Base.metadata, scoped_session=Session)
assert str(orig_req) == str(deserialized_obj)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
MikhailZhukovcommented, Jan 13, 2020

yes, i think we will do that in nearest future. I replaced all column_property to hybrid_property now and it look like it work good enough while we will refactor code base

0reactions
zzzeekcommented, Jan 13, 2020

is it possible that instaed of caching the completed query, you cache the information from the REST request that is used to build up that query? this would be much more portable.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Expression Serializer Extension
Expression Serializer Extension¶. Serializer/Deserializer objects for usage with SQLAlchemy query structures, allowing “contextual” deserialization.
Read more >
Allow to inject expression-based columns into Query objects ...
It fails with AttributeError since query.selectable is read-only. I haven't found another way to inject an expression by reading the docs or the...
Read more >
How to implement dynamic API filtering using query ... - Mindee
When it comes to API filtering, the most intuitive way of doing this is to use query parameters. Query parameters only having a...
Read more >
SQLAlchemy/Postgres: Intermittent Error Serializing Object ...
I think it smells like a race condition, with the update trigger not being complete before SQLAlchemy has tried to get the updated...
Read more >
SQLAlchemy Documentation - Read the Docs
Joining a Session into an External Transaction (such as for test ... SQLAlchemy is not constructing the correct query when I try to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found