Search in sources :

Example 46 with SqlNullable

use of io.trino.spi.function.SqlNullable in project trino by trinodb.

the class GeoFunctions method stSphericalArea.

@SqlNullable
@Description("Returns the area of a geometry on the Earth's surface using spherical model")
@ScalarFunction("ST_Area")
@SqlType(DOUBLE)
public static Double stSphericalArea(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) {
    OGCGeometry geometry = deserialize(input);
    if (geometry.isEmpty()) {
        return null;
    }
    validateSphericalType("ST_Area", geometry, EnumSet.of(POLYGON, MULTI_POLYGON));
    Polygon polygon = (Polygon) geometry.getEsriGeometry();
    // See https://www.movable-type.co.uk/scripts/latlong.html
    // and http://osgeo-org.1560.x6.nabble.com/Area-of-a-spherical-polygon-td3841625.html
    // and https://www.element84.com/blog/determining-if-a-spherical-polygon-contains-a-pole
    // for the underlying Maths
    double sphericalExcess = 0.0;
    int numPaths = polygon.getPathCount();
    for (int i = 0; i < numPaths; i++) {
        double sign = polygon.isExteriorRing(i) ? 1.0 : -1.0;
        sphericalExcess += sign * Math.abs(computeSphericalExcess(polygon, polygon.getPathStart(i), polygon.getPathEnd(i)));
    }
    // isExteriorRing returns false for the exterior ring
    return Math.abs(sphericalExcess * EARTH_RADIUS_M * EARTH_RADIUS_M);
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) Polygon(com.esri.core.geometry.Polygon) OGCMultiPolygon(com.esri.core.geometry.ogc.OGCMultiPolygon) OGCPolygon(com.esri.core.geometry.ogc.OGCPolygon) MultiPoint(com.esri.core.geometry.MultiPoint) Point(com.esri.core.geometry.Point) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) SqlNullable(io.trino.spi.function.SqlNullable) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) SqlType(io.trino.spi.function.SqlType)

Example 47 with SqlNullable

use of io.trino.spi.function.SqlNullable in project trino by trinodb.

the class GeoFunctions method stY.

@SqlNullable
@Description("Return the Y coordinate of the point")
@ScalarFunction("ST_Y")
@SqlType(DOUBLE)
public static Double stY(@SqlType(GEOMETRY_TYPE_NAME) Slice input) {
    OGCGeometry geometry = deserialize(input);
    validateType("ST_Y", geometry, EnumSet.of(POINT));
    if (geometry.isEmpty()) {
        return null;
    }
    return ((OGCPoint) geometry).Y();
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) SqlNullable(io.trino.spi.function.SqlNullable) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) SqlType(io.trino.spi.function.SqlType)

Example 48 with SqlNullable

use of io.trino.spi.function.SqlNullable in project trino by trinodb.

the class GeoFunctions method stContains.

@SqlNullable
@Description("Returns TRUE if and only if no points of right lie in the exterior of left, and at least one point of the interior of left lies in the interior of right")
@ScalarFunction("ST_Contains")
@SqlType(BOOLEAN)
public static Boolean stContains(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) {
    if (!envelopes(left, right, Envelope::contains)) {
        return false;
    }
    OGCGeometry leftGeometry = deserialize(left);
    OGCGeometry rightGeometry = deserialize(right);
    verifySameSpatialReference(leftGeometry, rightGeometry);
    return leftGeometry.contains(rightGeometry);
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) SqlNullable(io.trino.spi.function.SqlNullable) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) SqlType(io.trino.spi.function.SqlType)

Example 49 with SqlNullable

use of io.trino.spi.function.SqlNullable in project trino by trinodb.

the class StringFunctions method splitPart.

@SqlNullable
@Description("Splits a string by a delimiter and returns the specified field (counting from one)")
@ScalarFunction
@LiteralParameters({ "x", "y" })
@SqlType("varchar(x)")
public static Slice splitPart(@SqlType("varchar(x)") Slice string, @SqlType("varchar(y)") Slice delimiter, @SqlType(StandardTypes.BIGINT) long index) {
    checkCondition(index > 0, INVALID_FUNCTION_ARGUMENT, "Index must be greater than zero");
    // Empty delimiter? Then every character will be a split
    if (delimiter.length() == 0) {
        int startCodePoint = toIntExact(index);
        int indexStart = offsetOfCodePoint(string, startCodePoint - 1);
        if (indexStart < 0) {
            // index too big
            return null;
        }
        int length = lengthOfCodePoint(string, indexStart);
        if (indexStart + length > string.length()) {
            throw new TrinoException(INVALID_FUNCTION_ARGUMENT, "Invalid UTF-8 encoding");
        }
        return string.slice(indexStart, length);
    }
    int matchCount = 0;
    int previousIndex = 0;
    while (previousIndex < string.length()) {
        int matchIndex = string.indexOf(delimiter, previousIndex);
        // No match
        if (matchIndex < 0) {
            break;
        }
        // Reached the requested part?
        if (++matchCount == index) {
            return string.slice(previousIndex, matchIndex - previousIndex);
        }
        // Continue searching after the delimiter
        previousIndex = matchIndex + delimiter.length();
    }
    if (matchCount == index - 1) {
        // returns last section of the split
        return string.slice(previousIndex, string.length() - previousIndex);
    }
    // index is too big, null is returned
    return null;
}
Also used : TrinoException(io.trino.spi.TrinoException) Constraint(io.trino.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) SqlNullable(io.trino.spi.function.SqlNullable) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) LiteralParameters(io.trino.spi.function.LiteralParameters) SqlType(io.trino.spi.function.SqlType)

