21 namespace spatial_type {
27 :
Codegen(geo_operator, catalog) {
33 size_t size() const final {
return 2; }
38 const std::vector<llvm::Value*>& arg_lvs,
39 const std::vector<llvm::Value*>& pos_lvs,
42 std::string size_fn_name =
"array_size";
44 size_fn_name +=
"_nullable";
47 auto& builder = cgen_state->ir_builder_;
48 llvm::Value*
is_null = cgen_state->llBool(
false);
50 std::vector<llvm::Value*> operand_lvs;
51 size_t arg_lvs_index{0};
52 for (
size_t i = 0; i <
size(); i++) {
55 const auto& operand_ti = operand->get_type_info();
57 const size_t num_physical_coord_lvs = operand_ti.get_physical_coord_cols();
60 bool is_coords_lv{
true};
61 if (dynamic_cast<const Analyzer::ColumnVar*>(operand)) {
62 for (
size_t j = 0; j < num_physical_coord_lvs; j++) {
63 CHECK_LT(arg_lvs_index, arg_lvs.size());
64 auto lv = arg_lvs[arg_lvs_index++];
67 cgen_state->emitExternalCall(
"array_buff",
68 llvm::Type::getInt8PtrTy(cgen_state->context_),
72 array_buff_lv = builder.CreateBitCast(
73 array_buff_lv, llvm::Type::getInt32PtrTy(cgen_state->context_));
75 operand_lvs.push_back(array_buff_lv);
77 const auto ptr_type = llvm::dyn_cast_or_null<llvm::PointerType>(lv->getType());
79 const auto elem_type = ptr_type->getElementType();
81 const uint32_t coords_elem_sz_bytes =
83 operand_ti.get_type() ==
kPOINT
86 std::vector<llvm::Value*> array_sz_args{
89 cgen_state->llInt(
log2_bytes(j == 0 ? coords_elem_sz_bytes : 4))};
92 array_sz_args.push_back(cgen_state->llInt(
93 static_cast<int32_t>(inline_int_null_value<int32_t>())));
95 operand_lvs.push_back(cgen_state->emitExternalCall(
96 size_fn_name,
get_int_type(32, cgen_state->context_), array_sz_args));
97 llvm::Value* operand_is_null_lv{
nullptr};
99 if (operand_ti.get_type() ==
kPOINT) {
100 operand_is_null_lv = cgen_state->emitExternalCall(
101 "point_coord_array_is_null",
102 llvm::Type::getInt1Ty(cgen_state->context_),
105 operand_is_null_lv = builder.CreateICmpEQ(
108 static_cast<int32_t>(inline_int_null_value<int32_t>())));
110 is_null = builder.CreateOr(is_null, operand_is_null_lv);
112 is_coords_lv =
false;
115 bool is_coords_lv{
true};
116 for (
size_t j = 0; j < num_physical_coord_lvs; j++) {
118 CHECK_LT(arg_lvs_index, arg_lvs.size());
119 auto array_buff_lv = arg_lvs[arg_lvs_index++];
122 array_buff_lv = builder.CreateBitCast(
123 array_buff_lv, llvm::Type::getInt8PtrTy(cgen_state->context_));
126 array_buff_lv = builder.CreateBitCast(
127 array_buff_lv, llvm::Type::getInt32PtrTy(cgen_state->context_));
129 operand_lvs.push_back(array_buff_lv);
131 auto coords_array_type =
132 llvm::dyn_cast<llvm::PointerType>(operand_lvs.back()->getType());
133 CHECK(coords_array_type);
136 builder.CreateICmpEQ(operand_lvs.back(),
137 llvm::ConstantPointerNull::get(coords_array_type)));
139 is_coords_lv =
false;
140 CHECK_LT(arg_lvs_index, arg_lvs.size());
141 operand_lvs.push_back(arg_lvs[arg_lvs_index++]);
145 CHECK_EQ(arg_lvs_index, arg_lvs.size());
148 return std::make_tuple(operand_lvs, is_nullable_ ?
is_null :
nullptr);
151 std::vector<llvm::Value*>
codegen(
const std::vector<llvm::Value*>&
args,
155 const auto& first_operand_ti = getOperand(0)->get_type_info();
156 const auto& second_operand_ti = getOperand(1)->get_type_info();
158 const bool is_geodesic = first_operand_ti.get_subtype() ==
kGEOGRAPHY &&
159 first_operand_ti.get_output_srid() == 4326;
161 if (is_geodesic && !((first_operand_ti.get_type() ==
kPOINT &&
162 second_operand_ti.get_type() ==
kPOINT) ||
164 second_operand_ti.get_type() ==
kPOINT) ||
165 (first_operand_ti.get_type() ==
kPOINT &&
167 throw std::runtime_error(getName() +
168 " currently doesn't accept non-POINT geographies");
171 std::string func_name = getName() +
suffix(first_operand_ti.get_type()) +
172 suffix(second_operand_ti.get_type());
174 func_name +=
"_Geodesic";
176 auto& builder = cgen_state->ir_builder_;
178 std::vector<llvm::Value*> operand_lvs;
179 for (
size_t i = 0; i <
args.size(); i += 2) {
180 operand_lvs.push_back(
args[i]);
181 operand_lvs.push_back(
182 builder.CreateSExt(
args[i + 1], llvm::Type::getInt64Ty(cgen_state->context_)));
185 const auto& ret_ti = operator_->get_type_info();
187 operand_lvs.push_back(
189 operand_lvs.push_back(
190 cgen_state->llInt(first_operand_ti.get_input_srid()));
191 operand_lvs.push_back(cgen_state->llInt(
193 operand_lvs.push_back(
194 cgen_state->llInt(second_operand_ti.get_input_srid()));
195 const auto srid_override = operator_->getOutputSridOverride();
196 operand_lvs.push_back(
197 cgen_state->llInt(srid_override ? *srid_override : 0));
199 if (getName() ==
"ST_Distance" && first_operand_ti.get_subtype() !=
kGEOGRAPHY &&
200 (first_operand_ti.get_type() !=
kPOINT ||
201 second_operand_ti.get_type() !=
kPOINT)) {
202 operand_lvs.push_back(cgen_state->llFp(
double(0.0)));
206 auto ret = cgen_state->emitExternalCall(
207 func_name, llvm::Type::getDoubleTy(cgen_state->context_), operand_lvs);
209 CHECK(nullcheck_codegen);
210 ret = nullcheck_codegen->finalize(cgen_state->inlineFpNull(ret_ti), ret);
class for a per-database catalog. also includes metadata for the current database and the current use...
int32_t get_compression_scheme(const SQLTypeInfo &ti)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::string suffix(SQLTypes type)
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
CONSTEXPR DEVICE bool is_null(const T &value)
std::vector< llvm::Value * > codegen(const std::vector< llvm::Value * > &args, CodeGenerator::NullCheckCodegen *nullcheck_codegen, CgenState *cgen_state, const CompilationOptions &co) final
const SQLTypeInfo & get_type_info() const
Distance(const Analyzer::GeoOperator *geo_operator, const Catalog_Namespace::Catalog *catalog)
const Analyzer::GeoOperator * operator_
size_t size() const final
virtual const Analyzer::Expr * getOperand(const size_t index)
uint32_t log2_bytes(const uint32_t bytes)
SQLTypeInfo getNullType() const final