From d498451cdf2d4181d0399ea1c86bd50fcacff311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Jadwiszczak?= Date: Wed, 21 Jun 2023 10:55:08 +0200 Subject: [PATCH 1/2] cql3:statements:describe_statement: check pointer to UDF/UDA While looking for specific UDF/UDA, result of `functions::functions::find()` needs to be filtered out based on function's type. Fixes: #14360 --- cql3/statements/describe_statement.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cql3/statements/describe_statement.cc b/cql3/statements/describe_statement.cc index 57bfb5cff0a2..184218e4e1d8 100644 --- a/cql3/statements/describe_statement.cc +++ b/cql3/statements/describe_statement.cc @@ -179,7 +179,13 @@ future> function(replica::database& db, const sstring& auto udfs = boost::copy_range>>(fs | boost::adaptors::transformed([] (const auto& f) { return dynamic_pointer_cast(f.second); + }) | boost::adaptors::filtered([] (const auto& f) { + return f != nullptr; })); + if (udfs.empty()) { + throw exceptions::invalid_request_exception(format("Function '{}' not found in keyspace '{}'", name, ks)); + } + co_return co_await generate_descriptions(db, udfs, true); } @@ -192,13 +198,19 @@ future> functions(replica::database& db,const sstring& future> aggregate(replica::database& db, const sstring& ks, const sstring& name) { auto fs = functions::functions::find(functions::function_name(ks, name)); - if(fs.empty()) { + if (fs.empty()) { throw exceptions::invalid_request_exception(format("Aggregate '{}' not found in keyspace '{}'", name, ks)); } auto udas = boost::copy_range>>(fs | boost::adaptors::transformed([] (const auto& f) { return dynamic_pointer_cast(f.second); + }) | boost::adaptors::filtered([] (const auto& f) { + return f != nullptr; })); + if (udas.empty()) { + throw exceptions::invalid_request_exception(format("Aggregate '{}' not found in keyspace '{}'", name, ks)); + } + co_return co_await generate_descriptions(db, udas, true); } From d3d9a15505a589e09722e92ac283453c611b3032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Jadwiszczak?= Date: Wed, 21 Jun 2023 12:00:37 +0200 Subject: [PATCH 2/2] cql-pytest:test_describe: add test for filtering UDF and UDA --- test/cql-pytest/test_describe.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/cql-pytest/test_describe.py b/test/cql-pytest/test_describe.py index f95e873c13a5..f1c9894d293b 100644 --- a/test/cql-pytest/test_describe.py +++ b/test/cql-pytest/test_describe.py @@ -12,6 +12,7 @@ from pytest import fixture from contextlib import contextmanager from util import new_type, unique_name, new_test_table, new_test_keyspace, new_function, new_aggregate, new_cql +from cassandra.protocol import InvalidRequest # (`element` refers to keyspace or keyspace's element(table, type, function, aggregate)) # There are 2 main types of tests: @@ -459,6 +460,16 @@ def test_generic_desc(cql, random_seed): assert generic_tbl == desc_tbl assert generic_idx == desc_idx +# Test that 'DESC FUNCTION'/'DESC AGGREGATE' doesn't show UDA/UDF and doesn't crash Scylla +def test_desc_udf_uda(cql, test_keyspace): + with new_function(cql, test_keyspace, "(a int, b int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE LUA AS 'return a+b'") as fn: + with new_aggregate(cql, test_keyspace, f"(int) SFUNC {fn} STYPE int") as aggr: + + with pytest.raises(InvalidRequest): + cql.execute(f"DESC FUNCTION {test_keyspace}.{aggr}") + with pytest.raises(InvalidRequest): + cql.execute(f"DESC AGGREGATE {test_keyspace}.{fn}") + # ----------------------------------------------------------------------------- # Following tests `test_*_quoting` check if names inside elements' descriptions are quoted if needed. # The tests don't check if create statements are correct, but only assert if the name inside is quoted.