Skip to content

Commit 9935553

Browse files
committed
Dremio 24.2.6 support
STGeomFromGeoJSON Added
1 parent 0ab0e3c commit 9935553

File tree

9 files changed

+157
-30
lines changed

9 files changed

+157
-30
lines changed

.idea/detekt.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/kotlinc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.MD

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
# Dremio Geo-Spatial Extensions
1010

1111
### What you get
12+
1213
- Widespread OGC implementation for SQL (adheres to PostGIS standards)
13-
- Supported input formats: `WKT`, `WKB (HEX or BINARY)`
14-
- Supported output formats: `WKT`, `WKB`, `GeoJSON`
15-
- Easily installable Maven-Central/Github artifacts shaded jar artifact
16-
- Dremio CE version compatibility (new versions will be released with each community edition)
14+
- Supported input formats: `WKT`, `WKB (HEX or BINARY)`
15+
- Supported output formats: `WKT`, `WKB`, `GeoJSON`
16+
- Easily installable Maven-Central/Github artifacts shaded jar artifact
17+
- Dremio CE version compatibility (new versions will be released with each community edition)
1718
- Up-2-date Proj4J & JTS geometry based implementation
1819

19-
2020
### Sponsorship
2121

2222
Enjoying my work? A show of support would be much obliged :grin:
@@ -28,6 +28,7 @@ Enjoying my work? A show of support would be much obliged :grin:
2828
</a>
2929

