Search in sources :

Example 11 with Description

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

the class StringFunctions method substring.

@Description("Substring of given length starting at an index")
@ScalarFunction(alias = "substr")
@LiteralParameters("x")
@SqlType("varchar(x)")
public static Slice substring(@SqlType("varchar(x)") Slice utf8, @SqlType(StandardTypes.BIGINT) long start, @SqlType(StandardTypes.BIGINT) long length) {
    if (start == 0 || (length <= 0) || (utf8.length() == 0)) {
        return Slices.EMPTY_SLICE;
    }
    int startCodePoint = Ints.saturatedCast(start);
    int lengthCodePoints = Ints.saturatedCast(length);
    if (startCodePoint > 0) {
        int indexStart = offsetOfCodePoint(utf8, startCodePoint - 1);
        if (indexStart < 0) {
            // before beginning of string
            return Slices.EMPTY_SLICE;
        }
        int indexEnd = offsetOfCodePoint(utf8, indexStart, lengthCodePoints);
        if (indexEnd < 0) {
            // after end of string
            indexEnd = utf8.length();
        }
        return utf8.slice(indexStart, indexEnd - indexStart);
    }
    // negative start is relative to end of string
    int codePoints = countCodePoints(utf8);
    startCodePoint += codePoints;
    // before beginning of string
    if (startCodePoint < 0) {
        return Slices.EMPTY_SLICE;
    }
    int indexStart = offsetOfCodePoint(utf8, startCodePoint);
    int indexEnd;
    if (startCodePoint + lengthCodePoints < codePoints) {
        indexEnd = offsetOfCodePoint(utf8, indexStart, lengthCodePoints);
    } else {
        indexEnd = utf8.length();
    }
    return utf8.slice(indexStart, indexEnd - indexStart);
}
Also used : Constraint(io.trino.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) 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 12 with Description

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

the class StringFunctions method levenshteinDistance.

@Description("Computes Levenshtein distance between two strings")
@ScalarFunction
@LiteralParameters({ "x", "y" })
@SqlType(StandardTypes.BIGINT)
public static long levenshteinDistance(@SqlType("varchar(x)") Slice left, @SqlType("varchar(y)") Slice right) {
    int[] leftCodePoints = castToCodePoints(left);
    int[] rightCodePoints = castToCodePoints(right);
    if (leftCodePoints.length < rightCodePoints.length) {
        int[] tempCodePoints = leftCodePoints;
        leftCodePoints = rightCodePoints;
        rightCodePoints = tempCodePoints;
    }
    if (rightCodePoints.length == 0) {
        return leftCodePoints.length;
    }
    checkCondition((leftCodePoints.length * (rightCodePoints.length - 1)) <= 1_000_000, INVALID_FUNCTION_ARGUMENT, "The combined inputs for Levenshtein distance are too large");
    int[] distances = new int[rightCodePoints.length];
    for (int i = 0; i < rightCodePoints.length; i++) {
        distances[i] = i + 1;
    }
    for (int i = 0; i < leftCodePoints.length; i++) {
        int leftUpDistance = distances[0];
        if (leftCodePoints[i] == rightCodePoints[0]) {
            distances[0] = i;
        } else {
            distances[0] = Math.min(i, distances[0]) + 1;
        }
        for (int j = 1; j < rightCodePoints.length; j++) {
            int leftUpDistanceNext = distances[j];
            if (leftCodePoints[i] == rightCodePoints[j]) {
                distances[j] = leftUpDistance;
            } else {
                distances[j] = Math.min(distances[j - 1], Math.min(leftUpDistance, distances[j])) + 1;
            }
            leftUpDistance = leftUpDistanceNext;
        }
    }
    return distances[rightCodePoints.length - 1];
}
Also used : Constraint(io.trino.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) 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 13 with Description

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

the class StringFunctions method translate.

