21 namespace spatial_type {
31 size_t size() const final {
return 2; }
36 const std::vector<llvm::Value*>& arg_lvs,
37 const std::vector<llvm::Value*>& pos_lvs,
40 std::string size_fn_name =
"array_size";
42 size_fn_name +=
"_nullable";
45 auto& builder = cgen_state->ir_builder_;
46 llvm::Value*
is_null = cgen_state->llBool(
false);
48 std::vector<llvm::Value*> operand_lvs;
49 size_t arg_lvs_index{0};
50 for (
size_t i = 0; i <
size(); i++) {
53 const auto& operand_ti = operand->get_type_info();
55 const size_t num_physical_coord_lvs = operand_ti.get_physical_coord_cols();
58 bool is_coords_lv{
true};
59 if (dynamic_cast<const Analyzer::ColumnVar*>(operand)) {
60 for (
size_t j = 0; j < num_physical_coord_lvs; j++) {
61 CHECK_LT(arg_lvs_index, arg_lvs.size());
62 auto lv = arg_lvs[arg_lvs_index++];
65 cgen_state->emitExternalCall(
"array_buff",
66 llvm::Type::getInt8PtrTy(cgen_state->context_),
68 auto const is_coords = (j == 0);
71 array_buff_lv = builder.CreateBitCast(
72 array_buff_lv, llvm::Type::getInt32PtrTy(cgen_state->context_));
74 operand_lvs.push_back(array_buff_lv);
76 const auto ptr_type = llvm::dyn_cast_or_null<llvm::PointerType>(lv->getType());
78 const auto elem_type = ptr_type->getPointerElementType();
80 auto const shift =
log2_bytes(is_coords ? 1 : 4);
81 std::vector<llvm::Value*> array_sz_args{
82 lv, pos_lvs[i], cgen_state->llInt(shift)};
85 array_sz_args.push_back(cgen_state->llInt(
86 static_cast<int32_t>(inline_int_null_value<int32_t>())));
88 operand_lvs.push_back(cgen_state->emitExternalCall(
89 size_fn_name,
get_int_type(32, cgen_state->context_), array_sz_args));
90 llvm::Value* operand_is_null_lv{
nullptr};
92 if (operand_ti.get_type() ==
kPOINT) {
93 operand_is_null_lv = cgen_state->emitExternalCall(
94 "point_coord_array_is_null",
95 llvm::Type::getInt1Ty(cgen_state->context_),
98 operand_is_null_lv = builder.CreateICmpEQ(
101 static_cast<int32_t>(inline_int_null_value<int32_t>())));
103 CHECK(operand_is_null_lv);
104 is_null = builder.CreateOr(is_null, operand_is_null_lv);
106 is_coords_lv =
false;
109 for (
size_t j = 0; j < num_physical_coord_lvs; j++) {
111 CHECK_LT(arg_lvs_index, arg_lvs.size());
112 auto array_buff_lv = arg_lvs[arg_lvs_index];
115 array_buff_lv = builder.CreateBitCast(
116 array_buff_lv, llvm::Type::getInt8PtrTy(cgen_state->context_));
119 array_buff_lv = builder.CreateBitCast(
120 array_buff_lv, llvm::Type::getInt32PtrTy(cgen_state->context_));
122 operand_lvs.push_back(array_buff_lv);
125 if (geo_oper && geo_oper->getName() ==
"ST_Point") {
129 cgen_state->emitCall(
"point_double_is_null", {arg_lvs[arg_lvs_index]});
132 auto coords_array_type =
133 llvm::dyn_cast<llvm::PointerType>(operand_lvs.back()->getType());
134 CHECK(coords_array_type);
137 builder.CreateICmpEQ(
139 llvm::ConstantPointerNull::get(coords_array_type)));
143 is_coords_lv =
false;
144 CHECK_LT(arg_lvs_index, arg_lvs.size());
145 operand_lvs.push_back(arg_lvs[arg_lvs_index++]);
149 CHECK_EQ(arg_lvs_index, arg_lvs.size());
152 return std::make_tuple(operand_lvs, is_nullable_ ?
is_null :
nullptr);
155 std::vector<llvm::Value*>
codegen(
const std::vector<llvm::Value*>&
args,
159 const auto& first_operand_ti = getOperand(0)->get_type_info();
160 const auto& second_operand_ti = getOperand(1)->get_type_info();
162 const bool is_geodesic = first_operand_ti.get_subtype() ==
kGEOGRAPHY &&
163 first_operand_ti.get_output_srid() == 4326;
165 if (is_geodesic && !((first_operand_ti.get_type() ==
kPOINT &&
166 second_operand_ti.get_type() ==
kPOINT) ||
168 second_operand_ti.get_type() ==
kPOINT) ||
169 (first_operand_ti.get_type() ==
kPOINT &&
171 throw std::runtime_error(getName() +
172 " currently doesn't accept non-POINT geographies");
175 bool unsupported_args =
false;
177 unsupported_args = (second_operand_ti.get_type() !=
kPOINT);
179 unsupported_args = (first_operand_ti.get_type() !=
kPOINT);
181 if (unsupported_args) {
182 throw std::runtime_error(getName() +
183 " currently doesn't support this argument combination");
186 std::string func_name = getName() +
suffix(first_operand_ti.get_type()) +
187 suffix(second_operand_ti.get_type());
189 func_name +=
"_Geodesic";
191 auto& builder = cgen_state->ir_builder_;
193 std::vector<llvm::Value*> operand_lvs;
194 for (
size_t i = 0; i <
args.size(); i += 2) {
195 operand_lvs.push_back(
args[i]);
196 operand_lvs.push_back(
197 builder.CreateSExt(
args[i + 1], llvm::Type::getInt64Ty(cgen_state->context_)));
200 const auto& ret_ti = operator_->get_type_info();
202 operand_lvs.push_back(
204 operand_lvs.push_back(
205 cgen_state->llInt(first_operand_ti.get_input_srid()));
206 operand_lvs.push_back(cgen_state->llInt(
208 operand_lvs.push_back(
209 cgen_state->llInt(second_operand_ti.get_input_srid()));
210 const auto srid_override = operator_->getOutputSridOverride();
211 operand_lvs.push_back(
212 cgen_state->llInt(srid_override ? *srid_override : 0));
214 if (getName() ==
"ST_Distance" && first_operand_ti.get_subtype() !=
kGEOGRAPHY &&
215 (first_operand_ti.get_type() !=
kPOINT ||
216 second_operand_ti.get_type() !=
kPOINT)) {
217 operand_lvs.push_back(cgen_state->llFp(
double(0.0)));
221 auto ret = cgen_state->emitExternalCall(
222 func_name, llvm::Type::getDoubleTy(cgen_state->context_), operand_lvs);
224 CHECK(nullcheck_codegen);
225 ret = nullcheck_codegen->finalize(cgen_state->inlineFpNull(ret_ti), ret);
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
const Analyzer::GeoOperator * operator_
Distance(const Analyzer::GeoOperator *geo_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