mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
test: add UDF/UDA keyspace isolation and UDT tests
Port 3 tests from scylla-dtest user_functions_test.py: - test_udf_with_udt: UDF taking frozen UDT arg, verifies DROP TYPE blocked - test_udf_with_udt_keyspace_isolation: cross-keyspace UDT references rejected - test_aggregate_with_udt_keyspace_isolation: cross-keyspace UDT in UDA rejected All tests use Lua (Scylla's supported UDF language). Reproduces CASSANDRA-9409. Closes scylladb/scylladb#1928 Closes scylladb/scylladb#29843
This commit is contained in:
committed by
Nadav Har'El
parent
f55a55fbf3
commit
c359a09189
@@ -9,7 +9,7 @@
|
||||
|
||||
import pytest
|
||||
from cassandra.protocol import InvalidRequest, ConfigurationException
|
||||
from .util import unique_name, new_test_table, new_function, new_aggregate, new_type
|
||||
from .util import unique_name, new_test_keyspace, new_test_table, new_function, new_aggregate, new_type
|
||||
|
||||
# Test that computing an average by hand works the same as
|
||||
# the built-in function
|
||||
@@ -266,3 +266,18 @@ def test_replace_sfunc_ffunc(cql, test_keyspace, cassandra_bug):
|
||||
cql.execute(f"CREATE OR REPLACE FUNCTION {test_keyspace}.{sum_final} {sum_final_body2}")
|
||||
result = cql.execute(f"SELECT {custom_sum}(id) AS result FROM {table}").one()
|
||||
assert result.result == 36
|
||||
|
||||
# Test that an aggregate cannot reference a UDT from another keyspace.
|
||||
# Ported from scylla-dtest user_functions_test.py::test_aggregate_with_udt_keyspace_isolation (SCYLLADB-1928).
|
||||
# Reproduces CASSANDRA-9409.
|
||||
def test_aggregate_with_udt_keyspace_isolation(cql, test_keyspace):
|
||||
with new_type(cql, test_keyspace, "(a int)") as udt:
|
||||
_, udt_name = udt.split('.')
|
||||
with new_test_keyspace(cql, "WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor': 1}") as other_ks:
|
||||
# The SFUNC 'plus' doesn't need to exist — the cross-keyspace
|
||||
# UDT reference error fires during type validation, before
|
||||
# function lookup.
|
||||
with pytest.raises(InvalidRequest, match="cannot refer to a user type in keyspace"):
|
||||
cql.execute(
|
||||
f"CREATE AGGREGATE {other_ks}.suma ({test_keyspace}.{udt_name}) "
|
||||
f"SFUNC plus STYPE int INITCOND 10")
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
#############################################################################
|
||||
|
||||
import pytest
|
||||
from .util import unique_name, new_function
|
||||
from cassandra.protocol import InvalidRequest
|
||||
|
||||
from .util import new_test_keyspace, new_test_table, new_type, unique_name, new_function
|
||||
|
||||
# Unfortunately, while ScyllaDB and Cassandra support the same UDF
|
||||
# feature, each supports a different choice of languages. In particular,
|
||||
# Cassandra supports Java and ScyllaDB doesn't - but ScyllaDB supports
|
||||
@@ -65,3 +66,52 @@ def test_drop_overloaded_udf(cql, test_keyspace, has_java_udf):
|
||||
# So let's recreate them to pacify new_function():
|
||||
cql.execute(f"CREATE FUNCTION {test_keyspace}.{fun} {body1}")
|
||||
cql.execute(f"CREATE FUNCTION {test_keyspace}.{fun} {body2}")
|
||||
|
||||
# Test that a UDF can take a frozen UDT argument and that the UDT cannot
|
||||
# be dropped while the function is in use.
|
||||
# Ported from scylla-dtest user_functions_test.py::test_udf_with_udt (SCYLLADB-1928).
|
||||
def test_udf_with_udt(cql, test_keyspace, has_java_udf):
|
||||
with new_type(cql, test_keyspace, "(a text, b int)") as udt:
|
||||
_, udt_name = udt.split('.')
|
||||
with new_test_table(cql, test_keyspace,
|
||||
f"key int PRIMARY KEY, udt frozen<{udt_name}>") as table:
|
||||
cql.execute(f"INSERT INTO {table} (key, udt) VALUES (1, {{a: 'un', b: 1}})")
|
||||
cql.execute(f"INSERT INTO {table} (key, udt) VALUES (2, {{a: 'deux', b: 2}})")
|
||||
cql.execute(f"INSERT INTO {table} (key, udt) VALUES (3, {{a: 'trois', b: 3}})")
|
||||
|
||||
if has_java_udf:
|
||||
func_body = f"(udt {udt_name}) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return udt.getInt(\"b\");'"
|
||||
else:
|
||||
func_body = f"(udt {udt_name}) CALLED ON NULL INPUT RETURNS int LANGUAGE lua AS 'return udt.b'"
|
||||
with new_function(cql, test_keyspace, func_body) as funk:
|
||||
result = list(cql.execute(f"SELECT sum({test_keyspace}.{funk}(udt)) FROM {table}"))
|
||||
assert len(result) == 1
|
||||
assert result[0][0] == 6
|
||||
|
||||
# UDT should not be droppable while function references it
|
||||
with pytest.raises(InvalidRequest, match="is still used by"):
|
||||
cql.execute(f"DROP TYPE {udt}")
|
||||
|
||||
# Test that a UDF cannot reference a UDT from another keyspace.
|
||||
# Ported from scylla-dtest user_functions_test.py::test_udf_with_udt_keyspace_isolation (SCYLLADB-1928).
|
||||
# Reproduces CASSANDRA-9409.
|
||||
def test_udf_with_udt_keyspace_isolation(cql, test_keyspace, has_java_udf):
|
||||
with new_type(cql, test_keyspace, "(a text, b int)") as udt:
|
||||
_, udt_name = udt.split('.')
|
||||
with new_test_keyspace(cql, "WITH replication = {'class': 'NetworkTopologyStrategy', 'replication_factor': 1}") as other_ks:
|
||||
if has_java_udf:
|
||||
lang_arg = "LANGUAGE java AS 'return \"f1\";'"
|
||||
lang_ret = "LANGUAGE java AS 'return null;'"
|
||||
else:
|
||||
lang_arg = "LANGUAGE lua AS 'return \"f1\"'"
|
||||
lang_ret = "LANGUAGE lua AS 'return nil'"
|
||||
# Cannot use UDT from test_keyspace as function arg in other_ks
|
||||
with pytest.raises(InvalidRequest, match="cannot refer to a user type in keyspace"):
|
||||
cql.execute(
|
||||
f"CREATE FUNCTION {other_ks}.overloaded(v {test_keyspace}.{udt_name}) "
|
||||
f"CALLED ON NULL INPUT RETURNS text {lang_arg}")
|
||||
# Cannot use UDT from test_keyspace as return type in other_ks
|
||||
with pytest.raises(InvalidRequest, match="cannot refer to a user type in keyspace"):
|
||||
cql.execute(
|
||||
f"CREATE FUNCTION {other_ks}.testfun(v text) "
|
||||
f"CALLED ON NULL INPUT RETURNS {test_keyspace}.{udt_name} {lang_ret}")
|
||||
|
||||
Reference in New Issue
Block a user