Skip to content

Commit

Permalink
SQL: Add ST_WktToSQL function
Browse files Browse the repository at this point in the history
Adds support for ST_WktToSQL function which accepts a string and parses
it as WKT representation of a geoshape.

Relates to elastic#29872
  • Loading branch information
imotov committed Nov 8, 2018
1 parent 78dfa50 commit 024c079
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 2 deletions.
25 changes: 25 additions & 0 deletions docs/reference/sql/functions/geo.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,28 @@ Returns the WKT representation of the `geometry`. The return type is string.
--------------------------------------------------
include-tagged::{sql-specs}/geo/docs.csv-spec[aswkt]
--------------------------------------------------


[[sql-functions-geo-st-as-wkt]]
===== `ST_AsWKT`

.Synopsis:
[source, sql]
--------------------------------------------------
ST_WKTToSQL(string<1>)
--------------------------------------------------

*Input*:

<1> string geometry

*Output*: WKT string

.Description:

Returns the geometry from WKT representation. The return type is geometry.

["source","sql",subs="attributes,macros"]
--------------------------------------------------
include-tagged::{sql-specs}/geo/docs.csv-spec[aswkt]
--------------------------------------------------
1 change: 1 addition & 0 deletions x-pack/plugin/sql/qa/src/main/resources/command.csv-spec
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ SPACE |SCALAR
SUBSTRING |SCALAR
UCASE |SCALAR
ST_ASWKT |SCALAR
ST_WKTTOSQL |SCALAR
CAST |SCALAR
CONVERT |SCALAR
SCORE |SCORE
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugin/sql/qa/src/main/resources/docs.csv-spec
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ SPACE |SCALAR
SUBSTRING |SCALAR
UCASE |SCALAR
ST_ASWKT |SCALAR
ST_WKTTOSQL |SCALAR
CAST |SCALAR
CONVERT |SCALAR
SCORE |SCORE
Expand Down
11 changes: 10 additions & 1 deletion x-pack/plugin/sql/qa/src/main/resources/geo/docs.csv-spec
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@

selectAsWKT
// tag::aswkt
SELECT city, ST_ASWKT(location) location FROM "geo" WHERE city = 'Amsterdam';
SELECT city, ST_AsWKT(location) location FROM "geo" WHERE city = 'Amsterdam';

city:s | location:s
Amsterdam |point (4.850311987102032 52.347556999884546)
// end::aswkt
;

selectAsWKT
// tag::wkttosql
SELECT ST_AsWKT(ST_WKTToSQL('POINT (10 20)')) location;

