31 const bool with_bounds,
32 const bool with_render_group,
33 const bool expand_geo_col)
const {
34 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
38 const int rte_idx = it_rte_idx->second;
39 const auto& in_metainfo = source->getOutputMetainfo();
43 const auto scan_source =
dynamic_cast<const RelScan*
>(source);
47 CHECK(in_metainfo.empty());
49 const auto td = scan_source->getTableDescriptor();
50 table_id = td->tableId;
55 column_id = gcd->columnId;
60 table_id = -source->getId();
62 if (with_bounds || with_render_group) {
64 "Geospatial columns not yet supported in intermediate results.");
67 CHECK(!in_metainfo.empty());
70 CHECK_LT(static_cast<size_t>(column_id), in_metainfo.size());
71 ti = in_metainfo[column_id].get_type_info();
72 if (expand_geo_col && ti.is_geometry()) {
74 "Geospatial columns not yet supported in this temporary table context.");
80 "Geospatial expression and operator require geospatial column as their input "
92 args.push_back(std::make_shared<Analyzer::ColumnVar>(
93 pcol_ti, table_id, pcd->columnId, rte_idx));
97 std::make_shared<Analyzer::ColumnVar>(ti, table_id, column_id, rte_idx));
105 args.push_back(std::make_shared<Analyzer::ColumnVar>(
106 bounds_ti, table_id, bounds_cd->columnId, rte_idx));
113 auto render_group_ti = render_group_cd->
columnType;
114 args.push_back(std::make_shared<Analyzer::ColumnVar>(
115 render_group_ti, table_id, render_group_cd->columnId, rte_idx));
121 const RexLiteral* rex_literal,
123 bool with_bounds)
const {
125 if (rex_literal->getType() !=
kTEXT) {
126 throw std::runtime_error(
"Geo literals must be strings");
133 std::vector<double> coords;
134 std::vector<double> bounds;
135 std::vector<int> ring_sizes;
136 std::vector<int> poly_rings;
139 *wkt->get_constval().stringval, ti, coords, bounds, ring_sizes, poly_rings)) {
151 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
154 std::list<std::shared_ptr<Analyzer::Expr>> compressed_coords_exprs;
155 for (
auto cc : compressed_coords) {
158 auto e = makeExpr<Analyzer::Constant>(
kTINYINT,
false, d);
159 compressed_coords_exprs.push_back(e);
163 arr_ti.
set_size(compressed_coords.size() *
sizeof(int8_t));
166 args.push_back(makeExpr<Analyzer::Constant>(arr_ti,
false, compressed_coords_exprs));
171 std::list<std::shared_ptr<Analyzer::Expr>> ring_size_exprs;
172 for (
auto c : ring_sizes) {
175 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
176 ring_size_exprs.push_back(e);
180 arr_ti.
set_size(ring_sizes.size() *
sizeof(int32_t));
181 args.push_back(makeExpr<Analyzer::Constant>(arr_ti,
false, ring_size_exprs));
185 std::list<std::shared_ptr<Analyzer::Expr>> poly_rings_exprs;
186 for (
auto c : poly_rings) {
189 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
190 poly_rings_exprs.push_back(e);
194 arr_ti.
set_size(poly_rings.size() *
sizeof(int32_t));
195 args.push_back(makeExpr<Analyzer::Constant>(arr_ti,
false, poly_rings_exprs));
201 std::list<std::shared_ptr<Analyzer::Expr>> bounds_exprs;
202 for (
auto b : bounds) {
205 auto e = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
206 bounds_exprs.push_back(e);
210 arr_ti.
set_size(bounds.size() *
sizeof(double));
211 args.push_back(makeExpr<Analyzer::Constant>(arr_ti,
false, bounds_exprs));
221 return std::string(
"_Point");
224 return std::string(
"_MultiPoint");
227 return std::string(
"_LineString");
230 return std::string(
"_MultiLineString");
233 return std::string(
"_Polygon");
236 return std::string(
"_MultiPolygon");
273 const bool with_bounds,
274 const bool with_render_group,
275 const bool expand_geo_col,
277 const bool use_geo_expressions,
278 const bool try_to_compress,
279 const bool allow_gdal_transforms)
const {
280 std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
282 const auto rex_input =
dynamic_cast<const RexInput*
>(rex_scalar);
286 if (!column || !column->get_type_info().is_geometry()) {
289 if (use_geo_expressions) {
290 arg_ti = column->get_type_info();
291 return {makeExpr<Analyzer::GeoColumnVar>(column, with_bounds, with_render_group)};
294 rex_input, arg_ti, with_bounds, with_render_group, expand_geo_col);
298 if (rex_function->getName() ==
"ST_Transform"sv) {
299 CHECK_EQ(
size_t(2), rex_function->size());
300 const auto rex_scalar0 =
301 dynamic_cast<const RexScalar*
>(rex_function->getOperand(0));
303 throw QueryNotSupported(rex_function->getName() +
": unexpected first argument");
306 const auto rex_literal =
307 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(1));
310 ": second argument is expected to be a literal");
314 if (!ce || !e->get_type_info().is_integer()) {
318 if (e->get_type_info().get_type() ==
kSMALLINT) {
319 srid =
static_cast<int32_t
>(ce->get_constval().smallintval);
320 }
else if (e->get_type_info().get_type() ==
kTINYINT) {
321 srid =
static_cast<int32_t
>(ce->get_constval().tinyintval);
322 }
else if (e->get_type_info().get_type() ==
kINT) {
323 srid =
static_cast<int32_t
>(ce->get_constval().intval);
327 bool allow_result_gdal_transform =
false;
329 if (rex_function0 &&
func_resolve(rex_function0->getName(),
335 "ST_ConvexHull"sv)) {
346 if (!allow_gdal_transforms && !allow_result_gdal_transform) {
347 if (srid != 900913 && ((use_geo_expressions || is_projection) && srid != 4326 &&
354 bool arg0_use_geo_expressions = is_projection ?
true : use_geo_expressions;
355 if (allow_gdal_transforms) {
356 arg0_use_geo_expressions =
false;
364 arg0_use_geo_expressions);
366 if (use_geo_expressions) {
368 auto arg0_ti = arg0.front()->get_type_info();
369 arg0_ti.set_output_srid(srid);
370 if (arg0_ti.get_type() ==
kPOINT) {
373 const auto input_srid = arg0_ti.get_input_srid();
374 arg0_ti.set_input_srid(srid);
377 arg0_ti.set_comp_param(0);
382 return {makeExpr<Analyzer::GeoTransformOperator>(
383 arg0_ti, rex_function->getName(), arg0, input_srid, srid)};
385 if (
auto geo_constant =
386 std::dynamic_pointer_cast<Analyzer::GeoConstant>(arg0.front())) {
388 auto cast_geo_constant = geo_constant->add_cast(arg0_ti);
390 arg_ti = cast_geo_constant->get_type_info();
391 return {cast_geo_constant};
392 }
else if (
auto col_var =
393 std::dynamic_pointer_cast<Analyzer::ColumnVar>(arg0.front())) {
394 const auto& col_ti = col_var->get_type_info();
395 CHECK(col_ti.is_geometry());
396 if (col_ti.get_type() !=
kPOINT) {
401 if (!allow_gdal_transforms && !allow_result_gdal_transform) {
402 throw std::runtime_error(
403 "Transform on non-POINT geospatial types not yet supported in this "
411 if (!allow_gdal_transforms && !allow_result_gdal_transform) {
414 ": unsupported input SRID " +
419 if (allow_result_gdal_transform) {
429 ": unexpected input SRID, unable to transform");
433 rex_function->getName(),
"ST_GeomFromText"sv,
"ST_GeogFromText"sv)) {
434 CHECK(rex_function->size() == size_t(1) || rex_function->size() == size_t(2));
435 if (use_geo_expressions) {
437 if (rex_function->size() == 2) {
439 const auto rex_literal =
440 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(1));
443 ": second argument is expected to be a literal");
447 if (!ce || !e->get_type_info().is_integer()) {
450 if (e->get_type_info().get_type() ==
kSMALLINT) {
451 srid =
static_cast<int32_t
>(ce->get_constval().smallintval);
452 }
else if (e->get_type_info().get_type() ==
kTINYINT) {
453 srid =
static_cast<int32_t
>(ce->get_constval().tinyintval);
454 }
else if (e->get_type_info().get_type() ==
kINT) {
455 srid =
static_cast<int32_t
>(ce->get_constval().intval);
459 if (srid != 0 && srid != 4326 && srid != 900913) {
467 if (rex_function->getName() ==
"ST_GeogFromText"sv) {
479 use_geo_expressions);
480 CHECK_GE(func_args.size(), size_t(1));
486 if (rex_function->size() == 2) {
487 const auto rex_literal =
488 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(1));
491 ": second argument is expected to be a literal");
495 if (!ce || !e->get_type_info().is_integer()) {
498 if (e->get_type_info().get_type() ==
kSMALLINT) {
499 srid =
static_cast<int32_t
>(ce->get_constval().smallintval);
500 }
else if (e->get_type_info().get_type() ==
kTINYINT) {
501 srid =
static_cast<int32_t
>(ce->get_constval().tinyintval);
502 }
else if (e->get_type_info().get_type() ==
kINT) {
503 srid =
static_cast<int32_t
>(ce->get_constval().intval);
507 if (srid != 0 && srid != 4326 && srid != 900913) {
515 const auto rex_literal =
516 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(0));
519 " expects a string literal as first argument");
525 }
else if (rex_function->getName() ==
"ST_PointN"sv) {
527 const auto rex_scalar0 =
528 dynamic_cast<const RexScalar*
>(rex_function->getOperand(0));
531 ": expects scalar as first argument");
542 if (arg0.front()->get_type_info().get_type() !=
kLINESTRING) {
544 " expects LINESTRING as first argument");
546 const auto rex_literal =
547 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(1));
550 ": second argument is expected to be a literal");
554 if (!ce || !e->get_type_info().is_integer()) {
556 ": expecting integer index as second argument");
559 if (e->get_type_info().get_type() ==
kSMALLINT) {
560 index =
static_cast<int32_t
>(ce->get_constval().smallintval);
561 }
else if (e->get_type_info().get_type() ==
kTINYINT) {
562 index =
static_cast<int32_t
>(ce->get_constval().tinyintval);
563 }
else if (e->get_type_info().get_type() ==
kINT) {
564 index =
static_cast<int32_t
>(ce->get_constval().intval);
574 arg0.front()->get_type_info();
576 oper_ti.set_notnull(
false);
580 return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(), arg0)};
582 }
else if (rex_function->getName() ==
"ST_StartPoint"sv ||
583 rex_function->getName() ==
"ST_EndPoint"sv) {
584 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
585 CHECK_EQ(
size_t(1), rex_function->size());
593 CHECK_EQ(arg_exprs.size(), size_t(1));
594 CHECK(arg_exprs.front());
595 const auto arg_expr_ti = arg_exprs.front()->get_type_info();
598 " expected LINESTRING argument. Received " +
599 arg_expr_ti.toString());
601 args.push_back(arg_exprs.front());
603 auto oper_ti = args.back()->get_type_info();
608 return {makeExpr<Analyzer::GeoOperator>(oper_ti, rex_function->getName(),
args)};
609 }
else if (rex_function->getName() ==
"ST_SRID"sv) {
610 CHECK_EQ(
size_t(1), rex_function->size());
611 const auto rex_scalar0 =
612 dynamic_cast<const RexScalar*
>(rex_function->getOperand(0));
615 ": expects scalar as first argument");
618 rex_scalar0, arg_ti, with_bounds, with_render_group, expand_geo_col);
623 }
else if (rex_function->getName() ==
"ST_SetSRID"sv) {
624 CHECK_EQ(
size_t(2), rex_function->size());
625 const auto rex_literal =
626 dynamic_cast<const RexLiteral*
>(rex_function->getOperand(1));
629 ": second argument is expected to be a literal");
633 if (!ce || !e->get_type_info().is_integer()) {
637 if (e->get_type_info().get_type() ==
kSMALLINT) {
638 srid =
static_cast<int32_t
>(ce->get_constval().smallintval);
639 }
else if (e->get_type_info().get_type() ==
kTINYINT) {
640 srid =
static_cast<int32_t
>(ce->get_constval().tinyintval);
641 }
else if (e->get_type_info().get_type() ==
kINT) {
642 srid =
static_cast<int32_t
>(ce->get_constval().intval);
647 const auto rex_scalar0 =
648 dynamic_cast<const RexScalar*
>(rex_function->getOperand(0));
651 ": expects scalar as first argument");
662 (try_to_compress && (srid == 4326)));
664 CHECK(!arg0.empty() && arg0.front());
670 if (
auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
672 auto ti = geo_expr->get_type_info();
673 ti.set_input_srid(srid);
674 ti.set_output_srid(srid);
675 return {geo_expr->add_cast(ti)};
678 }
else if (rex_function->getName() ==
"CastToGeography"sv) {
679 CHECK_EQ(
size_t(1), rex_function->size());
680 const auto rex_scalar0 =
681 dynamic_cast<const RexScalar*
>(rex_function->getOperand(0));
684 ": expects scalar as first argument");
692 use_geo_expressions);
693 CHECK(!arg0.empty());
694 if (
auto geo_expr = std::dynamic_pointer_cast<Analyzer::GeoExpr>(arg0.front())) {
695 auto arg_ti = geo_expr->get_type_info();
697 return {geo_expr->add_cast(arg_ti)};
699 if (use_geo_expressions) {
700 arg_ti = arg0.front()->get_type_info();
702 arg0.front()->set_type_info(arg_ti);
709 " expects geometry with SRID=4326");
713 }
else if (rex_function->getName() ==
"ST_Point"sv) {
714 CHECK_EQ(
size_t(2), rex_function->size());
724 auto cast_coord1 = coord1->add_cast(d_ti);
725 auto cast_coord2 = coord2->add_cast(d_ti);
727 auto fold1 =
fold_expr(cast_coord1.get());
728 auto fold2 =
fold_expr(cast_coord2.get());
731 if (const_coord1 && const_coord2 && !use_geo_expressions) {
732 CHECK(const_coord1->get_type_info().get_type() ==
kDOUBLE);
733 CHECK(const_coord2->get_type_info().get_type() ==
kDOUBLE);
734 std::string wkt =
"POINT(" +
737 RexLiteral rex_literal{wkt,
kTEXT,
kNULLT, 0, 0, 0, 0};
743 if (!is_local_alloca || use_geo_expressions) {
744 if (try_to_compress) {
748 return {makeExpr<Analyzer::GeoOperator>(
750 rex_function->getName(),
751 std::vector<std::shared_ptr<Analyzer::Expr>>{cast_coord1, cast_coord2})};
757 if (try_to_compress) {
759 da_ti.set_subtype(
kINT);
761 da_ti.set_input_srid(4326);
762 da_ti.set_output_srid(4326);
764 da_ti.set_comp_param(32);
771 auto cast_coords = {cast_coord1, cast_coord2};
772 auto ae = makeExpr<Analyzer::ArrayExpr>(da_ti, cast_coords,
false, is_local_alloca);
775 return {makeExpr<Analyzer::UOper>(tia_ti,
false,
kCAST, ae)};
776 }
else if (rex_function->getName() ==
"ST_Centroid"sv) {
777 CHECK_EQ(
size_t(1), rex_function->size());
785 int legacy_transform_srid = 0;
793 CHECK_EQ(geoargs.size(), size_t(1));
799 if (try_to_compress) {
818 return {makeExpr<Analyzer::GeoOperator>(
820 rex_function->getName(),
821 std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()},
822 legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
824 }
else if (
func_resolve(rex_function->getName(),
"ST_ConvexHull"sv)) {
825 CHECK_EQ(
size_t(1), rex_function->size());
833 "ST_ConcaveHull"sv)) {
834 CHECK_EQ(
size_t(2), rex_function->size());
837 }
else if (
func_resolve(rex_function->getName(),
"ST_IsEmpty"sv,
"ST_IsValid"sv)) {
838 CHECK_EQ(
size_t(1), rex_function->size());
840 }
else if (
func_resolve(rex_function->getName(),
"ST_Equals"sv)) {
841 CHECK_EQ(
size_t(2), rex_function->size());
847 const auto rex_literal =
dynamic_cast<const RexLiteral*
>(rex_scalar);
849 if (use_geo_expressions) {
851 const auto constant_expr =
853 CHECK(constant_expr);
854 if (constant_expr->get_is_null()) {
858 const auto& datum = constant_expr->get_constval();
859 CHECK(datum.stringval);
861 CHECK(geospatial_base);
885 return {makeExpr<Analyzer::GeoConstant>(std::move(geospatial_base), ti)};
895 const bool with_bounds)
const {
898 const bool use_geo_projections = !(rex_function->
getName() ==
"ST_GeomFromText" ||
899 rex_function->
getName() ==
"ST_GeogFromText" ||
900 rex_function->
getName() ==
"ST_SetSRID");
907 use_geo_projections);
908 CHECK(!geoargs.empty());
909 if (std::dynamic_pointer_cast<const Analyzer::GeoExpr>(geoargs.front()) &&
910 !geoargs.front()->get_type_info().is_array()) {
912 return geoargs.front();
914 bool allow_gdal_transform =
false;
915 if (rex_function->
getName() ==
"ST_Transform") {
918 if (rex_function0 &&
func_resolve(rex_function0->getName(),
924 "ST_ConvexHull"sv)) {
926 allow_gdal_transform =
true;
929 if (use_geo_projections && !allow_gdal_transform) {
930 throw std::runtime_error(
"Geospatial projection for function " +
932 " not yet supported in this context");
934 return makeExpr<Analyzer::GeoUOper>(
941 const bool with_bounds)
const {
944 " geo constructor requires enabled GEOS support");
947 if (rex_function->
getName() ==
"ST_Difference"sv) {
949 }
else if (rex_function->
getName() ==
"ST_Union"sv) {
951 }
else if (rex_function->
getName() ==
"ST_Buffer"sv) {
953 }
else if (rex_function->
getName() ==
"ST_ConcaveHull"sv) {
966 "ST_ConcaveHull"sv)) {
994 " geo constructor requires arguments with matching srids");
1000 if (param_expr->get_type_info().get_type() !=
kDOUBLE) {
1001 param_expr = param_expr->add_cast(arg1_ti);
1003 geoargs1 = {param_expr};
1021 " requires its argument(s) to have a valid srid");
1030 return makeExpr<Analyzer::GeoBinOper>(op, arg_ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1036 const bool with_bounds)
const {
1039 " geo predicate requires enabled GEOS support");
1043 rex_function->
getOperand(0), arg_ti,
false,
false,
true,
true);
1045 auto op = (rex_function->
getName() ==
"ST_IsEmpty"sv)
1048 return makeExpr<Analyzer::GeoUOper>(op, ti, arg_ti, geoargs);
1054 const bool with_bounds)
const {
1055 if (rex_function->
getName() !=
"ST_Equals"sv) {
1060 " geo predicate requires enabled GEOS support");
1064 rex_function->
getOperand(0), arg0_ti,
false,
false,
true,
true);
1067 rex_function->
getOperand(1), arg1_ti,
false,
false,
true,
true);
1070 return makeExpr<Analyzer::GeoBinOper>(op, ti, arg0_ti, arg1_ti, geoargs0, geoargs1);
1076 const bool with_bounds)
const {
1079 " geo constructor requires enabled GEOS support");
1113 " requires its argument(s) to have a valid srid");
1122 return makeExpr<Analyzer::GeoUOper>(op, arg_ti, arg0_ti, geoargs0);
1129 std::string specialized_geofunc{rex_function->
getName()};
1133 if (rex_function->
getName() ==
"ST_NRings"sv) {
1144 " expects a POLYGON or MULTIPOLYGON");
1146 CHECK_EQ(geoargs.size(), size_t(1));
1147 arg_ti = rex_function->
getType();
1148 return makeExpr<Analyzer::GeoOperator>(
1151 std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
1152 }
else if (rex_function->
getName() ==
"ST_NPoints"sv) {
1161 CHECK_EQ(geoargs.size(), size_t(1));
1162 return makeExpr<Analyzer::GeoOperator>(
1165 std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()});
1168 int legacy_transform_srid = 0;
1176 CHECK_EQ(geoargs.size(), size_t(1));
1183 arg_ti = geoargs.front()->get_type_info();
1187 " expects a POLYGON or MULTIPOLYGON");
1189 return makeExpr<Analyzer::GeoOperator>(
1192 std::vector<std::shared_ptr<Analyzer::Expr>>{geoargs.front()},
1193 legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1206 " expects a POLYGON or MULTIPOLYGON");
1209 geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1211 return makeExpr<Analyzer::FunctionOper>(
1212 rex_function->
getType(), specialized_geofunc, geoargs);
1221 " expects a POLYGON or MULTIPOLYGON");
1224 geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1226 return makeExpr<Analyzer::FunctionOper>(
1227 rex_function->
getType(), specialized_geofunc, geoargs);
1241 CHECK_EQ(new_geoargs.size(), size_t(1));
1242 CHECK(new_geoargs.front());
1243 const auto& arg_expr_ti = new_geoargs.front()->get_type_info();
1244 if (arg_expr_ti.get_type() !=
kPOINT) {
1247 auto function_ti = rex_function->
getType();
1248 if (std::dynamic_pointer_cast<Analyzer::GeoOperator>(new_geoargs.front())) {
1251 if (std::dynamic_pointer_cast<Analyzer::GeoConstant>(new_geoargs.front())) {
1253 function_ti.set_notnull(
true);
1255 return makeExpr<Analyzer::GeoOperator>(
1258 std::vector<std::shared_ptr<Analyzer::Expr>>{new_geoargs.front()});
1263 bool with_bounds =
true;
1265 rex_function->
getOperand(0), arg_ti, with_bounds,
false,
false);
1267 if (rex_function->
getName() ==
"ST_SRID"sv) {
1270 return makeExpr<Analyzer::Constant>(
kINT,
false, output_srid);
1274 rex_function->
getName(),
"ST_XMin"sv,
"ST_YMin"sv,
"ST_XMax"sv,
"ST_YMax"sv)) {
1278 geoargs.erase(geoargs.begin(), geoargs.end() - 1);
1283 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid));
1286 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, output_srid));
1288 specialized_geofunc +=
"_Bounds"s;
1289 return makeExpr<Analyzer::FunctionOper>(
1290 rex_function->
getType(), specialized_geofunc, geoargs);
1296 auto discard_after_arg = 1;
1298 if (rex_function->
getName() ==
"ST_Length"sv) {
1301 " expects LINESTRING or MULTILINESTRING");
1304 auto ti0 = geoargs[0]->get_type_info();
1307 discard_after_arg = 2;
1314 " Geodesic is not supported for MULTILINESTRING");
1316 specialized_geofunc +=
"_Geodesic"s;
1320 geoargs.erase(geoargs.begin() + discard_after_arg, geoargs.end());
1324 Datum input_compression;
1326 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression));
1329 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid));
1334 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, output_srid));
1336 return makeExpr<Analyzer::FunctionOper>(
1337 rex_function->
getType(), specialized_geofunc, geoargs);
1342 auto function_name = rex_function->
getName();
1343 auto return_type = rex_function->
getType();
1345 if (function_name ==
"ST_Overlaps"sv) {
1348 auto extract_geo_bounds_from_input =
1349 [
this, &rex_function](
const size_t index) -> std::shared_ptr<Analyzer::Expr> {
1350 const auto rex_input =
1357 throw std::runtime_error(
"ST_Overlaps is not supported for point arguments.");
1359 return exprs.back();
1362 throw std::runtime_error(
1363 "Only inputs are supported as arguments to ST_Overlaps for now.");
1366 std::vector<std::shared_ptr<Analyzer::Expr>> geo_args;
1367 geo_args.push_back(extract_geo_bounds_from_input(0));
1368 geo_args.push_back(extract_geo_bounds_from_input(1));
1370 return makeExpr<Analyzer::FunctionOper>(return_type, function_name, geo_args);
1373 if (function_name ==
"ST_Distance"sv || function_name ==
"ST_MaxDistance"sv) {
1375 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
1376 int legacy_transform_srid = 0;
1377 for (
size_t i = 0; i < rex_function->
size(); i++) {
1390 CHECK(legacy_transform_srid == 0 ||
1394 args.insert(args.end(), geoargs.begin(), geoargs.end());
1396 return makeExpr<Analyzer::GeoOperator>(
1400 legacy_transform_srid > 0 ? std::make_optional<int>(legacy_transform_srid)
1404 bool swap_args =
false;
1405 bool with_bounds =
false;
1406 bool negate_result =
false;
1409 if (function_name ==
"ST_DWithin"sv) {
1411 function_name =
"ST_Distance";
1415 }
else if (function_name ==
"ST_Equals"sv) {
1418 function_name =
"ST_Distance";
1420 threshold_expr =
nullptr;
1423 compare_expr = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
1424 }
else if (function_name ==
"ST_DFullyWithin"sv) {
1426 function_name =
"ST_MaxDistance";
1429 threshold_expr =
nullptr;
1430 }
else if (function_name ==
"ST_Distance"sv) {
1432 threshold_expr =
nullptr;
1433 }
else if (function_name ==
"ST_MaxDistance"sv) {
1436 threshold_expr =
nullptr;
1440 if (function_name ==
"ST_Within"sv) {
1441 function_name =
"ST_Contains";
1443 }
else if (function_name ==
"ST_Disjoint"sv) {
1444 function_name =
"ST_Intersects";
1445 negate_result =
true;
1448 function_name,
"ST_Contains"sv,
"ST_Intersects"sv,
"ST_Approx_Overlaps"sv)) {
1452 std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1467 try_to_compress_arg0);
1468 geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1472 bool try_to_compress_arg1 =
1474 func_resolve(function_name,
"ST_Contains"sv,
"ST_Intersects"sv) &&
1485 try_to_compress_arg1);
1486 geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1490 " accepts either two GEOGRAPHY or two GEOMETRY arguments");
1519 threshold_expr = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, tolerance);
1520 compare_expr = threshold_expr;
1524 " unable to calculate compression tolerance for arguments");
1530 " currently doesn't support this argument combination");
1533 auto can_use_compressed_coords = [](
const SQLTypeInfo& i0_ti,
1537 const bool i0_is_poly =
1539 const bool i1_is_point = i1_ti.get_type() ==
kPOINT;
1540 const bool i1_is_literal =
1542 i1_operands.front()) !=
nullptr;
1543 return (i0_is_poly && !i1_is_literal && i1_is_point &&
1547 i1_ti.get_input_srid() == i1_ti.get_output_srid());
1550 if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1552 function_name =
"ST_cContains";
1556 if (can_use_compressed_coords(arg0_ti, geoargs0, arg1_ti, geoargs1)) {
1558 function_name =
"ST_cIntersects";
1559 }
else if (can_use_compressed_coords(arg1_ti, geoargs1, arg0_ti, geoargs0)) {
1561 function_name =
"ST_cIntersects";
1563 geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1564 geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1565 auto tmp_ti = arg0_ti;
1571 std::string specialized_geofunc{function_name +
suffix(arg0_ti.
get_type()) +
1576 if (function_name ==
"ST_Distance"sv) {
1581 specialized_geofunc +=
"_Geodesic"s;
1584 " currently doesn't accept non-POINT geographies");
1586 }
else if (rex_function->
getName() ==
"ST_Contains"sv) {
1592 }
else if (function_name ==
"ST_Distance"sv && rex_function->
size() == 3) {
1595 specialized_geofunc +=
"_Squared"s;
1601 Datum input_compression0;
1603 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression0));
1606 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid0));
1610 Datum input_compression1;
1612 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression1));
1615 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid1));
1620 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, output_srid));
1630 if (threshold_expr) {
1631 if (threshold_expr->get_type_info().get_type() !=
kDOUBLE) {
1633 threshold_expr = threshold_expr->add_cast(threshold_ti);
1635 threshold_expr =
fold_expr(threshold_expr.get());
1639 threshold_expr = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
1641 geoargs.push_back(threshold_expr);
1645 makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1646 if (negate_result) {
1661 if (distance_expr->get_type_info().get_type() !=
kDOUBLE) {
1662 distance_expr = distance_expr->add_cast(distance_ti);
1665 auto function_name = rex_function->
getName();
1666 if (function_name ==
"ST_DWithin"sv) {
1667 auto return_type = rex_function->
getType();
1668 bool swap_args =
false;
1669 bool with_bounds =
true;
1674 rex_function->
getOperand(0), arg0_ti, with_bounds,
false,
false);
1676 rex_function->
getOperand(1), arg1_ti, with_bounds,
false,
false);
1679 " cannot accept mixed GEOMETRY/GEOGRAPHY arguments");
1681 auto is_geodesic =
false;
1688 " in geodesic form can only accept POINT GEOGRAPHY arguments");
1706 Datum input_compression0;
1713 Datum input_compression1;
1722 std::string specialized_geofunc{function_name};
1723 std::vector<std::shared_ptr<Analyzer::Expr>> geoargs;
1726 geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1727 geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1728 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression1));
1729 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid1));
1730 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression0));
1731 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid0));
1735 specialized_geofunc +=
"_Geodesic"s;
1737 geoargs.insert(geoargs.end(), geoargs0.begin(), geoargs0.end());
1738 geoargs.insert(geoargs.end(), geoargs1.begin(), geoargs1.end());
1739 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression0));
1740 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid0));
1741 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression1));
1742 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid1));
1744 geoargs.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, output_srid));
1746 geoargs.push_back(distance_expr);
1749 makeExpr<Analyzer::FunctionOper>(return_type, specialized_geofunc, geoargs);
1757 return makeExpr<Analyzer::BinOper>(
kBOOLEAN,
kLE,
kONE, geo_distance, distance_expr);
1762 if (rex_operator->
size() != size_t(2)) {
1768 if (func_oper && func_oper->getName() ==
"ST_Distance"sv) {
1771 if (distance_expr->get_type_info().get_type() !=
kDOUBLE) {
1772 distance_expr = distance_expr->add_cast(distance_ti);
1774 distance_expr =
fold_expr(distance_expr.get());
1775 return makeExpr<Analyzer::BinOper>(
1783 std::string specialized_geofunc{rex_function->
getName()};
1785 "convert_meters_to_pixel_width"sv,
1786 "convert_meters_to_pixel_height"sv)) {
1789 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
1794 if (arg_ti.get_type() !=
kPOINT) {
1796 " expects a point for the second argument");
1799 args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1802 Datum input_compression;
1804 args.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression));
1805 if (arg_ti.get_input_srid() != 4326) {
1808 " currently only supports points of with SRID WGS84/EPSG:4326");
1811 input_srid.
intval = arg_ti.get_input_srid();
1812 args.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_srid));
1817 arg_ti.get_output_srid() != 900913 ? 900913 : arg_ti.get_output_srid();
1818 args.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, output_srid));
1824 return makeExpr<Analyzer::FunctionOper>(
1825 rex_function->
getType(), specialized_geofunc,
args);
1826 }
else if (rex_function->
getName() ==
"is_point_in_view"sv) {
1829 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
1833 if (arg_ti.get_type() !=
kPOINT) {
1835 " expects a point for the second argument");
1838 args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1841 Datum input_compression;
1843 args.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression));
1844 if (arg_ti.get_input_srid() != 4326) {
1847 " currently only supports points of with SRID WGS84/EPSG:4326");
1853 return makeExpr<Analyzer::FunctionOper>(
1854 rex_function->
getType(), specialized_geofunc,
args);
1855 }
else if (rex_function->
getName() ==
"is_point_size_in_view"sv) {
1858 std::vector<std::shared_ptr<Analyzer::Expr>>
args;
1862 if (arg_ti.get_type() !=
kPOINT) {
1864 " expects a point for the second argument");
1867 args.insert(args.end(), geoargs.begin(), geoargs.begin() + 1);
1870 Datum input_compression;
1872 args.push_back(makeExpr<Analyzer::Constant>(
kINT,
false, input_compression));
1873 if (arg_ti.get_input_srid() != 4326) {
1876 " currently only supports points of with SRID WGS84/EPSG:4326");
1883 return makeExpr<Analyzer::FunctionOper>(
1884 rex_function->
getType(), specialized_geofunc,
args);
1894 auto translate_input =
1895 [&](
const RexScalar* operand) -> std::shared_ptr<Analyzer::Expr> {
1896 const auto input =
dynamic_cast<const RexInput*
>(operand);
1903 return exprs.front();
1905 return exprs.back();
1915 translate_input(rex_operator->
getOperand(1)),
1916 translate_input(rex_operator->
getOperand(0)));
HOST DEVICE SQLTypes get_subtype() const
void set_compression(EncodingType c)
static std::unique_ptr< GeoBase > createGeoType(const std::string &wkt_or_wkb_hex)
std::shared_ptr< Analyzer::Expr > translateBinaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoFunctionArg(const RexScalar *rex_scalar, SQLTypeInfo &arg_ti, const bool with_bounds, const bool with_render_group, const bool expand_geo_col, const bool is_projection=false, const bool use_geo_expressions=false, const bool try_to_compress=false, const bool allow_gdal_transforms=false) const
#define SPIMAP_GEO_PHYSICAL_INPUT(c, i)
std::shared_ptr< Analyzer::Expr > translateScalarRex(const RexScalar *rex) const
const SQLTypeInfo & getType() const
const RexScalar * getOperand(const size_t idx) const
int32_t get_compression_scheme(const SQLTypeInfo &ti)
HOST DEVICE void set_subtype(SQLTypes st)
std::shared_ptr< Analyzer::Expr > ExpressionPtr
bool g_enable_geo_ops_on_uncompressed_coords
HOST DEVICE SQLTypes get_type() const
std::shared_ptr< Analyzer::Expr > translateGeoProjection(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
#define TOLERANCE_GEOINT32
std::string suffix(SQLTypes type)
std::shared_ptr< Analyzer::Expr > translateInput(const RexInput *) const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoFunction(const RexFunctionOperator *) const
bool has_render_group() const
std::shared_ptr< Analyzer::Expr > translateGeoOverlapsOper(const RexOperator *) const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoLiteral(const RexLiteral *, SQLTypeInfo &, bool) const
void set_input_srid(int d)
std::vector< uint8_t > compress_coords(const std::vector< double > &coords, const SQLTypeInfo &ti)
static std::shared_ptr< Analyzer::Expr > translateLiteral(const RexLiteral *)
SQLOps getOperator() const
const ColumnDescriptor * getMetadataForColumnBySpi(const int tableId, const size_t spi) const
void set_output_srid(int s)
const std::unordered_map< const RelAlgNode *, int > input_to_nest_level_
void set_comp_param(int p)
static bool getGeoColumns(const std::string &wkt_or_wkb_hex, SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool promote_poly_to_mpoly=false)
std::shared_ptr< Analyzer::Expr > translateUnaryGeoPredicate(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
HOST DEVICE EncodingType get_compression() const
std::shared_ptr< Analyzer::Expr > translateUnaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
bool is_projection(const RelAlgExecutionUnit &ra_exe_unit)
static RelRexToStringConfig defaults()
HOST DEVICE int get_comp_param() const
HOST DEVICE int get_input_srid() const
std::shared_ptr< Analyzer::Expr > translateTernaryGeoFunction(const RexFunctionOperator *) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoFunction(const RexFunctionOperator *) const
std::vector< ExpressionPtr > ExpressionPtrVector
std::string toString(RelRexToStringConfig config=RelRexToStringConfig::defaults()) const override
std::shared_ptr< Analyzer::Expr > translateFunctionWithGeoArg(const RexFunctionOperator *) const
const std::string & getName() const
std::shared_ptr< Analyzer::Expr > translateGeoComparison(const RexOperator *) const
int get_physical_coord_cols() const
std::vector< std::shared_ptr< Analyzer::Expr > > translateGeoColumn(const RexInput *, SQLTypeInfo &, const bool with_bounds, const bool with_render_group, const bool expand_geo_col) const
std::shared_ptr< Analyzer::Expr > translateBinaryGeoConstructor(const RexFunctionOperator *, SQLTypeInfo &, const bool with_bounds) const
SQLTypes get_ti_from_geo(const Geospatial::GeoBase *geo)
std::shared_ptr< Analyzer::Expr > fold_expr(const Analyzer::Expr *expr)
const Catalog_Namespace::Catalog & cat_
HOST DEVICE int get_output_srid() const
virtual GeoType getType() const =0
HOST DEVICE void set_type(SQLTypes t)