@Description("Translate characters from the source string based on original and translations strings")
@ScalarFunction
@LiteralParameters({ "x", "y", "z" })
@SqlType(StandardTypes.VARCHAR)
public static Slice translate(@SqlType("varchar(x)") Slice source, @SqlType("varchar(y)") Slice from, @SqlType("varchar(z)") Slice to) {
    int[] fromCodePoints = castToCodePoints(from);
    int[] toCodePoints = castToCodePoints(to);
    Int2IntOpenHashMap map = new Int2IntOpenHashMap(fromCodePoints.length);
    for (int index = 0; index < fromCodePoints.length; index++) {
        int fromCodePoint = fromCodePoints[index];
        map.putIfAbsent(fromCodePoint, index < toCodePoints.length ? toCodePoints[index] : -1);
    }
    int[] sourceCodePoints = castToCodePoints(source);
    int[] targetCodePoints = new int[sourceCodePoints.length];
    int targetPositions = 0;
    int targetBytes = 0;
    for (int index = 0; index < sourceCodePoints.length; index++) {
        int codePoint = sourceCodePoints[index];
        if (map.containsKey(codePoint)) {
            int translatedCodePoint = map.get(codePoint);
            if (translatedCodePoint == -1) {
                continue;
            }
            codePoint = translatedCodePoint;
        }
        targetCodePoints[targetPositions++] = codePoint;
        targetBytes += lengthOfCodePoint(codePoint);
    }
    Slice target = Slices.allocate(targetBytes);
    int offset = 0;
    for (int index = 0; index < targetPositions; index++) {
        offset += setCodePointAt(targetCodePoints[index], target, offset);
    }
    return target;
}
Also used : Slice(io.airlift.slice.Slice) Slices.utf8Slice(io.airlift.slice.Slices.utf8Slice) Int2IntOpenHashMap(it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap) Constraint(io.trino.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) 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 14 with Description

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

the class BingTileFunctions method geometryToBingTiles.

@Description("Given a geometry and a zoom level, returns the minimum set of Bing tiles that fully covers that geometry")
@ScalarFunction("geometry_to_bing_tiles")
@SqlType("array(" + BingTileType.NAME + ")")
public static Block geometryToBingTiles(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType(StandardTypes.INTEGER) long zoomLevelInput) {
    checkZoomLevel(zoomLevelInput);
    int zoomLevel = toIntExact(zoomLevelInput);
    OGCGeometry ogcGeometry = deserialize(input);
    if (ogcGeometry.isEmpty()) {
        return EMPTY_TILE_ARRAY;
    }
    Envelope envelope = getEnvelope(ogcGeometry);
    checkLatitude(envelope.getYMin(), LATITUDE_SPAN_OUT_OF_RANGE);
    checkLatitude(envelope.getYMax(), LATITUDE_SPAN_OUT_OF_RANGE);
    checkLongitude(envelope.getXMin(), LONGITUDE_SPAN_OUT_OF_RANGE);
    checkLongitude(envelope.getXMax(), LONGITUDE_SPAN_OUT_OF_RANGE);
    boolean pointOrRectangle = isPointOrRectangle(ogcGeometry, envelope);
    BingTile leftUpperTile = latitudeLongitudeToTile(envelope.getYMax(), envelope.getXMin(), zoomLevel);
    BingTile rightLowerTile = getTileCoveringLowerRightCorner(envelope, zoomLevel);
    // XY coordinates start at (0,0) in the left upper corner and increase left to right and top to bottom
    long tileCount = (long) (rightLowerTile.getX() - leftUpperTile.getX() + 1) * (rightLowerTile.getY() - leftUpperTile.getY() + 1);
    checkGeometryToBingTilesLimits(ogcGeometry, envelope, pointOrRectangle, tileCount, zoomLevel);
    BlockBuilder blockBuilder = BIGINT.createBlockBuilder(null, toIntExact(tileCount));
    if (pointOrRectangle || zoomLevel <= OPTIMIZED_TILING_MIN_ZOOM_LEVEL) {
        // all tiles covering the bounding box intersect the geometry.
        for (int x = leftUpperTile.getX(); x <= rightLowerTile.getX(); x++) {
            for (int y = leftUpperTile.getY(); y <= rightLowerTile.getY(); y++) {
                BingTile tile = BingTile.fromCoordinates(x, y, zoomLevel);
                if (pointOrRectangle || !disjoint(tileToEnvelope(tile), ogcGeometry)) {
                    BIGINT.writeLong(blockBuilder, tile.encode());
                }
            }
        }
    } else {
        // Intersection checks above are expensive. The logic below attempts to reduce the number
        // of these checks. The idea is to identify large tiles which are fully covered by the
        // geometry. For each such tile, we can cheaply compute all the containing tiles at
        // the right zoom level and append them to results in bulk. This way we perform a single
        // containment check instead of 2 to the power of level delta intersection checks, where
        // level delta is the difference between the desired zoom level and level of the large
        // tile covered by the geometry.
        BingTile[] tiles = getTilesInBetween(leftUpperTile, rightLowerTile, OPTIMIZED_TILING_MIN_ZOOM_LEVEL);
        for (BingTile tile : tiles) {
            appendIntersectingSubtiles(ogcGeometry, zoomLevel, tile, blockBuilder);
        }
    }
    return blockBuilder.build();
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) GeometryUtils.getEnvelope(io.trino.geospatial.GeometryUtils.getEnvelope) Envelope(com.esri.core.geometry.Envelope) Point(com.esri.core.geometry.Point) GeometryUtils.disjoint(io.trino.geospatial.GeometryUtils.disjoint) BlockBuilder(io.trino.spi.block.BlockBuilder) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) SqlType(io.trino.spi.function.SqlType)