location:s
point (10.0 20.0)
// end::wkttosql
;
29 changes: 29 additions & 0 deletions x-pack/plugin/sql/qa/src/main/resources/geo/geosql.csv-spec
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,32 @@ SELECT COUNT(city) count, CAST(SUBSTRING(ST_ASWKT(location), 8, 1) = '-' AS STRI
9 |false
6 |true
;

selectFakeCoordinatesFromCityAndRegion
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;

region:s | city:s | loc:s
Americas |Chicago |point (7.0 8.0)
Americas |Mountain View |point (13.0 8.0)
Americas |New York |point (8.0 8.0)
Americas |Phoenix |point (7.0 8.0)
Americas |San Francisco |point (13.0 8.0)
Asia |Hong Kong |point (9.0 4.0)
Asia |Seoul |point (5.0 4.0)
Asia |Singapore |point (9.0 4.0)
Asia |Sydney |point (6.0 4.0)
Asia |Tokyo |point (5.0 4.0)
Europe |Amsterdam |point (9.0 6.0)
Europe |Berlin |point (6.0 6.0)
Europe |London |point (6.0 6.0)
Europe |Munich |point (6.0 6.0)
Europe |Paris |point (5.0 6.0)
;

selectAllPointsGroupByHemisphereFromAsWKT
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;

count:l | west:s
9 |false
6 |true
;
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.WeekOfYear;
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.Year;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StAswkt;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosql;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ACos;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ASin;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.ATan;
Expand Down Expand Up @@ -215,6 +216,7 @@ private void defineDefaultFunctions() {

// Geo Functions
addToMap(def(StAswkt.class, StAswkt::new));
addToMap(def(StWkttosql.class, StWkttosql::new));
// DataType conversion
addToMap(def(Cast.class, Cast::new, "CONVERT"));
// Special
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosqlProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor;
Expand Down Expand Up @@ -90,6 +91,7 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
entries.add(new Entry(Processor.class, ReplaceFunctionProcessor.NAME, ReplaceFunctionProcessor::new));
entries.add(new Entry(Processor.class, SubstringFunctionProcessor.NAME, SubstringFunctionProcessor::new));
entries.add(new Entry(Processor.class, GeoProcessor.NAME, GeoProcessor::new));
entries.add(new Entry(Processor.class, StWkttosqlProcessor.NAME, StWkttosqlProcessor::new));
return entries;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.sql.expression.function.scalar.geo;

import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.Expressions;
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
import org.elasticsearch.xpack.sql.type.DataType;

/**
* Constructs geometric objects from their WTK representations
*/
public class StWkttosql extends UnaryScalarFunction {

public StWkttosql(Location location, Expression field) {
super(location, field);
}

@Override
protected StWkttosql replaceChild(Expression newChild) {
return new StWkttosql(location(), newChild);
}

@Override
protected TypeResolution resolveType() {
if (field().dataType().isString()) {
return TypeResolution.TYPE_RESOLVED;
}
return Expressions.typeMustBeString(field(), functionName(), Expressions.ParamOrdinal.DEFAULT);
}

@Override
protected Processor makeProcessor() {
return StWkttosqlProcessor.INSTANCE;
}

@Override
public DataType dataType() {
return DataType.GEO_SHAPE;
}

@Override
protected NodeInfo<StWkttosql> info() {
return NodeInfo.create(this, StWkttosql::new, field());
}

@Override
public String processScript(String script) {
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".wktToSql(" + script + ")");
}

@Override
public Object fold() {
return StWkttosqlProcessor.INSTANCE.process(field().fold());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.sql.expression.function.scalar.geo;

import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;

import java.io.IOException;

public class StWkttosqlProcessor implements Processor {

static final StWkttosqlProcessor INSTANCE = new StWkttosqlProcessor();

public static final String NAME = "geo_wkttosql";

private StWkttosqlProcessor() {
}

public StWkttosqlProcessor(StreamInput in) throws IOException {}

@Override
public Object process(Object input) {
return StWkttosqlProcessor.apply(input);
}


public static GeoShape apply(Object input) {
if (input == null) {
return null;
}

if ((input instanceof String) == false) {
throw new SqlIllegalArgumentException("A string is required; received {}", input);
}
try {
return new GeoShape(input);
} catch (IOException ex) {
throw new SqlIllegalArgumentException("Cannot parse [{}] as a geo_shape value", input);
}
}

@Override
public String getWriteableName() {
return NAME;
}

@Override
public void writeTo(StreamOutput out) throws IOException {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor;
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StWkttosqlProcessor;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation;
Expand Down Expand Up @@ -403,4 +405,8 @@ public static String aswktPoint(Object v) {
public static String aswktShape(Object v) {
return GeoProcessor.GeoOperation.ASWKT_SHAPE.apply(v).toString();
}

public static GeoShape wktToSql(String v) {
return StWkttosqlProcessor.apply(v);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package org.elasticsearch.xpack.sql.type;

import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape;
import org.joda.time.DateTime;

public final class DataTypes {
Expand Down Expand Up @@ -51,6 +52,9 @@ public static DataType fromJava(Object value) {
if (value instanceof String || value instanceof Character) {
return DataType.KEYWORD;
}
if (value instanceof GeoShape) {
return DataType.GEO_SHAPE;
}
throw new SqlIllegalArgumentException("No idea what's the DataType for {}", value.getClass());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
# you may not use this file except in compliance with the Elastic License.
#

# This file contains a whitelist for SQL specific utilities available inside SQL scripting
# This file contains a whitelist for SQL specific utilities and classes available inside SQL scripting

#### Classes

class org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoShape {

}


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

Expand Down Expand Up @@ -116,4 +123,5 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
String ucase(String)
String aswktPoint(Object)
String aswktShape(Object)
GeoShape wktToSql(String)
}

0 comments on commit 024c079

Please sign in to comment.