Code in functions.cc creates the different TYPEasblob() and blobasTYPE() functions for all type names TYPE. The functions for the "counter" type were skipped, supposedly because "counters are not supported yet". But counters are supported, so let's add the missing functions. The code fix is trivial, the tests that verify that the result behaves like Cassandra took more work. After this patch, unimplemented::cause::COUNTERS is no longer used anywhere in the code. I wanted to remove it, but noticed that unimplemented::cause is a graveyard of unused causes, so decided not to remove this one either. We should clean it up in a separate patch. Fixes #14742 Also includes tests for tangently-related issues: Refs #12607 Refs #14319 Signed-off-by: Nadav Har'El <nyh@scylladb.com>
75 lines
3.9 KiB
Python
75 lines
3.9 KiB
Python
# Copyright 2023-present ScyllaDB
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
###############################################################################
|
|
# Tests for various native (built-in) scalar functions that can be used in
|
|
# various SELECT, INSERT or UPDATE requests. Note we also have tests for
|
|
# some of these functions in many other test files. For example, the tests
|
|
# for the cast() function are in test_cast_data.py.
|
|
###############################################################################
|
|
|
|
import pytest
|
|
from util import new_test_table, unique_key_int
|
|
from cassandra.protocol import InvalidRequest
|
|
|
|
@pytest.fixture(scope="module")
|
|
def table1(cql, test_keyspace):
|
|
with new_test_table(cql, test_keyspace, "p int, i int, g bigint, b blob, s text, t timestamp, u timeuuid, PRIMARY KEY (p)") as table:
|
|
yield table
|
|
|
|
# Check that a function that can take a column name as a parameter, can also
|
|
# take a constant. This feature is barely useful for WHERE clauses, and
|
|
# even less useful for selectors, but should be allowed for both.
|
|
# Reproduces #12607.
|
|
@pytest.mark.xfail(reason="issue #12607")
|
|
def test_constant_function_parameter(cql, table1):
|
|
p = unique_key_int()
|
|
cql.execute(f"INSERT INTO {table1} (p, b) VALUES ({p}, 0x03)")
|
|
assert [(p,)] == list(cql.execute(f"SELECT p FROM {table1} WHERE p={p} AND b=tinyintAsBlob(3) ALLOW FILTERING"))
|
|
assert [(b'\x04',)] == list(cql.execute(f"SELECT tinyintAsBlob(4) FROM {table1} WHERE p={p}"))
|
|
|
|
# According to the documentation, "The `minTimeuuid` function takes a
|
|
# `timestamp` value t, either a timestamp or a date string.". But although
|
|
# both cases are supported with constant parameters in WHERE restrictions,
|
|
# in a *selector* (the first part of the SELECT, saying what to select), it
|
|
# turns out that ONLY a timestamp column is allowed. Although this is
|
|
# undocumented behavior, both Cassandra and Scylla share it so we deem it
|
|
# correct.
|
|
def test_selector_mintimeuuid(cql, table1):
|
|
p = unique_key_int()
|
|
cql.execute(f"INSERT INTO {table1} (p, s, t, i) VALUES ({p}, '2013-02-02 10:00+0000', 123, 456)")
|
|
# We just check this works, not what the value is:
|
|
cql.execute(f"SELECT mintimeuuid(t) FROM {table1} WHERE p={p}")
|
|
# This doesn't work - despite the documentation, in a selector a
|
|
# date string is not supported by mintimeuuid.
|
|
with pytest.raises(InvalidRequest, match='of type timestamp'):
|
|
cql.execute(f"SELECT mintimeuuid(s) FROM {table1} WHERE p={p}")
|
|
# Other integer types also don't work, it must be a timestamp:
|
|
with pytest.raises(InvalidRequest, match='of type timestamp'):
|
|
cql.execute(f"SELECT mintimeuuid(i) FROM {table1} WHERE p={p}")
|
|
|
|
# Cassandra allows the implicit (and wrong!) casting of a bigint returned
|
|
# by writetime() to the timestamp type required by mintimeuuid(). Scylla
|
|
# doesn't. I'm not sure which behavior we should consider correct, but it's
|
|
# useful to have a test that demonstrates this incompatibility.
|
|
# Reproduces #14319.
|
|
@pytest.mark.xfail(reason="issue #14319")
|
|
def test_selector_mintimeuuid_64bit(cql, table1):
|
|
p = unique_key_int()
|
|
cql.execute(f"INSERT INTO {table1} (p, g) VALUES ({p}, 123)")
|
|
cql.execute(f"SELECT mintimeuuid(g) FROM {table1} WHERE p={p}")
|
|
cql.execute(f"SELECT mintimeuuid(writetime(g)) FROM {table1} WHERE p={p}")
|
|
|
|
# blobasbigint() must insist to receive a properly-sized (8-byte) blob.
|
|
# If it accepts a shorter blob (e.g., 4 bytes) and returns that to the driver,
|
|
# it will confuse the driver (the driver will expect to read 8 bytes for the
|
|
# bigint but will get only 4).
|
|
def test_blobas_wrong_size(cql, table1):
|
|
p = unique_key_int()
|
|
cql.execute(f"INSERT INTO {table1} (p, i) VALUES ({p}, 123)")
|
|
# Cassandra and Scylla print: "In call to function system.blobasbigint,
|
|
# value 0x0000007b is not a valid binary representation for type bigint".
|
|
with pytest.raises(InvalidRequest, match='blobasbigint'):
|
|
cql.execute(f"SELECT blobasbigint(intasblob(i)) FROM {table1} WHERE p={p}")
|