From c11d2b8ce060565c939a2e26253fbe51d5266fb7 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Tue, 10 Dec 2024 14:46:46 -0800 Subject: [PATCH] Warn when a FILTER clause has `many` cardinality (#8089) This is kind of a footgun, and we worry it will be more of a footgun with simple_scoping enabled. --- edb/edgeql/compiler/inference/cardinality.py | 13 +++++++++ edb/testbase/connection.py | 16 ++++++----- edb/testbase/server.py | 26 ++++++++++++++++++ tests/schemas/cards.esdl | 8 +++--- tests/test_constraints.py | 4 +-- tests/test_dump01.py | 2 +- tests/test_edgeql_data_migration.py | 5 ++-- tests/test_edgeql_ddl.py | 28 ++++++++++++-------- tests/test_edgeql_delete.py | 2 +- tests/test_edgeql_expr_aliases.py | 6 ++--- tests/test_edgeql_expressions.py | 6 +++-- tests/test_edgeql_filter.py | 9 +++++++ tests/test_edgeql_for.py | 4 +++ tests/test_edgeql_group.py | 2 +- tests/test_edgeql_insert.py | 3 +++ tests/test_edgeql_internal_group.py | 2 ++ tests/test_edgeql_introspection.py | 7 +++-- tests/test_edgeql_json.py | 2 ++ tests/test_edgeql_linkatoms.py | 10 +++++-- tests/test_edgeql_linkprops.py | 9 ++++++- tests/test_edgeql_policies.py | 4 +-- tests/test_edgeql_scope.py | 14 ++++++++++ tests/test_edgeql_select.py | 22 ++++++++++++--- tests/test_edgeql_tree.py | 6 ++--- tests/test_edgeql_triggers.py | 4 +++ tests/test_edgeql_update.py | 7 +++-- tests/test_http_ext_auth.py | 6 +++-- 27 files changed, 176 insertions(+), 51 deletions(-) diff --git a/edb/edgeql/compiler/inference/cardinality.py b/edb/edgeql/compiler/inference/cardinality.py index e0691701674..78e094cf27e 100644 --- a/edb/edgeql/compiler/inference/cardinality.py +++ b/edb/edgeql/compiler/inference/cardinality.py @@ -1219,6 +1219,19 @@ def _infer_stmt_cardinality( ir.where_card = infer_cardinality( ir.where, scope_tree=scope_tree, ctx=ctx, ) + + if ( + ir.where_card.is_multi() + # Don't generate warnings against internally generated code + and ir.where.span + ): + ctx.env.warnings.append(errors.QueryError( + 'possibly more than one element returned by an expression ' + 'in a FILTER clause', + hint='If this is intended, try using any()', + span=ir.where.span, + )) + # Cross with AT_MOST_ONE to ensure result can be empty result_card = cartesian_cardinality([result_card, AT_MOST_ONE]) diff --git a/edb/testbase/connection.py b/edb/testbase/connection.py index c71382949cb..1b54476a452 100644 --- a/edb/testbase/connection.py +++ b/edb/testbase/connection.py @@ -53,10 +53,6 @@ class TransactionState(enum.Enum): FAILED = 4 -def raise_first_warning(warnings, res): - raise warnings[0] - - InputLanguage = protocol.InputLanguage @@ -300,7 +296,7 @@ def _get_state(self) -> options.State: return self._connection._get_state() def _get_warning_handler(self) -> options.WarningHandler: - return raise_first_warning + return self._connection._get_warning_handler() class Retry: @@ -355,6 +351,7 @@ def __init__( self._params = None self._server_hostname = server_hostname self._log_listeners = set() + self._capture_warnings = None def add_log_listener(self, callback): self._log_listeners.add(callback) @@ -365,8 +362,15 @@ def remove_log_listener(self, callback): def _get_state(self): return self._options.state + def _warning_handler(self, warnings, res): + if self._capture_warnings is not None: + self._capture_warnings.extend(warnings) + return res + else: + raise warnings[0] + def _get_warning_handler(self) -> options.WarningHandler: - return raise_first_warning + return self._warning_handler def _on_log_message(self, msg): if self._log_listeners: diff --git a/edb/testbase/server.py b/edb/testbase/server.py index 38a092c0a5f..05452eccad5 100644 --- a/edb/testbase/server.py +++ b/edb/testbase/server.py @@ -963,6 +963,17 @@ def tls_context(self) -> ssl.SSLContext: return tls_context +def ignore_warnings(warning_message=None): + def w(f): + async def wf(self, *args, **kwargs): + with self.ignore_warnings(warning_message): + return await f(self, *args, **kwargs) + + return wf + + return w + + class ConnectedTestCase(ClusterTestCase): BASE_TEST_CLASS = True @@ -983,6 +994,21 @@ def tearDownClass(cls): finally: super().tearDownClass() + @contextlib.contextmanager + def ignore_warnings(self, warning_message=None): + old = self.con._capture_warnings + warnings = [] + self.con._capture_warnings = warnings + try: + yield + finally: + self.con._capture_warnings = old + + if warning_message is not None: + for warning in warnings: + with self.assertRaisesRegex(Exception, warning_message): + raise warning + @classmethod async def setup_and_connect(cls): cls.con = await cls.connect() diff --git a/tests/schemas/cards.esdl b/tests/schemas/cards.esdl index da140791e9e..35ffcd7b787 100644 --- a/tests/schemas/cards.esdl +++ b/tests/schemas/cards.esdl @@ -103,22 +103,22 @@ alias EarthOrFireCard { alias AliceCard := ( SELECT Card - FILTER Card. str; multi link tweets := ( WITH U := User - SELECT Tweet FILTER .author = U + SELECT Tweet FILTER .author IN U ); } type Tweet { @@ -2948,7 +2948,7 @@ async def test_edgeql_migration_computed_03(self): property name -> str; multi link tweets := ( WITH U := DETACHED User - SELECT Tweet FILTER .author = U + SELECT Tweet FILTER .author IN U ); } type Tweet { @@ -3059,6 +3059,7 @@ async def test_edgeql_migration_computed_03(self): }], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_migration_computed_04(self): await self.migrate(r''' type User { diff --git a/tests/test_edgeql_ddl.py b/tests/test_edgeql_ddl.py index 9773815aa28..2962bd51042 100644 --- a/tests/test_edgeql_ddl.py +++ b/tests/test_edgeql_ddl.py @@ -749,7 +749,7 @@ async def test_edgeql_ddl_19(self): r""" SELECT schema::Link { pnames := .properties.name - } FILTER .name = {"connected", '__type__'} + } FILTER .name IN {"connected", '__type__'} AND .source.name = 'default::Alias2' """, [ @@ -6149,8 +6149,10 @@ async def test_edgeql_ddl_operator_01(self): } FILTER .name = 'default::+++' - AND .annotations.name = 'std::description' - AND .annotations@value = 'my plus'; + AND any( + .annotations.name = 'std::description' + AND .annotations@value = 'my plus' + ); ''', [{ 'name': 'default::+++', @@ -12022,9 +12024,10 @@ async def test_edgeql_ddl_drop_01(self): r""" WITH MODULE schema SELECT Constraint {name} - FILTER + FILTER any( .annotations.name = 'std::description' - AND .annotations@value = 'test_delta_drop_01_constraint'; + AND .annotations@value = 'test_delta_drop_01_constraint' + ) """, [ { @@ -12041,9 +12044,10 @@ async def test_edgeql_ddl_drop_01(self): r""" WITH MODULE schema SELECT Constraint {name} - FILTER + FILTER any( .annotations.name = 'std::description' - AND .annotations@value = 'test_delta_drop_01_constraint'; + AND .annotations@value = 'test_delta_drop_01_constraint' + ) """, [] ) @@ -12063,9 +12067,10 @@ async def test_edgeql_ddl_drop_02(self): r""" WITH MODULE schema SELECT Property {name} - FILTER + FILTER any( .annotations.name = 'std::description' - AND .annotations@value = 'test_delta_drop_02_link'; + AND .annotations@value = 'test_delta_drop_02_link' + ) """, [ { @@ -12082,9 +12087,10 @@ async def test_edgeql_ddl_drop_02(self): r""" WITH MODULE schema SELECT Property {name} - FILTER + FILTER any( .annotations.name = 'std::description' - AND .annotations@value = 'test_delta_drop_02_link'; + AND .annotations@value = 'test_delta_drop_02_link' + ) """, [] ) diff --git a/tests/test_edgeql_delete.py b/tests/test_edgeql_delete.py index 9afecc0c0ac..8445ad6bc75 100644 --- a/tests/test_edgeql_delete.py +++ b/tests/test_edgeql_delete.py @@ -269,7 +269,7 @@ async def test_edgeql_delete_returning_03(self): SELECT DeleteTest2 { name, foo := 'bar' - } FILTER DeleteTest2.name LIKE D.name[:2] ++ '%'; + } FILTER any(DeleteTest2.name LIKE D.name[:2] ++ '%'); """, [{ 'name': 'dt2.1', diff --git a/tests/test_edgeql_expr_aliases.py b/tests/test_edgeql_expr_aliases.py index 3ec4ddddaf9..90309ddbe13 100644 --- a/tests/test_edgeql_expr_aliases.py +++ b/tests/test_edgeql_expr_aliases.py @@ -250,7 +250,7 @@ async def test_edgeql_aliases_filter_01(self): await self.assert_query_result( r''' SELECT FireCard {name} - FILTER FireCard = DaveCard + FILTER FireCard IN DaveCard ORDER BY FireCard.name; ''', [{'name': 'Dragon'}], @@ -882,7 +882,7 @@ async def test_edgeql_aliases_esdl_01(self): name, owned_by_alice, } - FILTER .name ILIKE {'%turtle%', 'dwarf'} + FILTER any(.name ILIKE {'%turtle%', 'dwarf'}) ORDER BY .name; """, [ @@ -902,7 +902,7 @@ async def test_edgeql_aliases_esdl_01(self): SELECT EarthOrFireCard { name, } - FILTER .name = {'Imp', 'Dwarf'} + FILTER .name IN {'Imp', 'Dwarf'} ORDER BY .name; """, [ diff --git a/tests/test_edgeql_expressions.py b/tests/test_edgeql_expressions.py index 7870c04f241..63d5ffeb27a 100644 --- a/tests/test_edgeql_expressions.py +++ b/tests/test_edgeql_expressions.py @@ -8832,6 +8832,7 @@ async def test_edgeql_expr_aggregate_01(self): [5], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_expr_alias_01(self): await self.assert_query_result( r""" @@ -8844,6 +8845,7 @@ async def test_edgeql_expr_alias_01(self): [2], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_expr_alias_02(self): await self.assert_query_result( r""" @@ -9566,9 +9568,9 @@ async def test_edgeql_assert_distinct_01(self): await self.assert_query_result( """ SELECT assert_distinct(( - (SELECT Issue FILTER .references[IS File].name = "File 1") + (SELECT Issue FILTER "File 1" IN .references[IS File].name) UNION - (SELECT Issue FILTER .references[IS File].name = "File 2") + (SELECT Issue FILTER "File 2" IN .references[IS File].name) )) { number } diff --git a/tests/test_edgeql_filter.py b/tests/test_edgeql_filter.py index ffdf30a1c1d..3a55e932877 100644 --- a/tests/test_edgeql_filter.py +++ b/tests/test_edgeql_filter.py @@ -32,6 +32,7 @@ class TestEdgeQLFilter(tb.QueryTestCase): SETUP = os.path.join(os.path.dirname(__file__), 'schemas', 'issues_filter_setup.edgeql') + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_two_scalar_conditions01(self): await self.assert_query_result( r''' @@ -105,6 +106,7 @@ async def test_edgeql_filter_two_scalar_conditions03(self): [{'name': 'Yury'}], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_two_scalar_conditions04(self): await self.assert_query_result( r''' @@ -159,6 +161,7 @@ async def test_edgeql_filter_not_exists02(self): [{'name': 'Elvis'}, {'name': 'Yury'}], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_not_exists03(self): await self.assert_query_result( r''' @@ -177,6 +180,7 @@ async def test_edgeql_filter_not_exists03(self): [{'name': 'Elvis'}, {'name': 'Yury'}], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_not_exists04(self): await self.assert_query_result( r''' @@ -245,6 +249,7 @@ async def test_edgeql_filter_two_scalar_exists02(self): [{'name': 'Yury'}], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_two_scalar_exists03(self): await self.assert_query_result( r''' @@ -321,6 +326,7 @@ async def test_edgeql_filter_short_form02(self): [{}], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_flow01(self): await self.assert_query_result( r''' @@ -341,6 +347,7 @@ async def test_edgeql_filter_flow01(self): ['1', '2', '3', '4'], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_flow02(self): await self.assert_query_result( r''' @@ -361,6 +368,7 @@ async def test_edgeql_filter_flow02(self): [], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_flow03(self): await self.assert_query_result( r''' @@ -448,6 +456,7 @@ async def test_edgeql_filter_aggregate01(self): [4], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_filter_aggregate04(self): await self.assert_query_result( r''' diff --git a/tests/test_edgeql_for.py b/tests/test_edgeql_for.py index 6f105d776e8..dc4ff3c022a 100644 --- a/tests/test_edgeql_for.py +++ b/tests/test_edgeql_for.py @@ -212,6 +212,7 @@ async def test_edgeql_for_implicit_limit_01(self): implicit_limit=100, ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_for_filter_02(self): await self.assert_query_result( r''' @@ -235,6 +236,7 @@ async def test_edgeql_for_filter_02(self): } ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_for_filter_03(self): await self.assert_query_result( r''' @@ -1076,6 +1078,8 @@ async def test_edgeql_for_fake_group_01b(self): [{"key": {"element": "Earth"}}, {"key": {"element": "Water"}}] ) + # XXX: This is *wrong*, I think + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_for_fake_group_01c(self): await self.assert_query_result( r''' diff --git a/tests/test_edgeql_group.py b/tests/test_edgeql_group.py index 90bbd714536..bfb42bf4b52 100644 --- a/tests/test_edgeql_group.py +++ b/tests/test_edgeql_group.py @@ -1204,7 +1204,7 @@ async def test_edgeql_group_policies_01(self): with module cards insert User { name := 'Sully', - deck := (select Card filter .element = {'Water', 'Air'}) + deck := (select Card filter .element IN {'Water', 'Air'}) }; ''') diff --git a/tests/test_edgeql_insert.py b/tests/test_edgeql_insert.py index 24083714e4c..e3da3907084 100644 --- a/tests/test_edgeql_insert.py +++ b/tests/test_edgeql_insert.py @@ -1350,6 +1350,7 @@ async def test_edgeql_insert_for_01(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_insert_for_02(self): await self.con.execute(r''' # create 10 DefaultTest3 objects, each object is defined @@ -1822,6 +1823,7 @@ async def test_edgeql_insert_for_bad_04(self): INSERT Note {name := y ++ x.name})))))); """) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_insert_default_01(self): await self.con.execute(r''' # create 10 DefaultTest3 objects, each object is defined @@ -2315,6 +2317,7 @@ async def test_edgeql_insert_polymorphic_01(self): }], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_insert_linkprops_with_for_01(self): await self.con.execute(r""" FOR i IN {'1', '2', '3'} UNION ( diff --git a/tests/test_edgeql_internal_group.py b/tests/test_edgeql_internal_group.py index 42535926152..11a96e40f57 100644 --- a/tests/test_edgeql_internal_group.py +++ b/tests/test_edgeql_internal_group.py @@ -405,6 +405,7 @@ async def test_edgeql_igroup_returning_03(self): ], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_igroup_returning_04(self): await self.assert_query_result( r''' @@ -520,6 +521,7 @@ async def test_edgeql_igroup_returning_06b(self): ], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_igroup_returning_07(self): await self.assert_query_result( r''' diff --git a/tests/test_edgeql_introspection.py b/tests/test_edgeql_introspection.py index 17b2862cf6b..3a4a674a7f9 100644 --- a/tests/test_edgeql_introspection.py +++ b/tests/test_edgeql_introspection.py @@ -170,6 +170,8 @@ async def test_edgeql_introspection_objtype_04(self): }] ) + # XXX: This warning is wrong + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_introspection_objtype_05(self): await self.assert_query_result( r""" @@ -262,7 +264,7 @@ async def test_edgeql_introspection_objtype_07(self): FILTER ObjectType.name LIKE 'default::%' AND - ObjectType.links.cardinality = 'Many' + 'Many' IN ObjectType.links.cardinality ORDER BY ObjectType.name; """, [ @@ -290,7 +292,7 @@ async def test_edgeql_introspection_objtype_08(self): FILTER `ObjectType`.name LIKE 'default::%' AND - ObjectType.links.cardinality = 'Many' + 'Many' IN ObjectType.links.cardinality ORDER BY `ObjectType`.name; """, [ @@ -854,6 +856,7 @@ async def test_edgeql_introspection_volatility_01(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_introspection_volatility_02(self): await self.assert_query_result( r""" diff --git a/tests/test_edgeql_json.py b/tests/test_edgeql_json.py index 880f5bf2e9d..9deddd78631 100644 --- a/tests/test_edgeql_json.py +++ b/tests/test_edgeql_json.py @@ -1295,6 +1295,7 @@ async def test_edgeql_json_cast_object_to_json_02(self): }] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_json_cast_object_to_json_03(self): # Test that object-to-json cast works in tuples as well. await self.assert_query_result( @@ -1321,6 +1322,7 @@ async def test_edgeql_json_cast_object_to_json_03(self): [True], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_json_cast_object_to_json_04(self): # Test that object-to-json cast works in arrays as well. await self.assert_query_result( diff --git a/tests/test_edgeql_linkatoms.py b/tests/test_edgeql_linkatoms.py index f4e023ea852..d0e726c7cdf 100644 --- a/tests/test_edgeql_linkatoms.py +++ b/tests/test_edgeql_linkatoms.py @@ -228,7 +228,7 @@ async def test_edgeql_links_set_01(self): await self.assert_query_result( r''' SELECT Item {name} - FILTER 'plastic' = .tag_set1 + FILTER 'plastic' IN .tag_set1 ORDER BY .name; ''', [ @@ -240,7 +240,7 @@ async def test_edgeql_links_set_01(self): await self.assert_query_result( r''' SELECT Item {name} - FILTER 'plastic' = .tag_set2 + FILTER 'plastic' IN .tag_set2 ORDER BY .name; ''', [ @@ -304,6 +304,7 @@ async def test_edgeql_links_set_03(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_set_04(self): await self.assert_query_result( r''' @@ -329,6 +330,7 @@ async def test_edgeql_links_set_04(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_set_05(self): await self.assert_query_result( r''' @@ -356,6 +358,7 @@ async def test_edgeql_links_set_05(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_set_06(self): await self.assert_query_result( r''' @@ -645,6 +648,7 @@ async def test_edgeql_links_set_14(self): ], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_set_15(self): await self.assert_query_result( r''' @@ -754,6 +758,7 @@ async def test_edgeql_links_array_03(self): ], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_array_04(self): await self.assert_query_result( r''' @@ -904,6 +909,7 @@ async def test_edgeql_links_array_10(self): ], ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_links_array_11(self): await self.assert_query_result( r''' diff --git a/tests/test_edgeql_linkprops.py b/tests/test_edgeql_linkprops.py index eae5c8d8a7f..91722823795 100644 --- a/tests/test_edgeql_linkprops.py +++ b/tests/test_edgeql_linkprops.py @@ -259,6 +259,7 @@ async def test_edgeql_props_basic_02(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_props_basic_03(self): await self.assert_query_result( r''' @@ -347,7 +348,7 @@ async def test_edgeql_props_basic_04(self): cost } FILTER - .cost = . '1'; ''') + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_union_target_01(self): await self.assert_query_result( r''' diff --git a/tests/test_edgeql_tree.py b/tests/test_edgeql_tree.py index db0097d8ca9..71e4ed460ff 100644 --- a/tests/test_edgeql_tree.py +++ b/tests/test_edgeql_tree.py @@ -373,7 +373,7 @@ async def test_edgeql_tree_select_09(self): r""" SELECT Tree {val} FILTER - .children.children.val = '000' + any(.children.children.val = '000') ORDER BY .val; """, [{'val': '0'}], @@ -384,7 +384,7 @@ async def test_edgeql_tree_select_10(self): r""" SELECT Eert {val} FILTER - .children.children.val = '000' + any(.children.children.val = '000') ORDER BY .val; """, [{'val': '0'}], @@ -1082,7 +1082,7 @@ async def test_edgeql_tree_update_10(self): await self.assert_query_result( r""" select ( - update Tree filter .val = {"0", "00"} + update Tree filter .val IN {"0", "00"} set { parent := {} } ) { val, children: {val} order by .val diff --git a/tests/test_edgeql_triggers.py b/tests/test_edgeql_triggers.py index b8f98e3a322..7104b0aeb9d 100644 --- a/tests/test_edgeql_triggers.py +++ b/tests/test_edgeql_triggers.py @@ -279,6 +279,7 @@ async def test_edgeql_triggers_mixed_02(self): # MULTI! + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_triggers_multi_insert_01(self): await self.con.execute(''' alter type InsertTest { @@ -297,6 +298,7 @@ async def test_edgeql_triggers_multi_insert_01(self): {'name': "insert", 'notes': set("abcdef")}, ]) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_triggers_multi_mixed_01(self): # Install triggers for everything await self.con.execute(''' @@ -333,6 +335,7 @@ async def test_edgeql_triggers_multi_mixed_01(self): {'name': "update", 'notes': set(f'{x} -> {x}!' for x in "abcdef")}, ]) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_triggers_multi_mixed_02(self): # Install double and triple triggers await self.con.execute(''' @@ -1283,6 +1286,7 @@ async def test_edgeql_triggers_when_01(self): tb.bag(['a!', 'b', 'b!', 'c', 'c!', 'd', 'd!', 'e', 'e!', 'f']), ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_triggers_when_02(self): await self.con.execute(''' alter type InsertTest { diff --git a/tests/test_edgeql_update.py b/tests/test_edgeql_update.py index f19640c59cb..5218a1df56c 100644 --- a/tests/test_edgeql_update.py +++ b/tests/test_edgeql_update.py @@ -550,6 +550,7 @@ async def test_edgeql_update_bad_02(self): UPDATE schema::Migration SET { script := 'foo'}; ''') + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_update_filter_01(self): await self.assert_query_result( r""" @@ -571,6 +572,7 @@ async def test_edgeql_update_filter_01(self): ['bad test'] * 3, ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_update_filter_02(self): await self.assert_query_result( r""" @@ -875,6 +877,7 @@ async def test_edgeql_update_multiple_07(self): ] ) + @tb.ignore_warnings('more than one.* in a FILTER clause') async def test_edgeql_update_multiple_08(self): await self.con.execute(""" INSERT UpdateTest { @@ -3476,7 +3479,7 @@ async def test_edgeql_update_covariant_03(self): UPDATE UpdateTestSubType FILTER .name = "update-covariant" SET { - statuses := (SELECT Status FILTER .name = { + statuses := (SELECT Status FILTER .name IN { "Broke a Type System", "Downloaded a Car", }) @@ -3492,7 +3495,7 @@ async def test_edgeql_update_covariant_03(self): UPDATE UpdateTestSubType FILTER .name = "update-covariant" SET { - statuses := (SELECT Status FILTER .name = { + statuses := (SELECT Status FILTER .name IN { "Broke a Type System", "Downloaded a Car", "Open", diff --git a/tests/test_http_ext_auth.py b/tests/test_http_ext_auth.py index 934f17a18b3..302b10f7f49 100644 --- a/tests/test_http_ext_auth.py +++ b/tests/test_http_ext_auth.py @@ -4345,8 +4345,10 @@ async def test_http_auth_ext_webauthn_authenticate_options(self): SELECT EXISTS ( SELECT ext::auth::WebAuthnAuthenticationChallenge filter .challenge = $challenge - AND .factors.email = $email - AND .factors.user_handle = $user_handle + AND any( + .factors.email = $email + AND .factors.user_handle = $user_handle + ) ) ''', challenge=challenge_bytes,