Skip to content

Commit 024c079

Browse files
committed
SQL: Add ST_WktToSQL function
Adds support for ST_WktToSQL function which accepts a string and parses it as WKT representation of a geoshape. Relates to elastic#29872
1 parent 78dfa50 commit 024c079

File tree

12 files changed

+211
-2
lines changed

12 files changed

+211
-2
lines changed

docs/reference/sql/functions/geo.asciidoc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,28 @@ Returns the WKT representation of the `geometry`. The return type is string.
3030
--------------------------------------------------
3131
include-tagged::{sql-specs}/geo/docs.csv-spec[aswkt]
3232
--------------------------------------------------
33+
34+
35+
[[sql-functions-geo-st-as-wkt]]
36+
===== `ST_AsWKT`
37+
38+
.Synopsis:
39+
[source, sql]
40+
--------------------------------------------------
41+
ST_WKTToSQL(string<1>)
42+
--------------------------------------------------
43+
44+
*Input*:
45+
46+
<1> string geometry
47+
48+
*Output*: WKT string
49+
50+
.Description:
51+
52+
Returns the geometry from WKT representation. The return type is geometry.
53+
54+
["source","sql",subs="attributes,macros"]
55+
--------------------------------------------------
56+
include-tagged::{sql-specs}/geo/docs.csv-spec[aswkt]
57+
--------------------------------------------------

x-pack/plugin/sql/qa/src/main/resources/command.csv-spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ SPACE |SCALAR
101101
SUBSTRING |SCALAR
102102
UCASE |SCALAR
103103
ST_ASWKT |SCALAR
104+
ST_WKTTOSQL |SCALAR
104105
CAST |SCALAR
105106
CONVERT |SCALAR
106107
SCORE |SCORE

x-pack/plugin/sql/qa/src/main/resources/docs.csv-spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ SPACE |SCALAR
278278
SUBSTRING |SCALAR
279279
UCASE |SCALAR
280280
ST_ASWKT |SCALAR
281+
ST_WKTTOSQL |SCALAR
281282
CAST |SCALAR
282283
CONVERT |SCALAR
283284
SCORE |SCORE

x-pack/plugin/sql/qa/src/main/resources/geo/docs.csv-spec

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,18 @@
1010

1111
selectAsWKT
1212
// tag::aswkt
13-
SELECT city, ST_ASWKT(location) location FROM "geo" WHERE city = 'Amsterdam';
13+
SELECT city, ST_AsWKT(location) location FROM "geo" WHERE city = 'Amsterdam';
1414

1515
city:s | location:s
1616
Amsterdam |point (4.850311987102032 52.347556999884546)
1717
// end::aswkt
1818
;
19+
20+
selectAsWKT
21+
// tag::wkttosql
22+
SELECT ST_AsWKT(ST_WKTToSQL('POINT (10 20)')) location;
23+
24+
location:s
25+
point (10.0 20.0)
26+
// end::wkttosql
27+
;

