diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-01 12:26:06 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-04-01 13:22:26 -0400 |
| commit | ab01f893f8c489e2fe981699e022c76e0318ec77 (patch) | |
| tree | 2f6189dc7d041f6f9289ac234517434d279d3acd /lib/sqlalchemy/sql | |
| parent | 3a29d65f73c6e705f486588068172d45017285fa (diff) | |
| download | sqlalchemy-ab01f893f8c489e2fe981699e022c76e0318ec77.tar.gz | |
Correct for Variant + ARRAY cases in psycopg2
Fixed regression caused by :ticket:`6023` where the PostgreSQL cast
operator applied to elements within an :class:`_types.ARRAY` when using
psycopg2 would fail to use the correct type in the case that the datatype
were also embedded within an instance of the :class:`_types.Variant`
adapter.
Additionally, repairs support for the correct CREATE TYPE to be emitted
when using a ``Variant(ARRAY(some_schema_type))``.
Fixes: #6182
Change-Id: I1b9ba7c876980d4650715a0b0801b46bdc72860d
Diffstat (limited to 'lib/sqlalchemy/sql')
| -rw-r--r-- | lib/sqlalchemy/sql/sqltypes.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/type_api.py | 5 |
2 files changed, 17 insertions, 8 deletions
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 367b2e203..7cc50d99c 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1221,13 +1221,19 @@ class SchemaType(SchemaEventTarget): if variant_mapping is None: return True - if ( - dialect.name in variant_mapping - and variant_mapping[dialect.name] is self + # since PostgreSQL is the only DB that has ARRAY this can only + # be integration tested by PG-specific tests + def _we_are_the_impl(typ): + return ( + typ is self or isinstance(typ, ARRAY) and typ.item_type is self + ) + + if dialect.name in variant_mapping and _we_are_the_impl( + variant_mapping[dialect.name] ): return True elif dialect.name not in variant_mapping: - return variant_mapping["_default"] is self + return _we_are_the_impl(variant_mapping["_default"]) class Enum(Emulated, String, SchemaType): @@ -2857,16 +2863,16 @@ class ARRAY(SchemaEventTarget, Indexable, Concatenable, TypeEngine): def compare_values(self, x, y): return x == y - def _set_parent(self, column, **kw): + def _set_parent(self, column, outer=False, **kw): """Support SchemaEventTarget""" - if isinstance(self.item_type, SchemaEventTarget): + if not outer and isinstance(self.item_type, SchemaEventTarget): self.item_type._set_parent(column, **kw) def _set_parent_with_dispatch(self, parent): """Support SchemaEventTarget""" - super(ARRAY, self)._set_parent_with_dispatch(parent) + super(ARRAY, self)._set_parent_with_dispatch(parent, outer=True) if isinstance(self.item_type, SchemaEventTarget): self.item_type._set_parent_with_dispatch(parent) diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index bfce00cb5..69cd3c5ca 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -48,6 +48,7 @@ class TypeEngine(Traversible): _is_tuple_type = False _is_table_value = False _is_array = False + _is_type_decorator = False class Comparator(operators.ColumnOperators): """Base class for custom comparison operations defined at the @@ -955,6 +956,8 @@ class TypeDecorator(SchemaEventTarget, TypeEngine): __visit_name__ = "type_decorator" + _is_type_decorator = True + def __init__(self, *args, **kwargs): """Construct a :class:`.TypeDecorator`. @@ -1497,7 +1500,7 @@ class Variant(TypeDecorator): else: return self.impl - def _set_parent(self, column, **kw): + def _set_parent(self, column, outer=False, **kw): """Support SchemaEventTarget""" if isinstance(self.impl, SchemaEventTarget): |
