Remove many unused "import" statements or parts of import statement. All of them were detected by Copilot, but I verified each one manually and prepared this patch. Signed-off-by: Nadav Har'El <nyh@scylladb.com> Closes scylladb/scylladb#27675
177 lines
8.4 KiB
Python
177 lines
8.4 KiB
Python
# Copyright 2025-present ScyllaDB
|
|
#
|
|
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
|
|
#############################################################################
|
|
# Tests for limits on the *names* of keyspaces, tables, indexes, views, function and columns.
|
|
#############################################################################
|
|
|
|
import pytest
|
|
from contextlib import contextmanager
|
|
from cassandra.protocol import InvalidRequest
|
|
from .util import unique_name, new_test_table, new_secondary_index, new_function, is_scylla
|
|
|
|
# This context manager is similar to new_test_table() - creating a table and
|
|
# keeping it alive while the context manager is in scope - but allows the
|
|
# caller to pick the name of the table. This is useful to attempt to create
|
|
# a table whose name has different lengths or characters.
|
|
# Note that if used in a shared keyspace, it is recommended to base the
|
|
# given table name on the output of unique_name(), to avoid name clashes.
|
|
# See the padded_name() function below as an example.
|
|
@contextmanager
|
|
def new_named_table(cql, keyspace, table, schema, extra=""):
|
|
tbl = keyspace+'.'+table
|
|
cql.execute(f'CREATE TABLE {tbl} ({schema}) {extra}')
|
|
try:
|
|
yield tbl
|
|
finally:
|
|
cql.execute(f'DROP TABLE {tbl}')
|
|
|
|
# padded_name() creates a unique name of given length by taking the
|
|
# output of unique_name() and padding it with extra 'x' characters:
|
|
def padded_name(length):
|
|
u = unique_name()
|
|
assert length >= len(u)
|
|
return u + 'x'*(length-len(u))
|
|
|
|
# Utility function to create a new keyspace with the given name.
|
|
# Created to avoid passing the same replication option in every tests.
|
|
@contextmanager
|
|
def new_keyspace(cql, ks_name=unique_name()):
|
|
cql.execute(f"CREATE KEYSPACE {ks_name} WITH REPLICATION = {{'class': 'SimpleStrategy', 'replication_factor': 1}}")
|
|
try:
|
|
yield ks_name
|
|
finally:
|
|
cql.execute(f"DROP KEYSPACE {ks_name}")
|
|
|
|
# Utility function to create a new table with the given name.
|
|
# Created to avoid passing the same schema option in every tests.
|
|
@contextmanager
|
|
def new_table(cql, ks_name, tbl_name=unique_name(), extra=""):
|
|
qualified_table_name = ks_name + '.' + tbl_name
|
|
cql.execute(f'CREATE TABLE {qualified_table_name} (p int, x int, PRIMARY KEY (p)) {extra}')
|
|
try:
|
|
yield qualified_table_name
|
|
finally:
|
|
cql.execute(f'DROP TABLE {qualified_table_name}')
|
|
|
|
# Utility function to create a materialized view with the given name.
|
|
# Created to avoid passing the same parameter values in every tests.
|
|
@contextmanager
|
|
def new_mv(cql, qualified_table_name, mv_name):
|
|
keyspace = qualified_table_name.split('.')[0]
|
|
qualified_mv_name = keyspace + "." + mv_name
|
|
cql.execute(
|
|
f"CREATE MATERIALIZED VIEW {qualified_mv_name} AS SELECT * FROM {qualified_table_name} WHERE p is not null and x is not null PRIMARY KEY (p, x)"
|
|
)
|
|
try:
|
|
yield qualified_mv_name
|
|
finally:
|
|
cql.execute(f"DROP MATERIALIZED VIEW {qualified_mv_name}")
|
|
|
|
# Cassandra's documentation states that "Both keyspace and table name ... are
|
|
# limited in size to 48 characters". This was actually only true in Cassandra
|
|
# 3, and by Cassandra 4 and 5 this limitation was dropped (see discussion
|
|
# in CASSANDRA-20425).
|
|
# Test verifies that a 48-character name is allowed, and passes on all versions
|
|
# of Scylla and Cassandra.
|
|
def test_table_name_length_48(cql, test_keyspace):
|
|
with new_table(cql, test_keyspace, padded_name(48)):
|
|
pass
|
|
|
|
# After Cassandra removed the 48-character limit for table names, some applications began creating tables with longer names.
|
|
# ScyllaDB relaxed its own limit to maintain compatibility with these applications.
|
|
# Due to CDC-enabled tables, ScyllaDB enforces a 192-character limit (see schema::NAME_LENGTH for details),
|
|
# while Cassandra allows names up to 222 characters.
|
|
# The 192-character limit in ScyllaDB is considered sufficient for most use cases.
|
|
# Test verifies that a 192-character name is allowed, and passes on Scylla and latest Cassandra versions (4 and 5).
|
|
def test_table_name_length_192(cql, test_keyspace):
|
|
with new_table(cql, test_keyspace, padded_name(192)):
|
|
pass
|
|
|
|
# If we try an even longer table name length, e.g., 500 characters, we run
|
|
# into the problem that an attempt to create a file or directory name based
|
|
# on the table name will fail (due to filesystem capabilities). Even if we lift the 48-character limitation
|
|
# introduced in Cassandra 3, creating a 500-character name should fail gracefully.
|
|
# Test verifies that a 500-character name is rejected by ScyllaDB and Cassandra.
|
|
# We mark this test cassandra_bug because Cassandra 5 hangs on this test (CASSANDRA-20425 and CASSANDRA-20389).
|
|
def test_table_name_length_500(cql, test_keyspace, cassandra_bug):
|
|
name = padded_name(500)
|
|
with pytest.raises(InvalidRequest, match=name):
|
|
with new_table(cql, test_keyspace, name):
|
|
pass
|
|
|
|
# Test verifies that a 192-character name for CDC enabled table is accepted for Scylla and Cassandra 4/5.
|
|
def test_table_cdc_name_length_192(cql):
|
|
# Incompatible Cassandra <-> Scylla API to enable CDC. See #9859.
|
|
cdc = "{'enabled': true}" if is_scylla(cql) else 'true'
|
|
with new_keyspace(cql) as keyspace:
|
|
with new_table(cql, keyspace, padded_name(192), extra=f"with CDC = {cdc}"):
|
|
pass
|
|
|
|
# When ScyllaDB lifted the table name length restriction, it also lifted the limit on keyspace name length.
|
|
# However, Cassandra still enforces a 48-character limit for keyspace names.
|
|
# Test verifies that a keyspace name of exactly 48 characters is accepted by all versions of ScyllaDB and Cassandra.
|
|
def test_keyspace_name_length_48(cql):
|
|
with new_keyspace(cql, padded_name(48)):
|
|
pass
|
|
|
|
# Test verifies that a keyspace name of exactly 192 is accepted by ScyllaDB.
|
|
# Marked scylla_only because Cassandra keeps the 48-character limit for keyspace names.
|
|
def test_keyspace_name_length_192(cql, scylla_only):
|
|
with new_keyspace(cql, padded_name(192)):
|
|
pass
|
|
|
|
# Test verifies that too long keyspace (exceeding filesystem capabilities) is gracefully rejected.
|
|
def test_keyspace_name_length_500(cql):
|
|
name = padded_name(500)
|
|
with pytest.raises(InvalidRequest, match=name):
|
|
with new_keyspace(cql, name):
|
|
pass
|
|
|
|
# Test verifies that materialized view names follow the same length rules as table names.
|
|
def test_mv_name_length_192(cql, test_keyspace):
|
|
with new_table(cql, test_keyspace) as table:
|
|
with new_mv(cql, table, padded_name(192)):
|
|
pass
|
|
|
|
# Test verifies that materialized view names follow the same length rules as table names.
|
|
# Marked cassandra_bug because Cassandra 5 hangs on this test (CASSANDRA-20425 and CASSANDRA-20389).
|
|
def test_mv_name_length_500(cql, test_keyspace, cassandra_bug):
|
|
name = padded_name(500)
|
|
with new_table(cql, test_keyspace) as table:
|
|
with pytest.raises(InvalidRequest, match=name):
|
|
with new_mv(cql, table, name):
|
|
pass
|
|
|
|
# Test verifies that secondary index names follow the same length rules as table names.
|
|
def test_index_name_length_192(cql, test_keyspace):
|
|
with new_table(cql, test_keyspace) as table:
|
|
with new_secondary_index(cql, table, "x", padded_name(192)):
|
|
pass
|
|
|
|
# Test verifies that secondary index names follow the same length rules as table names.
|
|
# Marked cassandra_bug because Cassandra 5 hangs on this test (CASSANDRA-20425 and CASSANDRA-20389).
|
|
def test_index_name_length_500(cql, test_keyspace, cassandra_bug):
|
|
name = padded_name(500)
|
|
with new_table(cql, test_keyspace) as table:
|
|
with pytest.raises(InvalidRequest, match=name):
|
|
with new_secondary_index(cql, table, "x", name):
|
|
pass
|
|
|
|
# Test verifies that column names are not restricted by schema::NAME_LENGTH or filesystem constraints.
|
|
def test_function_name_500(cql, test_keyspace):
|
|
# ScyllaDB by default supports Lua functions while Cassandra Java only.
|
|
# In this test we only want to verify function name, hence function body is not important.
|
|
lang = "lua" if is_scylla(cql) else "java"
|
|
with new_function(cql, test_keyspace, f"() CALLED ON NULL INPUT RETURNS int LANGUAGE {lang} AS 'return 0;'",
|
|
name=padded_name(500)):
|
|
pass
|
|
|
|
# Test verifies that column names are not restricted by schema::NAME_LENGTH or filesystem constraints.
|
|
def test_column_name_500(cql, test_keyspace):
|
|
with new_test_table(cql, test_keyspace, "p int primary key, " + padded_name(500) + " int"):
|
|
pass
|
|
|
|
# TODO: add tests for the allowed characters in a table name
|