x-pack/plugin/sql/qa/src/main/resources/geo/geosql.csv-spec

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,32 @@ SELECT COUNT(city) count, CAST(SUBSTRING(ST_ASWKT(location), 8, 1) = '-' AS STRI
102102
9 |false
103103
6 |true
104104
;
105+
106+
selectFakeCoordinatesFromCityAndRegion
107+
SELECT region, city, ST_ASWKT(ST_WKTTOSQL(CONCAT(CONCAT(CONCAT(CONCAT('POINT (', CAST(LENGTH(city) AS STRING)), ' '), CAST(LENGTH(region) AS STRING)), ')'))) loc FROM geo ORDER BY region, city;
108+
109+
region:s | city:s | loc:s
110+
Americas |Chicago |point (7.0 8.0)
111+
Americas |Mountain View |point (13.0 8.0)
112+
Americas |New York |point (8.0 8.0)
113+
Americas |Phoenix |point (7.0 8.0)
114+
Americas |San Francisco |point (13.0 8.0)
115+
Asia |Hong Kong |point (9.0 4.0)
116+
Asia |Seoul |point (5.0 4.0)
117+
Asia |Singapore |point (9.0 4.0)
118+
Asia |Sydney |point (6.0 4.0)
119+
Asia |Tokyo |point (5.0 4.0)
120+
Europe |Amsterdam |point (9.0 6.0)
121+
Europe |Berlin |point (6.0 6.0)
122+
Europe |London |point (6.0 6.0)
123+
Europe |Munich |point (6.0 6.0)
124+
Europe |Paris |point (5.0 6.0)
125+
;
126+
127+
selectAllPointsGroupByHemisphereFromAsWKT
128+
SELECT COUNT(city) count, CAST(SUBSTRING(ST_ASWKT(ST_WKTTOSQL(UCASE(ST_ASWKT(location)))), 8, 1) = '-' AS STRING) west FROM "geo" GROUP BY west ORDER BY west;
129+
130+
count:l | west:s
131+
9 |false
132+
6 |true
133+
;

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.WeekOfYear;
3636
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.Year;
3737
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StAswkt;
38+
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosql;
3839
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ACos;
3940
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ASin;
4041
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ATan;
@@ -215,6 +216,7 @@ private void defineDefaultFunctions() {
215216

216217
// Geo Functions
217218
addToMap(def(StAswkt.class, StAswkt::new));
219+
addToMap(def(StWkttosql.class, StWkttosql::new));
218220
// DataType conversion
219221
addToMap(def(Cast.class, Cast::new, "CONVERT"));
220222
// Special

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor;
1212
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor;
1313
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor;
14+
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosqlProcessor;
1415
import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor;
1516
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor;
1617
import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor;
@@ -90,6 +91,7 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
9091
entries.add(new Entry(Processor.class, ReplaceFunctionProcessor.NAME, ReplaceFunctionProcessor::new));
9192
entries.add(new Entry(Processor.class, SubstringFunctionProcessor.NAME, SubstringFunctionProcessor::new));
9293
entries.add(new Entry(Processor.class, GeoProcessor.NAME, GeoProcessor::new));
94+
entries.add(new Entry(Processor.class, StWkttosqlProcessor.NAME, StWkttosqlProcessor::new));
9395
return entries;
9496
}
9597

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.sql.expression.function.scalar.geo;
8+
9+
import org.elasticsearch.xpack.sql.expression.Expression;
10+
import org.elasticsearch.xpack.sql.expression.Expressions;
11+
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
12+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
13+
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
14+
import org.elasticsearch.xpack.sql.tree.Location;
15+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
16+
import org.elasticsearch.xpack.sql.type.DataType;
17+
18+
/**
19+
* Constructs geometric objects from their WTK representations
20+
*/
21+
public class StWkttosql extends UnaryScalarFunction {
22+
23+
public StWkttosql(Location location, Expression field) {
24+
super(location, field);
25+
}
26+
27+
@Override
28+
protected StWkttosql replaceChild(Expression newChild) {
29+
return new StWkttosql(location(), newChild);
30+
}
31+
32+
@Override
33+
protected TypeResolution resolveType() {
34+
if (field().dataType().isString()) {
35+
return TypeResolution.TYPE_RESOLVED;
36+
}
37+
return Expressions.typeMustBeString(field(), functionName(), Expressions.ParamOrdinal.DEFAULT);
38+
}
39+
40+
@Override
41+
protected Processor makeProcessor() {
42+
return StWkttosqlProcessor.INSTANCE;
43+
}
44+
45+
@Override
46+
public DataType dataType() {
47+
return DataType.GEO_SHAPE;
48+
}
49+
50+
@Override
51+
protected NodeInfo<StWkttosql> info() {
52+
return NodeInfo.create(this, StWkttosql::new, field());
53+
}
54+
55+
@Override
56+
public String processScript(String script) {
57+
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".wktToSql(" + script + ")");
58+
}
59+
60+
@Override
61+
public Object fold() {
62+
return StWkttosqlProcessor.INSTANCE.process(field().fold());
63+
}
64+
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.sql.expression.function.scalar.geo;
8+
9+
import org.elasticsearch.common.io.stream.StreamInput;
10+
import org.elasticsearch.common.io.stream.StreamOutput;
11+
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
12+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
13+
14+
import java.io.IOException;
15+
16+
public class StWkttosqlProcessor implements Processor {
17+
18+
static final StWkttosqlProcessor INSTANCE = new StWkttosqlProcessor();
19+
20+
public static final String NAME = "geo_wkttosql";
21+
22+
private StWkttosqlProcessor() {
23+
}
24+
25+
public StWkttosqlProcessor(StreamInput in) throws IOException {}
26+
27+
@Override
28+
public Object process(Object input) {
29+
return StWkttosqlProcessor.apply(input);
30+
}
31+
32+
33+
public static GeoShape apply(Object input) {
34+
if (input == null) {
35+
return null;
36+
}
37+
38+
if ((input instanceof String) == false) {
39+
throw new SqlIllegalArgumentException("A string is required; received {}", input);
40+
}
41+
try {
42+
return new GeoShape(input);
43+
} catch (IOException ex) {
44+
throw new SqlIllegalArgumentException("Cannot parse [{}] as a geo_shape value", input);
45+
}
46+
}
47+
48+
@Override
49+
public String getWriteableName() {
50+
return NAME;
51+
}
52+
53+
@Override
54+
public void writeTo(StreamOutput out) throws IOException {
55+
56+
}
57+
}

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor;
1313
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor;
1414
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor;
15+
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape;
16+
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosqlProcessor;
1517
import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation;
1618
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
1719
import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation;
@@ -403,4 +405,8 @@ public static String aswktPoint(Object v) {
403405
public static String aswktShape(Object v) {
404406
return GeoProcessor.GeoOperation.ASWKT_SHAPE.apply(v).toString();
405407
}
408+
409+
public static GeoShape wktToSql(String v) {
410+
return StWkttosqlProcessor.apply(v);
411+
}
406412
}

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypes.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.elasticsearch.xpack.sql.type;
77

88
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape;
910
import org.joda.time.DateTime;
1011

1112
public final class DataTypes {
@@ -51,6 +52,9 @@ public static DataType fromJava(Object value) {
5152
if (value instanceof String || value instanceof Character) {
5253
return DataType.KEYWORD;
5354
}
55+
if (value instanceof GeoShape) {
56+
return DataType.GEO_SHAPE;
57+
}
5458
throw new SqlIllegalArgumentException("No idea what's the DataType for {}", value.getClass());
5559
}
5660

x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44
# you may not use this file except in compliance with the Elastic License.
55
#
66

7-
# This file contains a whitelist for SQL specific utilities available inside SQL scripting
7+
# This file contains a whitelist for SQL specific utilities and classes available inside SQL scripting
8+
9+
#### Classes
10+
11+
class org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape {
12+
13+
}
14+
815

916
class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalSqlScriptUtils {
1017

@@ -116,4 +123,5 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
116123
String ucase(String)
117124
String aswktPoint(Object)
118125
String aswktShape(Object)
126+
GeoShape wktToSql(String)
119127
}

0 commit comments

Comments
 (0)