Skip to content

Commit 76f76f3

Browse files
shtilmanandrewseidl
authored andcommitted
ST_Length(MULTILINESTRING)
1 parent 7a80dda commit 76f76f3

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

QueryEngine/ExtensionFunctionsGeo.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,36 @@ double ST_Length_LineString_Geodesic(int8_t* coords,
11751175
return length_linestring(coords, coords_sz, ic, isr, osr, true, false);
11761176
}
11771177

1178+
EXTENSION_NOINLINE
1179+
double ST_Length_MultiLineString(int8_t* coords,
1180+
int64_t coords_sz,
1181+
int8_t* linestring_sizes_in,
1182+
int64_t linestring_sizes_sz,
1183+
int32_t ic,
1184+
int32_t isr,
1185+
int32_t osr) {
1186+
if (linestring_sizes_sz <= 0) {
1187+
return 0.0;
1188+
}
1189+
double mls_length = 0.0;
1190+
1191+
auto next_linestring_coords = coords;
1192+
1193+
for (auto l = 0; l < linestring_sizes_sz; l++) {
1194+
auto linestring_coords = next_linestring_coords;
1195+
auto linestring_sizes = reinterpret_cast<int32_t*>(linestring_sizes_in);
1196+
auto linestring_num_points = linestring_sizes[l];
1197+
auto linestring_num_coords = 2 * linestring_num_points;
1198+
auto linestring_coords_size = linestring_num_coords * compression_unit_size(ic);
1199+
next_linestring_coords += linestring_coords_size;
1200+
double ls_length = length_linestring(
1201+
linestring_coords, linestring_coords_size, ic, isr, osr, false, false);
1202+
mls_length += ls_length;
1203+
}
1204+
1205+
return mls_length;
1206+
}
1207+
11781208
//
11791209
// ST_Perimeter
11801210
//

QueryEngine/GeoIR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ std::vector<llvm::Value*> CodeGenerator::codegenGeoColumnVar(
7373
switch (ti.get_type()) {
7474
case kPOINT:
7575
case kLINESTRING:
76+
case kMULTILINESTRING:
7677
case kPOLYGON:
7778
case kMULTIPOLYGON: {
7879
std::vector<llvm::Value*> geo_lvs;

QueryEngine/RelAlgTranslatorGeo.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,20 +1210,34 @@ std::shared_ptr<Analyzer::Expr> RelAlgTranslator::translateUnaryGeoFunction(
12101210
}
12111211
}
12121212

1213-
// All geo function calls translated below only need the coords, extras e.g.
1214-
// ring_sizes are dropped. Specialize for other/new functions if needed.
1215-
geoargs.erase(geoargs.begin() + 1, geoargs.end());
1213+
// Unless overriden, function is assumed to be interested in the first geoarg only,
1214+
// which may be a geo object (e.g. geo column), or a coord array (e.g. geo literal)
1215+
auto discard_after_arg = 1;
12161216

12171217
if (rex_function->getName() == "ST_Length"sv) {
1218-
if (arg_ti.get_type() != kLINESTRING) {
1219-
throw QueryNotSupported(rex_function->getName() + " expects LINESTRING");
1218+
if (arg_ti.get_type() != kLINESTRING && arg_ti.get_type() != kMULTILINESTRING) {
1219+
throw QueryNotSupported(rex_function->getName() +
1220+
" expects LINESTRING or MULTILINESTRING");
1221+
}
1222+
if (arg_ti.get_type() == kMULTILINESTRING) {
1223+
auto ti0 = geoargs[0]->get_type_info();
1224+
if (ti0.get_type() == kARRAY && ti0.get_subtype() == kTINYINT) {
1225+
// Received expanded geo: widen the reach to grab linestring size array as well
1226+
discard_after_arg = 2;
1227+
}
12201228
}
12211229
specialized_geofunc += suffix(arg_ti.get_type());
12221230
if (arg_ti.get_subtype() == kGEOGRAPHY && arg_ti.get_output_srid() == 4326) {
1231+
if (arg_ti.get_type() == kMULTILINESTRING) {
1232+
throw QueryNotSupported(rex_function->getName() +
1233+
" Geodesic is not supported for MULTILINESTRING");
1234+
}
12231235
specialized_geofunc += "_Geodesic"s;
12241236
}
12251237
}
12261238

1239+
geoargs.erase(geoargs.begin() + discard_after_arg, geoargs.end());
1240+
12271241
// Add input compression mode and SRID args to enable on-the-fly
12281242
// decompression/transforms
12291243
Datum input_compression;

Tests/GeospatialTest.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,13 @@ TEST(GeoSpatial, Math) {
16731673
R"(SELECT ST_Length(CAST (ST_GeomFromText('LINESTRING(-76.6168198439371 39.9703199555959, -80.5189990254673 40.6493554919257, -82.5189990254673 42.6493554919257)', 4326) as GEOGRAPHY));)",
16741674
dt)),
16751675
static_cast<double>(0.01));
1676+
// Cartesian length of a planar multi path
1677+
ASSERT_NEAR(
1678+
static_cast<double>(6.65685),
1679+
v<double>(run_simple_agg(
1680+
R"(SELECT ST_Length('MULTILINESTRING((1 0, 0 1, -1 0, 0 -1, 1 0),(2 2,2 3))');)",
1681+
dt)),
1682+
static_cast<double>(0.0001));
16761683

16771684
// ST_Perimeter
16781685
// Cartesian perimeter of a planar polygon

0 commit comments

Comments
 (0)