From 868a884b799f10827d84e0e5c334d8252acd310b Mon Sep 17 00:00:00 2001 From: Nadav Har'El Date: Thu, 22 Sep 2022 14:32:42 +0300 Subject: [PATCH] test/cql-pytest: add reproducer for ignored IS NOT NULL This test reproduces issue #10365: It shows that although "IS NOT NULL" is not allowed in regular SELECT filters, in a materialized view it is allowed, even for non-key columns - but then outright ignored and does not actually filter out anything - a fact which already surprised several users. The test also fails on Cassandra - it also wrongly allows IS NOT NULL on the non-key columns but then ignores this in the filter. So the test is marked with both xfail (known to fail on Scylla) and cassandra_bug (fails on Cassandra because of what we consider to be a Cassandra bug). Refs #10365 Refs #11606 Signed-off-by: Nadav Har'El Closes #11615 --- test/cql-pytest/test_materialized_view.py | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/cql-pytest/test_materialized_view.py b/test/cql-pytest/test_materialized_view.py index c7cc9dfcdec4..270ad3ba9e40 100644 --- a/test/cql-pytest/test_materialized_view.py +++ b/test/cql-pytest/test_materialized_view.py @@ -227,6 +227,47 @@ def test_is_not_operator_must_be_null(cql, test_keyspace): finally: cql.execute(f"DROP MATERIALIZED VIEW IF EXISTS {test_keyspace}.{mv}") +# The IS NOT NULL operator was first added to Cassandra and Scylla for use +# just in key columns in materialized views. It was not supported in general +# filters in SELECT (see issue #8517), and in particular cannot be used in +# a materialized-view definition as a filter on non-key columns. However, +# if this usage is not allowed, we expect to see a clear error and not silently +# ignoring the IS NOT NULL condition as happens in issue #10365. +# +# NOTE: if issue #8517 (IS NOT NULL in filters) is implemented, we will need to +# replace this test by a test that checks that the filter works as expected, +# both in ordinary base-table SELECT and in materialized-view definition. +@pytest.mark.xfail(reason="issue #10365") +def test_is_not_null_forbidden_in_filter(cql, test_keyspace, cassandra_bug): + with new_test_table(cql, test_keyspace, 'p int primary key, xyz int') as table: + # Check that "IS NOT NULL" is not supported in a regular (base table) + # SELECT filter. Cassandra reports an InvalidRequest: "Unsupported + # restriction: xyz IS NOT NULL". In Scylla the message is different: + # "restriction '(xyz) IS NOT { null }' is only supported in materialized + # view creation". + # + with pytest.raises(InvalidRequest, match="xyz"): + cql.execute(f'SELECT * FROM {table} WHERE xyz IS NOT NULL ALLOW FILTERING') + # Check that "xyz IS NOT NULL" is also not supported in a + # materialized-view definition (where xyz is not a key column) + # Reproduces #8517 + mv = unique_name() + try: + with pytest.raises(InvalidRequest, match="xyz"): + cql.execute(f"CREATE MATERIALIZED VIEW {test_keyspace}.{mv} AS SELECT * FROM {table} WHERE p IS NOT NULL AND xyz IS NOT NULL PRIMARY KEY (p)") + # There is no need to continue the test - if the CREATE + # MATERIALIZED VIEW above succeeded, it is already not what we + # expect without #8517. However, let's demonstrate that it's + # even worse - not only does the "xyz IS NOT NULL" not generate + # an error, it is outright ignored and not used in the filter. + # If it weren't ignored, it should filter out partition 124 + # in the following example: + cql.execute(f"INSERT INTO {table} (p,xyz) VALUES (123, 456)") + cql.execute(f"INSERT INTO {table} (p) VALUES (124)") + assert sorted(list(cql.execute(f"SELECT p FROM {test_keyspace}.{mv}")))==[(123,)] + finally: + cql.execute(f"DROP MATERIALIZED VIEW IF EXISTS {test_keyspace}.{mv}") + # Test that a view can be altered with synchronous_updates property and that # the synchronous updates code path is then reached for such view. def test_mv_synchronous_updates(cql, test_keyspace):