Example 50 with SqlNullable

use of io.trino.spi.function.SqlNullable in project trino by trinodb.

the class Re2JRegexpReplaceLambdaFunction method regexpReplace.

@LiteralParameters("x")
@SqlType("varchar")
@SqlNullable
public Slice regexpReplace(@SqlType("varchar") Slice source, @SqlType(Re2JRegexpType.NAME) Re2JRegexp pattern, @SqlType("function(array(varchar), varchar(x))") UnaryFunctionInterface replaceFunction) {
    // If there is no match we can simply return the original source without doing copy.
    Matcher matcher = pattern.matcher(source);
    if (!matcher.find()) {
        return source;
    }
    SliceOutput output = new DynamicSliceOutput(source.length());
    // that will be passed to the lambda function.
    if (pageBuilder.isFull()) {
        pageBuilder.reset();
    }
    BlockBuilder blockBuilder = pageBuilder.getBlockBuilder(0);
    int groupCount = matcher.groupCount();
    int appendPosition = 0;
    do {
        int start = matcher.start();
        int end = matcher.end();
        // Append the un-matched part
        if (appendPosition < start) {
            output.writeBytes(source, appendPosition, start - appendPosition);
        }
        appendPosition = end;
        // Append the capturing groups to the target block that will be passed to lambda
        for (int i = 1; i <= groupCount; i++) {
            Slice matchedGroupSlice = matcher.group(i);
            if (matchedGroupSlice != null) {
                VARCHAR.writeSlice(blockBuilder, matchedGroupSlice);
            } else {
                blockBuilder.appendNull();
            }
        }
        pageBuilder.declarePositions(groupCount);
        Block target = blockBuilder.getRegion(blockBuilder.getPositionCount() - groupCount, groupCount);
        // Call the lambda function to replace the block, and append the result to output
        Slice replaced = (Slice) replaceFunction.apply(target);
        if (replaced == null) {
            // replacing a substring with null (unknown) makes the entire string null
            return null;
        }
        output.appendBytes(replaced);
    } while (matcher.find());
    // Append the rest of un-matched
    output.writeBytes(source, appendPosition, source.length() - appendPosition);
    return output.slice();
}
Also used : SliceOutput(io.airlift.slice.SliceOutput) DynamicSliceOutput(io.airlift.slice.DynamicSliceOutput) Matcher(com.google.re2j.Matcher) Slice(io.airlift.slice.Slice) DynamicSliceOutput(io.airlift.slice.DynamicSliceOutput) Block(io.trino.spi.block.Block) BlockBuilder(io.trino.spi.block.BlockBuilder) SqlNullable(io.trino.spi.function.SqlNullable) LiteralParameters(io.trino.spi.function.LiteralParameters) SqlType(io.trino.spi.function.SqlType)

Aggregations

SqlNullable (io.trino.spi.function.SqlNullable)56 SqlType (io.trino.spi.function.SqlType)56 ScalarFunction (io.trino.spi.function.ScalarFunction)44 Description (io.trino.spi.function.Description)38 OGCGeometry (com.esri.core.geometry.ogc.OGCGeometry)32 OGCPoint (com.esri.core.geometry.ogc.OGCPoint)14 JsonParser (com.fasterxml.jackson.core.JsonParser)14 TrinoException (io.trino.spi.TrinoException)14 JsonUtil.createJsonParser (io.trino.util.JsonUtil.createJsonParser)14 IOException (java.io.IOException)14 MultiPoint (com.esri.core.geometry.MultiPoint)12 Point (com.esri.core.geometry.Point)12 BlockBuilder (io.trino.spi.block.BlockBuilder)10 ScalarOperator (io.trino.spi.function.ScalarOperator)8 JsonCastException (io.trino.util.JsonCastException)8 LiteralParameters (io.trino.spi.function.LiteralParameters)7 JsonToken (com.fasterxml.jackson.core.JsonToken)6 MultiPath (com.esri.core.geometry.MultiPath)4 MultiVertexGeometry (com.esri.core.geometry.MultiVertexGeometry)4 Slice (io.airlift.slice.Slice)4