Line data Source code
1 : #include "backend/engine/semantic/functions/range_funcs.h"
2 :
3 : #include <memory>
4 : #include <string>
5 : #include <vector>
6 :
7 : #include "absl/status/statusor.h"
8 : #include "absl/strings/str_cat.h"
9 : #include "backend/engine/semantic/value.h"
10 : #include "googlesql/public/analyzer.h"
11 : #include "googlesql/public/analyzer_options.h"
12 : #include "googlesql/public/analyzer_output.h"
13 : #include "googlesql/public/builtin_function_options.h"
14 : #include "googlesql/public/language_options.h"
15 : #include "googlesql/public/options.pb.h"
16 : #include "googlesql/public/simple_catalog.h"
17 : #include "googlesql/public/types/type_factory.h"
18 : #include "googlesql/public/value.h"
19 : #include "googlesql/resolved_ast/resolved_ast.h"
20 : #include "gtest/gtest.h"
21 :
22 : namespace bigquery_emulator {
23 : namespace backend {
24 : namespace engine {
25 : namespace semantic {
26 : namespace functions {
27 : namespace {
28 :
29 : using ::googlesql::Value;
30 :
31 6 : ::googlesql::AnalyzerOptions MakeAnalyzerOptions() {
32 6 : ::googlesql::LanguageOptions language;
33 6 : language.EnableMaximumLanguageFeatures();
34 6 : language.set_product_mode(::googlesql::PRODUCT_EXTERNAL);
35 6 : ::googlesql::AnalyzerOptions options(language);
36 6 : options.CreateDefaultArenasIfNotSet();
37 6 : return options;
38 6 : }
39 :
40 : class RangeFuncsTest : public ::testing::Test {
41 : protected:
42 3 : void SetUp() override {
43 3 : type_factory_ = std::make_unique<::googlesql::TypeFactory>();
44 3 : catalog_ = std::make_unique<::googlesql::SimpleCatalog>(
45 3 : "range_funcs_catalog", type_factory_.get());
46 3 : catalog_->AddBuiltinFunctions(
47 3 : ::googlesql::BuiltinFunctionOptions::AllReleasedFunctions());
48 3 : }
49 :
50 6 : absl::StatusOr<Value> LiteralValue(absl::string_view literal_sql) {
51 6 : last_output_.reset();
52 6 : const std::string sql = absl::StrCat("SELECT ", literal_sql);
53 6 : absl::Status s = ::googlesql::AnalyzeStatement(sql,
54 6 : MakeAnalyzerOptions(),
55 6 : catalog_.get(),
56 6 : type_factory_.get(),
57 6 : &last_output_);
58 6 : if (!s.ok()) return s;
59 6 : if (last_output_ == nullptr) {
60 0 : return absl::InternalError("analyzer returned null output");
61 0 : }
62 6 : const auto* stmt = last_output_->resolved_statement()
63 6 : ->GetAs<::googlesql::ResolvedQueryStmt>();
64 6 : if (stmt == nullptr) {
65 0 : return absl::InternalError("expected ResolvedQueryStmt");
66 0 : }
67 6 : const auto* project =
68 6 : stmt->query()->GetAs<::googlesql::ResolvedProjectScan>();
69 6 : if (project == nullptr || project->expr_list_size() == 0) {
70 0 : return absl::InternalError("expected literal project scan");
71 0 : }
72 6 : const auto* lit =
73 6 : project->expr_list(0)->expr()->GetAs<::googlesql::ResolvedLiteral>();
74 6 : if (lit == nullptr) {
75 0 : return absl::InternalError("expected ResolvedLiteral");
76 0 : }
77 6 : return lit->value();
78 6 : }
79 :
80 : std::unique_ptr<::googlesql::TypeFactory> type_factory_{};
81 : std::unique_ptr<::googlesql::SimpleCatalog> catalog_{};
82 : std::unique_ptr<const ::googlesql::AnalyzerOutput> last_output_{};
83 : };
84 :
85 1 : TEST_F(RangeFuncsTest, RangeOverlapsDetectsOverlap) {
86 1 : auto a_or = LiteralValue("RANGE<DATE> '[2001-11-12, 2001-11-14)'");
87 1 : auto b_or = LiteralValue("RANGE<DATE> '[2001-11-13, 2001-11-15)'");
88 2 : ASSERT_TRUE(a_or.ok()) << a_or.status();
89 2 : ASSERT_TRUE(b_or.ok()) << b_or.status();
90 1 : Value a = *std::move(a_or);
91 1 : Value b = *std::move(b_or);
92 1 : auto v = RangeOverlaps({a, b});
93 2 : ASSERT_TRUE(v.ok()) << v.status();
94 1 : EXPECT_TRUE(v->bool_value());
95 1 : }
96 :
97 1 : TEST_F(RangeFuncsTest, RangeOverlapsAdjacentRangesDoNotOverlap) {
98 1 : auto a_or = LiteralValue("RANGE<DATE> '[2001-11-12, 2001-11-14)'");
99 1 : auto b_or = LiteralValue("RANGE<DATE> '[2001-11-14, 2001-11-15)'");
100 2 : ASSERT_TRUE(a_or.ok()) << a_or.status();
101 2 : ASSERT_TRUE(b_or.ok()) << b_or.status();
102 1 : Value a = *std::move(a_or);
103 1 : Value b = *std::move(b_or);
104 1 : auto v = RangeOverlaps({a, b});
105 2 : ASSERT_TRUE(v.ok()) << v.status();
106 1 : EXPECT_FALSE(v->bool_value());
107 1 : }
108 :
109 1 : TEST_F(RangeFuncsTest, RangeStartAndCtorBuildLdiffSlice) {
110 1 : auto p1_or = LiteralValue("RANGE<DATE> '[2001-11-12, 2001-11-14)'");
111 1 : auto p2_or = LiteralValue("RANGE<DATE> '[2001-11-13, 2001-11-15)'");
112 2 : ASSERT_TRUE(p1_or.ok()) << p1_or.status();
113 2 : ASSERT_TRUE(p2_or.ok()) << p2_or.status();
114 1 : Value p1 = *std::move(p1_or);
115 1 : Value p2 = *std::move(p2_or);
116 1 : auto start1 = RangeStart({p1});
117 1 : auto start2 = RangeStart({p2});
118 2 : ASSERT_TRUE(start1.ok()) << start1.status();
119 2 : ASSERT_TRUE(start2.ok()) << start2.status();
120 1 : auto range = RangeCtor({*start1, *start2}, p1.type());
121 2 : ASSERT_TRUE(range.ok()) << range.status();
122 1 : EXPECT_EQ(range->type_kind(), ::googlesql::TYPE_RANGE);
123 1 : std::string lit = range->GetSQLLiteral();
124 38 : for (char& c : lit) {
125 38 : if (c == '"') c = '\'';
126 38 : }
127 1 : EXPECT_EQ(lit, "RANGE<DATE> '[2001-11-12, 2001-11-13)'");
128 1 : }
129 :
130 : } // namespace
131 : } // namespace functions
132 : } // namespace semantic
133 : } // namespace engine
134 : } // namespace backend
135 : } // namespace bigquery_emulator
|