Files
scylladb/test/boost/cql_query_group_test.cc
Kefu Chai 7ff0d7ba98 tree: Remove unused boost headers
This commit eliminates unused boost header includes from the tree.

Removing these unnecessary includes reduces dependencies on the
external Boost.Adapters library, leading to faster compile times
and a slightly cleaner codebase.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#22857
2025-02-15 20:32:22 +02:00

238 lines
14 KiB
C++

/*
* Copyright (C) 2015-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#include <boost/test/unit_test.hpp>
#include <seastar/net/inet_address.hh>
#undef SEASTAR_TESTING_MAIN
#include <seastar/testing/test_case.hh>
#include <seastar/testing/thread_test_case.hh>
#include "test/lib/cql_test_env.hh"
#include "test/lib/cql_assertions.hh"
#include <seastar/core/future-util.hh>
#include "test/lib/exception_utils.hh"
BOOST_AUTO_TEST_SUITE(cql_query_group_test)
using namespace std::literals::chrono_literals;
SEASTAR_TEST_CASE(test_group_by_syntax) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e,
"create table t1 (p1 int, p2 int, c1 int, c2 int, c3 int, npk int, primary key((p1, p2), c1, c2, c3))");
cquery_nofail(e, "create table t2 (p1 int, p2 int, p3 int, npk int, primary key((p1, p2, p3)))");
// Must parse correctly:
cquery_nofail(e, "select count(c1) from t1 group by p1, p2");
cquery_nofail(e, "select count(c1) from t1 group by p1, p2, c1");
cquery_nofail(e, "select sum(c2) from t1 group by p1, p2");
cquery_nofail(e, "select avg(npk) from t1 group by \"p1\", \"p2\"");
cquery_nofail(e, "select sum(p2) from t1 group by p1, p2, c1, c2, c3");
cquery_nofail(e, "select count(npk) from t1 where p1=1 and p2=1 group by c1, c2 order by c1 allow filtering");
cquery_nofail(e, "select c2 from t1 where p2=2 group by p1, c1 allow filtering");
cquery_nofail(e, "select npk from t1 where p2=2 group by p1, p2, c1 allow filtering");
cquery_nofail(e, "select p1 from t2 group by p1, p2, p3");
cquery_nofail(e, "select * from t2 where p1=1 group by p1, p2, p3 allow filtering");
cquery_nofail(e, "select * from t2 where p1=1 group by p2, p3 allow filtering");
cquery_nofail(e, "select * from t2 where p1=1 and p2=2 and p3=3 group by p1, p2, p3 allow filtering");
cquery_nofail(e, "select * from t2 where p1=1 and p2=2 and p3=3 group by p3 allow filtering");
cquery_nofail(e, "select * from t1 where p1>0 and p2=0 group by p1, c1 allow filtering");
using ire = exceptions::invalid_request_exception;
const auto unknown = exception_predicate::message_contains("unknown column");
const auto non_primary = exception_predicate::message_contains("non-primary-key");
const auto order = exception_predicate::message_contains("order");
const auto partition = exception_predicate::message_contains("partition key");
// Flag invalid columns in GROUP BY:
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by xyz").get(), ire, unknown);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by p1, xyz").get(), ire, unknown);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by npk").get(), ire, non_primary);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by p1, npk").get(), ire, non_primary);
// Even when GROUP BY lists all primary-key columns:
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by p1, p2, c1, c2, c3, foo").get(), ire, unknown);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t1 group by p1, p2, c1, c2, c3, npk").get(), ire, non_primary);
// Even when entire primary key is equality-restricted.
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t2 where p1=1 and p2=2 and p3=3 group by npk allow filtering").get(),
ire, non_primary);
// Flag invalid column order:
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by p2, p1").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t1 where p1=1 group by p2, c2 allow filtering").get(), ire, order);
// Even with equality restrictions:
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t2 where p1=1 group by p3 allow filtering").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t2 where p1=1 group by p2, p1 allow filtering").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t2 where p2=2 group by p1, p3, p2 allow filtering").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t2 where p1=1 and p2=2 and p3=3 group by p2, p1 allow filtering").get(),
ire, order);
// And with non-equality restrictions:
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t1 where p1 > 0 group by p2 allow filtering").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t1 where (c1,c2) > (0,0) group by p1, p2, c3 allow filtering").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t1 where p1>0 and p2=0 group by c1 allow filtering").get(), ire, order);
// Even when GROUP BY lists all primary-key columns:
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t2 group by p1, p2, p2, p3").get(), ire, order);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t2 group by p1, p2, p3, p1").get(), ire, order);
// GROUP BY must list the entire partition key:
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t2 group by p1, p2").get(), ire, partition);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t2 group by p1").get(), ire, partition);
BOOST_REQUIRE_EXCEPTION(e.execute_cql("select * from t1 group by p1").get(), ire, partition);
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_syntax_no_value_columns) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p1 int, p2 int, p3 int, primary key((p1, p2, p3)))");
BOOST_REQUIRE_EXCEPTION(
e.execute_cql("select * from t group by p1, p2, p3, p1").get(),
exceptions::invalid_request_exception,
exception_predicate::message_contains("order"));
});
}
namespace {
auto I(int32_t x) { return int32_type->decompose(x); }
auto L(int64_t x) { return long_type->decompose(x); }
auto T(const char* t) { return utf8_type->decompose(t); }
} // anonymous namespace
SEASTAR_TEST_CASE(test_group_by_aggregate_single_key) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p int primary key, n int)");
cquery_nofail(e, "insert into t (p, n) values (1, 10)");
// Rows contain GROUP BY column values (later filtered in cql_server::connection).
require_rows(e, "select sum(n) from t group by p", {{I(10), I(1)}});
require_rows(e, "select avg(n) from t group by p", {{I(10), I(1)}});
require_rows(e, "select count(n) from t group by p", {{L(1), I(1)}});
cquery_nofail(e, "insert into t (p, n) values (2, 20)");
require_rows(e, "select sum(n) from t group by p", {{I(10), I(1)}, {I(20), I(2)}});
require_rows(e, "select avg(n) from t group by p", {{I(20), I(2)}, {I(10), I(1)}});
require_rows(e, "select count(n) from t group by p", {{L(1), I(2)}, {L(1), I(1)}});
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_aggregate_partition_only) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p1 int, p2 int, p3 int, v int, primary key((p1, p2, p3)))");
cquery_nofail(e, "insert into t (p1, p2, p3, v) values (1, 1, 1, 100)");
// Rows contain GROUP BY column values (later filtered in cql_server::connection).
require_rows(e, "select sum(v) from t group by p1, p2, p3", {{I(100), I(1), I(1), I(1)}});
cquery_nofail(e, "insert into t (p1, p2, p3, v) values (1, 2, 1, 100)");
require_rows(e, "select sum(v) from t group by p1, p2, p3",
{{I(100), I(1), I(1), I(1)}, {I(100), I(1), I(2), I(1)}});
require_rows(e, "select sum(v) from t where p2=2 group by p1, p3 allow filtering",
{{I(100), I(2), I(1), I(1)}});
cquery_nofail(e, "insert into t (p1, p2, p3, v) values (1, 2, 2, 100)");
require_rows(e, "select sum(v) from t group by p1, p2, p3",
{{I(100), I(1), I(1), I(1)}, {I(100), I(1), I(2), I(1)}, {I(100), I(1), I(2), I(2)}});
cquery_nofail(e, "delete from t where p1=1 and p2=1 and p3=1");
require_rows(e, "select sum(v) from t group by p1, p2, p3",
{{I(100), I(1), I(2), I(1)}, {I(100), I(1), I(2), I(2)}});
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_aggregate_clustering) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p1 int, c1 int, c2 int, v int, primary key((p1), c1, c2))");
cquery_nofail(e, "insert into t (p1, c1, c2, v) values (1, 1, 1, 100)");
cquery_nofail(e, "insert into t (p1, c1, c2, v) values (1, 1, 2, 100)");
cquery_nofail(e, "insert into t (p1, c1, c2, v) values (1, 1, 3, 100)");
cquery_nofail(e, "insert into t (p1, c1, c2, v) values (2, 1, 1, 100)");
cquery_nofail(e, "insert into t (p1, c1, c2, v) values (2, 2, 2, 100)");
cquery_nofail(e, "delete from t where p1=1 and c1=1 and c2 =3");
require_rows(e, "select sum(v) from t group by p1", {{I(200), I(1)}, {I(200), I(2)}});
require_rows(e, "select sum(v) from t group by p1, c1",
{{I(200), I(1), I(1)}, {I(100), I(2), I(1)}, {I(100), I(2), I(2)}});
require_rows(e, "select sum(v) from t where p1=1 and c1=1 group by c2 allow filtering",
{{I(100), I(1)}, {I(100), I(2)}});
require_rows(e, "select sum(v) from t group by p1, c1, c2",
{{I(100), I(1), I(1), I(1)}, {I(100), I(1), I(1), I(2)},
{I(100), I(2), I(1), I(1)}, {I(100), I(2), I(2), I(2)}});
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_text_key) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p text, c text, v int, primary key(p, c))");
cquery_nofail(e, "insert into t (p, c, v) values ('123456789012345678901234567890123', '1', 100)");
cquery_nofail(e, "insert into t (p, c, v) values ('123456789012345678901234567890123', '2', 200)");
cquery_nofail(e, "insert into t (p, c, v) values ('123456789012345678901234567890123', '3', 300)");
cquery_nofail(e, "insert into t (p, c, v) values ('123456789012345678901234567890123abc', '1', 150)");
cquery_nofail(e, "insert into t (p, c, v) values ('123456789012345678901234567890123abc', '2', 250)");
cquery_nofail(e, "insert into t (p, c, v) values ('ab', 'cd', 310)");
cquery_nofail(e, "insert into t (p, c, v) values ('abc', 'd', 420)");
require_rows(e, "select sum(v) from t group by p",
{{I(600), T("123456789012345678901234567890123")},
{I(400), T("123456789012345678901234567890123abc")},
{I(310), T("ab")},
{I(420), T("abc")}});
require_rows(e, "select sum(v) from t where p in ('ab','abc') group by p, c allow filtering",
{{I(310), T("ab"), T("cd")}, {I(420), T("abc"), T("d")}});
require_rows(e, "select sum(v) from t where p='123456789012345678901234567890123' group by c",
{{I(100), T("1")}, {I(200), T("2")}, {I(300), T("3")}});
cquery_nofail(e, "create table t2 (p text, c1 text, c2 text, v int, primary key(p, c1, c2))");
cquery_nofail(e, "insert into t2 (p, c1, c2, v) values (' ', '', '', 10)");
cquery_nofail(e, "insert into t2 (p, c1, c2, v) values (' ', '', 'b', 20)");
cquery_nofail(e, "insert into t2 (p, c1, c2, v) values (' ', 'a', '', 30)");
cquery_nofail(e, "insert into t2 (p, c1, c2, v) values (' ', 'a', 'b', 40)");
require_rows(e, "select avg(v) from t2 group by p", {{I(25), T(" ")}});
require_rows(e, "select avg(v) from t2 group by p, c1", {{I(15), T(" "), T("")}, {I(35), T(" "), T("a")}});
require_rows(e, "select sum(v) from t2 where c1='' group by p, c2 allow filtering",
{{I(10), T(" "), T("")}, {I(20), T(" "), T("b")}});
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_non_aggregate) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p int, c int, n int, primary key(p, c))");
cquery_nofail(e, "insert into t (p, c, n) values (1, 1, 11)");
require_rows(e, "select n from t group by p", {{I(11), I(1)}});
cquery_nofail(e, "insert into t (p, c, n) values (2, 1, 21)");
require_rows(e, "select n from t group by p", {{I(11), I(1)}, {I(21), I(2)}});
cquery_nofail(e, "delete from t where p=1");
require_rows(e, "select n from t group by p", {{I(21), I(2)}});
cquery_nofail(e, "insert into t (p, c, n) values (1, 1, 11)");
cquery_nofail(e, "insert into t (p, c, n) values (1, 2, 12)");
cquery_nofail(e, "insert into t (p, c, n) values (1, 3, 13)");
require_rows(e, "select n from t group by p", {{I(11), I(1)}, {I(21), I(2)}});
return make_ready_future<>();
});
}
SEASTAR_TEST_CASE(test_group_by_null_clustering) {
return do_with_cql_env_thread([] (cql_test_env& e) {
cquery_nofail(e, "create table t (p int, c int, sv int static, primary key(p, c))");
cquery_nofail(e, "insert into t (p, sv) values (1, 100)"); // c will be NULL.
require_rows(e, "select sv from t where p=1 group by c", {{I(100), std::nullopt}});
return make_ready_future<>();
});
}
BOOST_AUTO_TEST_SUITE_END()