--- /dev/null
+.. change::
+ :tags: bug, postgresql
+ :tickets: 6515
+
+ Fixed bug in :class:`.ARRAY` datatype in combination with :class:`.Enum` on
+ PostgreSQL where using the ``.any()`` method to render SQL ANY(), given
+ members of the Python enumeration as arguments, would produce a type
+ adaptation failure on all drivers.
__slots__ = ()
+ type: ARRAY
+
def _setup_getitem(self, index):
- arr_type = cast(ARRAY, self.type)
+ arr_type = self.type
return_type: TypeEngine[Any]
elements = util.preloaded.sql_elements
operator = operator if operator else operators.eq
+ arr_type = self.type
+
# send plain BinaryExpression so that negate remains at None,
# leading to NOT expr for negation.
return elements.BinaryExpression(
- coercions.expect(roles.ExpressionElementRole, other),
+ coercions.expect(
+ roles.BinaryElementRole,
+ element=other,
+ operator=operator,
+ expr=self.expr,
+ bindparam_type=arr_type.item_type,
+ ),
elements.CollectionAggregate._create_any(self.expr),
operator,
)
elements = util.preloaded.sql_elements
operator = operator if operator else operators.eq
+ arr_type = self.type
+
# send plain BinaryExpression so that negate remains at None,
# leading to NOT expr for negation.
return elements.BinaryExpression(
- coercions.expect(roles.ExpressionElementRole, other),
+ coercions.expect(
+ roles.BinaryElementRole,
+ element=other,
+ operator=operator,
+ expr=self.expr,
+ bindparam_type=arr_type.item_type,
+ ),
elements.CollectionAggregate._create_all(self.expr),
operator,
)
)
self.assert_compile(
postgresql.Any(4, c),
- "%(param_1)s = ANY (x)",
- checkparams={"param_1": 4},
+ "%(x_1)s = ANY (x)",
+ checkparams={"x_1": 4},
)
self.assert_compile(
c.any(5),
- "%(param_1)s = ANY (x)",
- checkparams={"param_1": 5},
+ "%(x_1)s = ANY (x)",
+ checkparams={"x_1": 5},
)
self.assert_compile(
~c.any(5),
- "NOT (%(param_1)s = ANY (x))",
- checkparams={"param_1": 5},
+ "NOT (%(x_1)s = ANY (x))",
+ checkparams={"x_1": 5},
)
self.assert_compile(
c.all(5),
- "%(param_1)s = ALL (x)",
- checkparams={"param_1": 5},
+ "%(x_1)s = ALL (x)",
+ checkparams={"x_1": 5},
)
self.assert_compile(
~c.all(5),
- "NOT (%(param_1)s = ALL (x))",
- checkparams={"param_1": 5},
+ "NOT (%(x_1)s = ALL (x))",
+ checkparams={"x_1": 5},
)
self.assert_compile(
c.any(5, operator=operators.ne),
- "%(param_1)s != ANY (x)",
- checkparams={"param_1": 5},
+ "%(x_1)s != ANY (x)",
+ checkparams={"x_1": 5},
)
self.assert_compile(
postgresql.All(6, c, operator=operators.gt),
- "%(param_1)s > ALL (x)",
- checkparams={"param_1": 6},
+ "%(x_1)s > ALL (x)",
+ checkparams={"x_1": 6},
)
self.assert_compile(
c.all(7, operator=operators.lt),
- "%(param_1)s < ALL (x)",
- checkparams={"param_1": 7},
+ "%(x_1)s < ALL (x)",
+ checkparams={"x_1": 7},
)
@testing.combinations(
col = column("x", postgresql.ARRAY(Integer))
self.assert_compile(
select(col.any(7, operator=operators.lt)),
- "SELECT %(param_1)s < ANY (x) AS anon_1",
- checkparams={"param_1": 7},
+ "SELECT %(x_1)s < ANY (x) AS anon_1",
+ checkparams={"x_1": 7},
)
def test_array_all(self):
col = column("x", postgresql.ARRAY(Integer))
self.assert_compile(
select(col.all(7, operator=operators.lt)),
- "SELECT %(param_1)s < ALL (x) AS anon_1",
- checkparams={"param_1": 7},
+ "SELECT %(x_1)s < ALL (x) AS anon_1",
+ checkparams={"x_1": 7},
)
def test_array_contains(self):
metadata.create_all(connection)
connection.execute(
tbl.insert(),
- [{"enum_col": ["foo"]}, {"enum_col": ["foo", "bar"]}],
+ [
+ {"enum_col": ["foo"], "pyenum_col": [MyEnum.a, MyEnum.b]},
+ {"enum_col": ["foo", "bar"], "pyenum_col": [MyEnum.b]},
+ ],
)
return tbl, MyEnum
)(fn)
)
+ @_enum_combinations
+ @testing.combinations("all", "any", argnames="fn")
+ def test_any_all_roundtrip(
+ self, array_of_enum_fixture, connection, array_cls, enum_cls, fn
+ ):
+ """test #6515"""
+
+ tbl, MyEnum = array_of_enum_fixture(array_cls, enum_cls)
+
+ if fn == "all":
+ expr = tbl.c.pyenum_col.all(MyEnum.b)
+ result = [([MyEnum.b],)]
+ elif fn == "any":
+ expr = tbl.c.pyenum_col.any(MyEnum.b)
+ result = [([MyEnum.a, MyEnum.b],), ([MyEnum.b],)]
+ else:
+ assert False
+ sel = select(tbl.c.pyenum_col).where(expr).order_by(tbl.c.id)
+ eq_(connection.execute(sel).fetchall(), result)
+
@_enum_combinations
def test_array_of_enums_roundtrip(
self, array_of_enum_fixture, connection, array_cls, enum_cls
self.assert_compile(
t.c.arrval.any(5, operator.gt),
- ":param_1 > ANY (tab1.arrval)",
- checkparams={"param_1": 5},
+ ":arrval_1 > ANY (tab1.arrval)",
+ checkparams={"arrval_1": 5},
)
def test_any_array_comparator_negate_accessor(self, t_fixture):
self.assert_compile(
~t.c.arrval.any(5, operator.gt),
- "NOT (:param_1 > ANY (tab1.arrval))",
- checkparams={"param_1": 5},
+ "NOT (:arrval_1 > ANY (tab1.arrval))",
+ checkparams={"arrval_1": 5},
)
def test_all_array_comparator_accessor(self, t_fixture):
self.assert_compile(
t.c.arrval.all(5, operator.gt),
- ":param_1 > ALL (tab1.arrval)",
- checkparams={"param_1": 5},
+ ":arrval_1 > ALL (tab1.arrval)",
+ checkparams={"arrval_1": 5},
)
def test_all_array_comparator_negate_accessor(self, t_fixture):
self.assert_compile(
~t.c.arrval.all(5, operator.gt),
- "NOT (:param_1 > ALL (tab1.arrval))",
- checkparams={"param_1": 5},
+ "NOT (:arrval_1 > ALL (tab1.arrval))",
+ checkparams={"arrval_1": 5},
)
def test_any_array_expression(self, t_fixture):