Example 15 with Description

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

the class GeoFunctions method toSphericalGeography.

@Description("Converts a Geometry object to a SphericalGeography object")
@ScalarFunction("to_spherical_geography")
@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME)
public static Slice toSphericalGeography(@SqlType(GEOMETRY_TYPE_NAME) Slice input) {
    // "every point in input is in range" <=> "the envelope of input is in range"
    Envelope envelope = deserializeEnvelope(input);
    if (!envelope.isEmpty()) {
        checkLatitude(envelope.getYMin());
        checkLatitude(envelope.getYMax());
        checkLongitude(envelope.getXMin());
        checkLongitude(envelope.getXMax());
    }
    OGCGeometry geometry = deserialize(input);
    if (geometry.is3D()) {
        throw new TrinoException(INVALID_FUNCTION_ARGUMENT, "Cannot convert 3D geometry to a spherical geography");
    }
    GeometryCursor cursor = geometry.getEsriGeometryCursor();
    while (true) {
        com.esri.core.geometry.Geometry subGeometry = cursor.next();
        if (subGeometry == null) {
            break;
        }
        if (!GEOMETRY_TYPES_FOR_SPHERICAL_GEOGRAPHY.contains(subGeometry.getType())) {
            throw new TrinoException(INVALID_FUNCTION_ARGUMENT, "Cannot convert geometry of this type to spherical geography: " + subGeometry.getType());
        }
    }
    return input;
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) GeometryCursor(com.esri.core.geometry.GeometryCursor) ListeningGeometryCursor(com.esri.core.geometry.ListeningGeometryCursor) TrinoException(io.trino.spi.TrinoException) GeometrySerde.deserializeEnvelope(io.trino.geospatial.serde.GeometrySerde.deserializeEnvelope) Envelope(com.esri.core.geometry.Envelope) ScalarFunction(io.trino.spi.function.ScalarFunction) Description(io.trino.spi.function.Description) SqlType(io.trino.spi.function.SqlType)

Aggregations

Description (io.trino.spi.function.Description)92 ScalarFunction (io.trino.spi.function.ScalarFunction)90 SqlType (io.trino.spi.function.SqlType)90 OGCGeometry (com.esri.core.geometry.ogc.OGCGeometry)46 SqlNullable (io.trino.spi.function.SqlNullable)38 LiteralParameters (io.trino.spi.function.LiteralParameters)19 Constraint (io.trino.type.Constraint)18 Point (com.esri.core.geometry.Point)17 OGCPoint (com.esri.core.geometry.ogc.OGCPoint)17 Slice (io.airlift.slice.Slice)17 BlockBuilder (io.trino.spi.block.BlockBuilder)16 MultiPoint (com.esri.core.geometry.MultiPoint)15 TrinoException (io.trino.spi.TrinoException)15 SliceUtf8.lengthOfCodePoint (io.airlift.slice.SliceUtf8.lengthOfCodePoint)8 SliceUtf8.offsetOfCodePoint (io.airlift.slice.SliceUtf8.offsetOfCodePoint)8 Matcher (io.airlift.joni.Matcher)7 GeometryType (io.trino.geospatial.GeometryType)7 Envelope (com.esri.core.geometry.Envelope)5 MultiPath (com.esri.core.geometry.MultiPath)5 MultiVertexGeometry (com.esri.core.geometry.MultiVertexGeometry)5