Files
scylladb/test/cql-pytest/test_udf.py
Nadav Har'El 0ecf84e83e test/cql-pytest: add test for DROP FUNCTION
We already have in test/cql-pytest various tests for UDF in the bigger
context of UDA (test_uda.py), WASM (test_wasm.py) and permissions, but
somehow we never had a file for simple tests only for UDF, so we
add one here, test/cql-pytest/test_udf.py

We add a test for checking something which was already assumed in
test_permissions.py - that it is possible to create two different
UDFs with the same name and different parameters, and then you must
specify the parameters when you want to DROP one of them. The test
confirms that ScyllaDB's and Cassandra's behavior is identical in
this, as hoped.

To allow the test to run on both ScyllaDB and Cassandra, it needs to
support both Lua (for ScyllaDB) or Java (for Cassandra), and we introduce
a fixture to make it easier to support both. This fixture can later
be used in more tests added to this file.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2023-11-12 17:14:08 +02:00

68 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2023-present ScyllaDB
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#############################################################################
# Tests for user-defined functions (UDF)
#############################################################################
import pytest
from util import unique_name, new_function
from cassandra.protocol import InvalidRequest
# 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
# Lua. The following fixture can be used to check if the server supports
# Java UDFs - and if it doesn't, the test should use Lua.
@pytest.fixture(scope="session")
def has_java_udf(cql, test_keyspace):
try:
with new_function(cql, test_keyspace, "(i int) CALLED ON NULL INPUT RETURNS int LANGUAGE java AS 'return 42;'"):
return True
except InvalidRequest as e:
# When the language "java" is not supported, Scylla prints the
# error message "Language 'java' is not supported". Cassandra
# isn't expected to fail here because it does support Java.
# Any other error here indicates an unexpected bug.
assert "Language 'java' is not supported" in str(e)
return False
# Test that if we have an overloaded function (i.e., two functions with the
# same name, just with different parameters), DROP FUNCTION requires
# disambiguating which function you want to drop. Without parameters, the
# DROP will be an error. On the other hand, when a function is not
# overloaded and has a unique name, it's not necessary to list the
# parameters in the DROP command.
def test_drop_overloaded_udf(cql, test_keyspace, has_java_udf):
if has_java_udf:
body1 = "(i int) CALLED ON NULL INPUT RETURNS bigint LANGUAGE java AS 'return 42L;'"
body2 = "(i int, j int) CALLED ON NULL INPUT RETURNS bigint LANGUAGE java AS 'return 42L;'"
else:
body1 = "(i int) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return 42;'"
body2 = "(i int, j int) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return 42;'"
args1 = "int"
args2 = "int, int"
# Create two different functions with the same name fun, but a
# different signature (different parameters):
fun = unique_name()
with new_function(cql, test_keyspace, body1, name=fun, args=args1):
with new_function(cql, test_keyspace, body2, name=fun, args=args2):
# Shouldn't be able to DROP "fun" without parameters, because
# it's ambiguous.
with pytest.raises(InvalidRequest, match="multiple function"):
cql.execute(f"DROP FUNCTION {test_keyspace}.{fun}")
# Should be ok to DROP one of the "fun" instances by specifying
# its parameters explicitly
cql.execute(f"DROP FUNCTION {test_keyspace}.{fun}({args2})")
# Now there's only one function left with that name, so it
# should be fine to drop "fun" without explicit parameters:
cql.execute(f"DROP FUNCTION {test_keyspace}.{fun}")
# The new_function() context manager will expect the functions
# to exist when it ends, to drop them. But we just dropped them.
# 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}")