Merge 'cql3:statements:describe_statement: include UDT/UDF/UDA in generic describe' from Michał Jadwiszczak

So far generic describe (`DESC <name>`) followed Cassandra implementation and it only described keyspace/table/view/index.

This commit adds UDT/UDF/UDA to generic describe.

Fixes: #14170

Closes scylladb/scylladb#14334

* github.com:scylladb/scylladb:
  docs:cql: add information  about generic describe
  cql-pytest:test_describe: add test for generic UDT/UDF/UDA desc
  cql3:statements:describe_statement: include UDT/UDF/UDA in generic describe
This commit is contained in:
Nadav Har'El
2023-09-24 13:03:04 +03:00
3 changed files with 67 additions and 1 deletions

View File

@@ -659,6 +659,7 @@ std::vector<lw_shared_ptr<column_specification>> generic_describe_statement::get
future<std::vector<std::vector<bytes_opt>>> generic_describe_statement::describe(cql3::query_processor& qp, const service::client_state& client_state) const {
auto db = qp.db();
auto& replica_db = db.real_database();
auto raw_ks = client_state.get_raw_keyspace();
auto ks_name = (_keyspace) ? *_keyspace : raw_ks;
@@ -671,6 +672,12 @@ future<std::vector<std::vector<bytes_opt>>> generic_describe_statement::describe
throw exceptions::invalid_request_exception(format("'{}' not found in keyspaces", _name));
}
}
auto ks = db.try_find_keyspace(ks_name);
if (!ks) {
throw exceptions::invalid_request_exception(format("'{}' not found in keyspaces", _name));
}
auto ks_meta = ks->metadata();
auto tbl = db.try_find_table(ks_name, _name);
if (tbl) {
@@ -686,6 +693,32 @@ future<std::vector<std::vector<bytes_opt>>> generic_describe_statement::describe
co_return serialize_descriptions({index(db, ks_name, _name, _with_internals)});
}
auto udt_meta = ks_meta->user_types();
if (udt_meta.has_type(to_bytes(_name))) {
co_return serialize_descriptions({type(replica_db, ks_meta, _name)});
}
auto uf = functions::functions::find(functions::function_name(ks_name, _name));
if (!uf.empty()) {
auto udfs = boost::copy_range<std::vector<shared_ptr<const keyspace_element>>>(uf | boost::adaptors::transformed([] (const auto& f) {
return dynamic_pointer_cast<const functions::user_function>(f.second);
}) | boost::adaptors::filtered([] (const auto& f) {
return f != nullptr;
}));
if (!udfs.empty()) {
co_return serialize_descriptions(co_await generate_descriptions(replica_db, udfs, true));
}
auto udas = boost::copy_range<std::vector<shared_ptr<const keyspace_element>>>(uf | boost::adaptors::transformed([] (const auto& f) {
return dynamic_pointer_cast<const functions::user_aggregate>(f.second);
}) | boost::adaptors::filtered([] (const auto& f) {
return f != nullptr;
}));
if (!udas.empty()) {
co_return serialize_descriptions(co_await generate_descriptions(replica_db, udas, true));
}
}
throw exceptions::invalid_request_exception(format("'{}' not found in keyspace '{}'", _name, ks_name));
}

View File

@@ -380,6 +380,9 @@ dumping all or portions of the schema.
In any of the commands, ``DESC`` may be used in place of ``DESCRIBE``.
You may also omit what you want to describe and just simply use ``DESCRIBE <name>``. This will look for the object
in a specific order: keyspace, table, view, index, user-defined type, user-defined function, user-defined aggregate.
The ``DESCRIBE CLUSTER`` command prints the cluster name and partitioner::

View File

@@ -439,7 +439,16 @@ def test_index_desc_in_table_desc(cql, test_keyspace):
assert create_idx_c in desc
assert f"CREATE INDEX {tbl_name}_b_idx_1 ON {tbl}((a), b)" in desc
# Test that generic 'DESC' works properly. It should be able to describe keyspace, table.
# -----------------------------------------------------------------------------
# "Generic describe" is a describe statement without specifying what kind of object
# you want to describe, so it only requires keyspace name(optionally) and object name.
# Genric describe should be exactly the same as normal describe, so for instannce:
# `DESC TABLE <table_name> == DESC <table_name>`.
#
# ScyllaDB looks for describing object in a following order:
# keyspace, table, view, index, UDT, UDF, UDA
# Cassandra compatibility require us to be able generic describe: keyspace, table, view, index.
def test_generic_desc(cql, random_seed):
with new_random_keyspace(cql) as ks:
with new_random_table(cql, ks) as t1, new_test_table(cql, ks, "a int primary key, b int, c int") as tbl:
@@ -460,6 +469,27 @@ def test_generic_desc(cql, random_seed):
assert generic_tbl == desc_tbl
assert generic_idx == desc_idx
# We've extended generic describe to include user-defined objects: UDTs, UDFs and UDAs.
# Since Cassandra doesn't generic description of support user-defined objects,
# the test is `scylla_only`.
# Reproduces #14170
def test_generic_desc_user_defined(scylla_only, cql, test_keyspace):
with new_random_type(cql, test_keyspace) as udt:
assert cql.execute(f"DESC {udt}") == cql.execute(f"DESC TYPE {udt}")
with new_function(cql, test_keyspace, """
(val1 int, val2 int)
RETURNS NULL ON NULL INPUT
RETURNS int
LANGUAGE lua
AS 'return val1 + val2'
""") as fn:
assert cql.execute(f"DESC {test_keyspace}.{fn}") == cql.execute(f"DESC FUNCTION {test_keyspace}.{fn}")
with new_aggregate(cql, test_keyspace, f"(int) SFUNC {fn} STYPE int INITCOND 0") as aggr:
assert cql.execute(f"DESC {test_keyspace}.{aggr}") == cql.execute(f"DESC AGGREGATE {test_keyspace}.{aggr}")
# 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: