--- /dev/null
+.. change::
+ :tags: bug, sql
+ :tickets: 10213
+ :versions: 2.0.20
+
+ Fixed issue where unpickling of a :class:`_schema.Column` or other
+ :class:`_sql.ColumnElement` would fail to restore the correct "comparator"
+ object, which is used to generate SQL expressions specific to the type
+ object.
else:
return comparator_factory(self)
+ def __setstate__(self, state):
+ self.__dict__.update(state)
+
def __getattr__(self, key: str) -> Any:
try:
return getattr(self.comparator, key)
return op, self.type
- def __reduce__(self) -> Any:
- return _reconstitute_comparator, (self.expr,)
-
hashable = True
"""Flag, if False, means values from this type aren't hashable.
)
-def _reconstitute_comparator(expression: Any) -> Any:
- return expression.comparator
-
-
@overload
def to_instance(typeobj: Union[Type[_TE], _TE], *arg: Any, **kw: Any) -> _TE:
...
from sqlalchemy.types import Indexable
from sqlalchemy.types import JSON
from sqlalchemy.types import MatchType
+from sqlalchemy.types import NullType
from sqlalchemy.types import TypeDecorator
from sqlalchemy.types import TypeEngine
from sqlalchemy.types import UserDefinedType
clause = tuple_(1, 2, 3)
eq_(str(clause), str(pickle.loads(pickle.dumps(clause))))
+ @testing.combinations(Integer(), String(), JSON(), argnames="typ")
+ @testing.variation("eval_first", [True, False])
+ def test_pickle_comparator(self, typ, eval_first):
+ """test #10213"""
+
+ table1 = Table("t", MetaData(), Column("x", typ))
+ t1 = table1.c.x
+
+ if eval_first:
+ t1.comparator
+
+ t1p = pickle.loads(pickle.dumps(table1.c.x))
+
+ is_not(t1p.comparator.__class__, NullType.Comparator)
+ is_(t1.comparator.__class__, t1p.comparator.__class__)
+
@testing.combinations(
(operator.lt, "<", ">"),
(operator.gt, ">", "<"),