3030
### Installation
31+
3132
- Take the shaded jar for the desired version and place inside your Dremio installation (`$DREMIO_HOME/jars/3rdparty`)
3233
- Restart your Dremio server(s)
3334
- Rejoice! (and see the [WIKI](https://github.com/sheinbergon/dremio-udf-gis/wiki) for detailed usage instructions)
@@ -36,30 +37,32 @@ Enjoying my work? A show of support would be much obliged :grin:
3637

3738
| Library Version | Dremio Version | Status |
3839
|-----------------|----------------|------------|
39-
| 0.2.x | 20.1.x | Legacy |
40-
| 0.3.x | 21.1.x | Legacy |
41-
| 0.4.x | 21.2.x | Legacy |
42-
| 0.5.x | 22.0.x | Legacy |
43-
| 0.6.x | 22.1.x | Legacy |
44-
| 0.7.x | 23.0.x | Maintained |
45-
| 0.8.x | 23.1.x | Maintained |
46-
| 0.9.x | 24.0.x | Maintained |
47-
| 0.10.x | 24.0.x | Maintained |
48-
40+
| 0.2.x | 20.1.0 | Legacy |
41+
| 0.3.x | 21.1.1 | Legacy |
42+
| 0.4.x | 21.2.0 | Legacy |
43+
| 0.5.x | 22.0.0 | Legacy |
44+
| 0.6.x | 22.1.1 | Legacy |
45+
| 0.7.x | 23.0.1 | Legacy |
46+
| 0.8.x | 23.1.0 | Legacy |
47+
| 0.9.x | 24.0.0 | Maintained |
48+
| 0.10.x | 24.1.0 | Maintained |
49+
| 0.11.x | 24.2.6 | Maintained |
4950

5051
### Usage Notes
52+
5153
As opposed to PostGIS, Dremio is only a query engine based on existing/projected data sources/lakes.
5254
That means that `Geometry` is not a natively supported data type, and you can only access it if
5355
it's being properly projected from the data sources (For example, PostGIS Geometry is read as an `EWKB` HEX encoded string).
5456

5557
In order to successfully use the provided GIS functions, you must first make sure the geometry is in `WKB (BINARY)` format.
56-
If it's not, you need to decode it:
58+
If it's not, you need to decode it:
59+
5760
- if the input is in `WKT` format, use `ST_GeomFromText`
5861
- if the input is a HEX encoded`WKB`, use Dremio's `FROM_HEX`
5962

6063
This library uses Dremios' Arrow buffers (`ArrowBuf`) to maintain geometry data in binary (`WKB`) format (for performance and efficiency)
6164
when interchanging it between GIS functions, which is of course undecipherable for the naked eye. When running queries from the UI,
62-
`WKB` output will always be base64 encoded.
65+
`WKB` output will always be base64 encoded.
6366

6467
In order to resolve Data back to human-readable format (`WKT`), use `ST_AsText`/`ST_AsGeoJson`
6568

@@ -74,11 +77,14 @@ SELECT ST_AsText(
7477
```
7578

7679
### Roadmap
80+
7781
- Frequent version/dependency updates
7882
- Add more OGC/PostGIS matching functionality
7983
- Add Geography type support
8084

8185
### Noteworthy Mentions
82-
Work in this repository was originally based on the following sources:
86+
87+
Work in this repository was originally based on the following sources:
88+
8389
- [Apache Drill GIS Functionality](https://github.com/apache/drill/tree/master/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/gis)
8490
- [Christy Haragan's initial port](https://github.com/christyharagan/dremio-gis)

pom.xml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@
66
<artifactId>dremio-udf-gis</artifactId>
77
<properties>
88
<checkstyle.version>9.3</checkstyle.version>
9-
<dremio.version>24.2.2-202309281602050954-7d5e877f</dremio.version>
10-
<dremio-arrow.version>12.0.1-20230728221431-62098927e3-dremio</dremio-arrow.version>
9+
<dremio.version>24.2.6-202311250456170399-68acbe47</dremio.version>
10+
<dremio-arrow.version>12.0.1-20231103121511-850ae5a2d6-dremio</dremio-arrow.version>
1111
<proj4j.version>1.3.0</proj4j.version>
1212
<jts-core.version>1.19.0</jts-core.version>
1313
<jts-io-common.version>1.19.0</jts-io-common.version>
1414
<commons-io.version>2.11.0</commons-io.version>
1515
<junit.version>4.13.2</junit.version>
16-
<junit-jupiter.version>5.10.0</junit-jupiter.version>
17-
<kotlin.version>1.9.10</kotlin.version>
16+
<junit-jupiter.version>5.10.1</junit-jupiter.version>
17+
<junit-platform.version>1.10.1</junit-platform.version>
18+
<kotlin.version>1.9.21</kotlin.version>
1819
<kotest.version>5.7.2</kotest.version>
1920
<joda.version>2.9</joda.version>
20-
<detekt.version>1.23.1</detekt.version>
21+
<detekt.version>1.23.4</detekt.version>
2122
<carrotsearch.version>0.7.0</carrotsearch.version>
22-
<arrow-memory-netty.version>vector-12.0.1-20230728221431-62098927e3-dremio</arrow-memory-netty.version>
23+
<arrow-memory-netty.version>12.0.1</arrow-memory-netty.version>
2324
</properties>
2425
<version>0.11.0-SNAPSHOT</version>
2526
<name>dremio-udf-gis</name>
@@ -192,6 +193,12 @@
192193
<version>${junit-jupiter.version}</version>
193194
<scope>test</scope>
194195
</dependency>
196+
<dependency>
197+
<groupId>org.junit.platform</groupId>
198+
<artifactId>junit-platform-engine</artifactId>
199+
<version>${junit-platform.version}</version>
200+
<scope>test</scope>
201+
</dependency>
195202
<dependency>
196203
<groupId>org.jetbrains.kotlin</groupId>
197204
<artifactId>kotlin-test-junit5</artifactId>
@@ -393,7 +400,7 @@
393400
<plugin>
394401
<groupId>org.apache.maven.plugins</groupId>
395402
<artifactId>maven-surefire-plugin</artifactId>
396-
<version>3.0.0-M7</version>
403+
<version>3.1.2</version>
397404
</plugin>
398405
<plugin>
399406
<groupId>org.jacoco</groupId>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.sheinbergon.dremio.udf.gis;
19+
20+
import com.dremio.exec.expr.SimpleFunction;
21+
import com.dremio.exec.expr.annotations.FunctionTemplate;
22+
import com.dremio.exec.expr.annotations.Output;
23+
import com.dremio.exec.expr.annotations.Param;
24+
25+
import javax.inject.Inject;
26+
27+
@FunctionTemplate(
28+
name = "ST_GeomFromGeoJSON",
29+
scope = FunctionTemplate.FunctionScope.SIMPLE,
30+
nulls = FunctionTemplate.NullHandling.INTERNAL)
31+
public class STGeomFromGeoJson implements SimpleFunction {
32+
33+
@Param
34+
org.apache.arrow.vector.holders.NullableVarCharHolder jsonInput;
35+
36+
@Output
37+
org.apache.arrow.vector.holders.NullableVarBinaryHolder binaryOutput;
38+
39+
@Inject
40+
org.apache.arrow.memory.ArrowBuf buffer;
41+
42+
public void setup() {
43+
}
44+
45+
public void eval() {
46+
if (org.sheinbergon.dremio.udf.gis.util.GeometryHelpers.isHolderSet(jsonInput)) {
47+
org.locationtech.jts.geom.Geometry geom = org.sheinbergon.dremio.udf.gis.util.GeometryHelpers.toGeometryFromGeoJson(jsonInput);
48+
byte[] bytes = org.sheinbergon.dremio.udf.gis.util.GeometryHelpers.toEWKB(geom);
49+
buffer = buffer.reallocIfNeeded(bytes.length);
50+
org.sheinbergon.dremio.udf.gis.util.GeometryHelpers.populate(bytes, buffer, binaryOutput);
51+
} else {
52+
org.sheinbergon.dremio.udf.gis.util.GeometryHelpers.markHolderNotSet(binaryOutput);
53+
}
54+
}
55+
}

src/main/java/org/sheinbergon/dremio/udf/gis/util/GeometryHelpers.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.locationtech.jts.algorithm.Angle;
2828
import org.locationtech.jts.geom.*;
2929
import org.locationtech.jts.io.*;
30+
import org.locationtech.jts.io.geojson.GeoJsonReader;
3031
import org.locationtech.jts.io.geojson.GeoJsonWriter;
3132
import org.locationtech.jts.operation.buffer.BufferOp;
3233
import org.locationtech.jts.operation.valid.IsValidOp;
@@ -133,6 +134,17 @@ public static Geometry toGeometry(final @Nonnull NullableVarCharHolder holder) {
133134
}
134135
}
135136

137+
@Nonnull
138+
public static Geometry toGeometryFromGeoJson(final @Nonnull NullableVarCharHolder holder) {
139+
try {
140+
String json = toUTF8String(holder);
141+
GeoJsonReader reader = new GeoJsonReader();
142+
return reader.read(json);
143+
} catch (ParseException x) {
144+
throw new RuntimeException(x);
145+
}
146+
}
147+
136148
@Nonnull
137149
public static Geometry toGeometryFromEWKT(final @Nonnull NullableVarCharHolder holder) {
138150
try {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.sheinbergon.dremio.udf.gis
2+
3+
import org.apache.arrow.vector.holders.NullableVarBinaryHolder
4+
import org.apache.arrow.vector.holders.NullableVarCharHolder
5+
import org.sheinbergon.dremio.udf.gis.spec.GeometryInputFunSpec
6+
import org.sheinbergon.dremio.udf.gis.util.allocateBuffer
7+
8+
internal class STGeomFromGeoJsonTests : GeometryInputFunSpec.NullableVarChar<STGeomFromGeoJson>() {
9+
10+
init {
11+
testGeometryInput(
12+
"Calling ST_GeomFromGeoJSON on a POINT",
13+
"""
14+
{"type":"Point","coordinates":[0.5,0.5]}
15+
""".trimIndent(),
16+
byteArrayOf(1, 1, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -32, 63, 0, 0, 0, 0, 0, 0, -32, 63)
17+
)
18+
19+
testInvalidGeometryInput(
20+
"Calling ST_GeomFromGeoJSON on rubbish text",
21+
"42ifon2 fA!@",
22+
)
23+
24+
testNullGeometryInput(
25+
"Calling ST_GeomFromGeoJSON on null input"
26+
)
27+
}
28+
29+
override val function = STGeomFromGeoJson().apply {
30+
jsonInput = NullableVarCharHolder()
31+
binaryOutput = NullableVarBinaryHolder()
32+
buffer = allocateBuffer()
33+
}
34+
35+
override val STGeomFromGeoJson.input: NullableVarCharHolder get() = function.jsonInput
36+
override val STGeomFromGeoJson.output: NullableVarBinaryHolder get() = function.binaryOutput
37+
}

src/test/kotlin/org/sheinbergon/dremio/udf/gis/spec/GeometryInputFunSpec.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.sheinbergon.dremio.udf.gis.util.reset
1414
import org.sheinbergon.dremio.udf.gis.util.setBinary
1515
import org.sheinbergon.dremio.udf.gis.util.setUtf8
1616
import org.sheinbergon.dremio.udf.gis.util.valueIsNotSet
17+
import java.util.*
1718

1819
abstract class GeometryInputFunSpec<F : SimpleFunction, I : ValueHolder, V : Any> : FunSpec() {
1920

@@ -44,7 +45,9 @@ abstract class GeometryInputFunSpec<F : SimpleFunction, I : ValueHolder, V : Any
4445
}
4546
}
4647

47-
final override fun NullableVarCharHolder.markNotSet() = this.valueIsNotSet()
48+
final override fun NullableVarCharHolder.markNotSet() {
49+
this.valueIsNotSet()
50+
}
4851

4952
final override fun NullableVarCharHolder.set(value: String) = this.setUtf8(value)
5053
}
@@ -97,7 +100,10 @@ abstract class GeometryInputFunSpec<F : SimpleFunction, I : ValueHolder, V : Any
97100
}
98101

99102
private fun NullableVarBinaryHolder.valueIs(bytes: ByteArray) =
100-
GeometryHelpers.toEWKB(GeometryHelpers.toGeometry(this)) shouldBe bytes
103+
print(Arrays.toString(GeometryHelpers.toEWKB(GeometryHelpers.toGeometry(this))))
104+
.also {
105+
GeometryHelpers.toEWKB(GeometryHelpers.toGeometry(this)) shouldBe bytes
106+
}
101107

102108
protected abstract fun I.set(value: V)
103109
protected abstract val function: F

src/test/kotlin/org/sheinbergon/dremio/udf/gis/spec/GeometryRelationFunSpec.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ abstract class GeometryRelationFunSpec<F : SimpleFunction, O : ValueHolder> : Fu
4747
this.isSet shouldBeExactly 1
4848
}
4949

50-
override fun NullableVarCharHolder.valueIsNotSet() =
50+
override fun NullableVarCharHolder.valueIsNotSet() {
5151
this.isSet shouldBe 0
52+
}
5253
}
5354

5455
abstract class NullableBitOutput<F : SimpleFunction> : GeometryRelationFunSpec<F, NullableBitHolder>() {
@@ -91,8 +92,9 @@ abstract class GeometryRelationFunSpec<F : SimpleFunction, O : ValueHolder> : Fu
9192
}
9293
}
9394

94-
override fun NullableBitHolder.valueIsNotSet() =
95+
override fun NullableBitHolder.valueIsNotSet() {
9596
this.isSet shouldBe 0
97+
}
9698
}
9799

98100
protected fun testNullGeometryRelation(

0 commit comments

Comments
 (0)