OmniSciDB  b28c0d5765
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NumGeometries.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
20 
21 namespace spatial_type {
22 
23 class NumGeometries : public Codegen {
24  public:
25  NumGeometries(const Analyzer::GeoOperator* geo_operator,
26  const Catalog_Namespace::Catalog* catalog)
27  : Codegen(geo_operator, catalog) {}
28 
29  size_t size() const final { return 1; }
30 
31  SQLTypeInfo getNullType() const final { return SQLTypeInfo(kINT); }
32 
33  const SQLTypeInfo getOperandTypeInfo(const size_t index) {
34  CHECK_EQ(index, size_t(0));
35  const auto operand = operator_->getOperand(0);
36  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(operand);
37  if (!col_var) {
38  throw std::runtime_error(getName() +
39  " requires a geo column as its input argument.");
40  }
41  return col_var->get_type_info();
42  }
43 
44  const Analyzer::Expr* getOperand(const size_t index) final {
45  CHECK_EQ(index, size_t(0));
46  if (operand_owned_) {
47  return operand_owned_.get();
48  }
49 
50  const auto operand = operator_->getOperand(0);
51  auto col_var = dynamic_cast<const Analyzer::ColumnVar*>(operand);
52  if (!col_var) {
53  throw std::runtime_error(getName() +
54  " requires a geo column as its input argument.");
55  }
56 
57  const auto& geo_ti = col_var->get_type_info();
58  if (!geo_ti.is_geometry()) {
59  throw std::runtime_error(getName() +
60  " requires a geo column as its input argument.");
61  }
62  is_nullable_ = !geo_ti.get_notnull();
63 
64  auto const geo_type = geo_ti.get_type();
65  int column_offset{};
66  switch (geo_type) {
67  case kMULTIPOLYGON:
68  column_offset = 3; // poly_rings
69  break;
70  case kMULTILINESTRING:
71  column_offset = 2; // ring_sizes
72  break;
73  case kMULTIPOINT:
74  column_offset = 1; // points
75  break;
76  case kPOINT:
77  case kLINESTRING:
78  case kPOLYGON:
79  column_offset = 1; // nothing to count, but allow through
80  break;
81  default:
82  UNREACHABLE();
83  }
84 
85  // create a new operand which is just the column to count, and codegen it
86  const auto column_id = col_var->get_column_id() + column_offset;
87  auto cd = get_column_descriptor(column_id, col_var->get_table_id(), *cat_);
88  CHECK(cd);
89 
90  operand_owned_ = std::make_unique<Analyzer::ColumnVar>(
91  cd->columnType, col_var->get_table_id(), column_id, col_var->get_rte_idx());
92  return operand_owned_.get();
93  }
94 
95  // returns arguments lvs and null lv
96  std::tuple<std::vector<llvm::Value*>, llvm::Value*> codegenLoads(
97  const std::vector<llvm::Value*>& arg_lvs,
98  const std::vector<llvm::Value*>& pos_lvs,
99  CgenState* cgen_state) final {
100  CHECK_EQ(pos_lvs.size(), size());
101  CHECK_EQ(arg_lvs.size(), size_t(1));
102 
103  const auto& oper_ti = getOperandTypeInfo(0);
104  auto const is_multi_geo = IS_GEO_MULTI(oper_ti.get_type());
105 
106  // non-MULTI non-nullable geo, just return 1 (no function call)
107  if (!isNullable() && !is_multi_geo) {
108  auto* const one = cgen_state->llInt(1);
109  return {{one}, one};
110  }
111 
112  // will be a function call, the first two arguments
113  std::string fn_name("array_size");
114  auto& argument_lv = arg_lvs.front();
115  std::vector<llvm::Value*> array_size_args = {argument_lv, pos_lvs.front()};
116 
117  if (is_multi_geo) {
118  // MULTI geo, fetch and append element log size argument
119  const auto& elem_ti = getOperand(0)->get_type_info().get_elem_type();
120  uint32_t elem_log_sz_value{};
121  if (oper_ti.get_type() == kMULTIPOINT) {
122  // we must have been passed the coords column
123  CHECK(elem_ti.get_type() == kTINYINT);
124  // we want to return the number of points (two coords),
125  // so divide by either 8 (compressed) or 16 (uncompressed)
126  if (oper_ti.get_compression() == kENCODING_GEOINT) {
127  // number of INT pairs
128  elem_log_sz_value = 3;
129  } else {
130  // number of DOUBLE pairs
131  elem_log_sz_value = 4;
132  }
133  } else {
134  // some other count (ring_sizes or poly_sizes)
135  elem_log_sz_value = log2_bytes(elem_ti.get_logical_size());
136  }
137  array_size_args.push_back(cgen_state->llInt(elem_log_sz_value));
138  } else {
139  // non-MULTI but nullable geo, return 1 or NULL
140  fn_name += "_1";
141  }
142 
143  // nullable, add NULL value
144  if (isNullable()) {
145  fn_name += "_nullable";
146  array_size_args.push_back(cgen_state->inlineIntNull(getTypeInfo()));
147  }
148 
149  const auto total_num_geometries_lv = cgen_state->emitExternalCall(
150  fn_name, get_int_type(32, cgen_state->context_), array_size_args);
151 
152  return {{total_num_geometries_lv}, total_num_geometries_lv};
153  }
154 
155  std::vector<llvm::Value*> codegen(const std::vector<llvm::Value*>& args,
156  CodeGenerator::NullCheckCodegen* nullcheck_codegen,
157  CgenState* cgen_state,
158  const CompilationOptions& co) final {
159  CHECK_EQ(args.size(), size_t(1));
160  if (isNullable()) {
161  CHECK(nullcheck_codegen);
162  return {nullcheck_codegen->finalize(cgen_state->inlineIntNull(getTypeInfo()),
163  args.front())};
164  }
165  return {args.front()};
166  }
167 
168  protected:
169  std::unique_ptr<Analyzer::ColumnVar> operand_owned_;
170 };
171 
172 } // namespace spatial_type
#define CHECK_EQ(x, y)
Definition: Logger.h:230
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:132
#define UNREACHABLE()
Definition: Logger.h:266
SQLTypeInfo getNullType() const final
Definition: NumGeometries.h:31
std::unique_ptr< Analyzer::ColumnVar > operand_owned_
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
auto getTypeInfo() const
Definition: Codegen.h:37
NumGeometries(const Analyzer::GeoOperator *geo_operator, const Catalog_Namespace::Catalog *catalog)
Definition: NumGeometries.h:25
const Analyzer::Expr * getOperand(const size_t index) final
Definition: NumGeometries.h:44
const Catalog_Namespace::Catalog * cat_
Definition: Codegen.h:71
auto isNullable() const
Definition: Codegen.h:35
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:82
std::tuple< std::vector< llvm::Value * >, llvm::Value * > codegenLoads(const std::vector< llvm::Value * > &arg_lvs, const std::vector< llvm::Value * > &pos_lvs, CgenState *cgen_state) final
Definition: NumGeometries.h:96
const Analyzer::GeoOperator * operator_
Definition: Codegen.h:70
#define CHECK(condition)
Definition: Logger.h:222
const SQLTypeInfo getOperandTypeInfo(const size_t index)
Definition: NumGeometries.h:33
std::string getName() const
Definition: Codegen.h:39
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
Analyzer::Expr * getOperand(const size_t index) const
Definition: Analyzer.cpp:3954
uint32_t log2_bytes(const uint32_t bytes)
Definition: Execute.h:176
Definition: sqltypes.h:60
size_t size() const final
Definition: NumGeometries.h:29
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:957
const ColumnDescriptor * get_column_descriptor(const int col_id, const int table_id, const Catalog_Namespace::Catalog &cat)
Definition: Execute.h:191
#define IS_GEO_MULTI(T)
Definition: sqltypes.h:305