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:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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::
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user