Search in sources :

Example 81 with PrestoException

use of com.facebook.presto.spi.PrestoException in project presto by prestodb.

the class JoniRegexpFunctions method appendReplacement.

private static void appendReplacement(SliceOutput result, Slice source, Regex pattern, Region region, Slice replacement) {
    // Handle the following items:
    // 1. ${name};
    // 2. $0, $1, $123 (group 123, if exists; or group 12, if exists; or group 1);
    // 3. \\, \$, \t (literal 't').
    // 4. Anything that doesn't starts with \ or $ is considered regular bytes
    int idx = 0;
    while (idx < replacement.length()) {
        byte nextByte = replacement.getByte(idx);
        if (nextByte == '$') {
            idx++;
            if (idx == replacement.length()) {
                // not using checkArgument because `.toStringUtf8` is expensive
                throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Illegal replacement sequence: " + replacement.toStringUtf8());
            }
            nextByte = replacement.getByte(idx);
            int backref;
            if (nextByte == '{') {
                // case 1 in the above comment
                idx++;
                int startCursor = idx;
                while (idx < replacement.length()) {
                    nextByte = replacement.getByte(idx);
                    if (nextByte == '}') {
                        break;
                    }
                    idx++;
                }
                byte[] groupName = replacement.getBytes(startCursor, idx - startCursor);
                try {
                    backref = pattern.nameToBackrefNumber(groupName, 0, groupName.length, region);
                } catch (ValueException e) {
                    throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Illegal replacement sequence: unknown group { " + new String(groupName, StandardCharsets.UTF_8) + " }");
                }
                idx++;
            } else {
                // case 2 in the above comment
                backref = nextByte - '0';
                if (backref < 0 || backref > 9) {
                    // not using checkArgument because `.toStringUtf8` is expensive
                    throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Illegal replacement sequence: " + replacement.toStringUtf8());
                }
                if (region.numRegs <= backref) {
                    throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Illegal replacement sequence: unknown group " + backref);
                }
                idx++;
                while (idx < replacement.length()) {
                    // Adaptive group number: find largest group num that is not greater than actual number of groups
                    int nextDigit = replacement.getByte(idx) - '0';
                    if (nextDigit < 0 || nextDigit > 9) {
                        break;
                    }
                    int newBackref = (backref * 10) + nextDigit;
                    if (region.numRegs <= newBackref) {
                        break;
                    }
                    backref = newBackref;
                    idx++;
                }
            }
            int beg = region.beg[backref];
            int end = region.end[backref];
            if (beg != -1 && end != -1) {
                // the specific group doesn't exist in the current match, skip
                result.appendBytes(source.slice(beg, end - beg));
            }
        } else {
            // case 3 and 4 in the above comment
            if (nextByte == '\\') {
                idx++;
                if (idx == replacement.length()) {
                    // not using checkArgument because `.toStringUtf8` is expensive
                    throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Illegal replacement sequence: " + replacement.toStringUtf8());
                }
                nextByte = replacement.getByte(idx);
            }
            result.appendByte(nextByte);
            idx++;
        }
    }
}
Also used : ValueException(io.airlift.joni.exception.ValueException) PrestoException(com.facebook.presto.spi.PrestoException) Constraint(com.facebook.presto.type.Constraint)

Example 82 with PrestoException

use of com.facebook.presto.spi.PrestoException in project presto by prestodb.

the class ArrayJoin method specializeArrayJoin.

private static ScalarFunctionImplementation specializeArrayJoin(Map<String, Type> types, FunctionRegistry functionRegistry, List<Boolean> nullableArguments, MethodHandle methodHandle) {
    Type type = types.get("T");
    if (type instanceof UnknownType) {
        return new ScalarFunctionImplementation(false, nullableArguments, methodHandle.bindTo(null), true);
    } else {
        try {
            ScalarFunctionImplementation castFunction = functionRegistry.getScalarFunctionImplementation(internalOperator(CAST.name(), VARCHAR_TYPE_SIGNATURE, ImmutableList.of(type.getTypeSignature())));
            MethodHandle getter;
            Class<?> elementType = type.getJavaType();
            if (elementType == boolean.class) {
                getter = GET_BOOLEAN;
            } else if (elementType == double.class) {
                getter = GET_DOUBLE;
            } else if (elementType == long.class) {
                getter = GET_LONG;
            } else if (elementType == Slice.class) {
                getter = GET_SLICE;
            } else {
                throw new UnsupportedOperationException("Unsupported type: " + elementType.getClass().getName());
            }
            MethodHandle cast = castFunction.getMethodHandle();
            // if the cast doesn't take a ConnectorSession, create an adapter that drops the provided session
            if (cast.type().parameterArray()[0] != ConnectorSession.class) {
                cast = MethodHandles.dropArguments(cast, 0, ConnectorSession.class);
            }
            // Adapt a target cast that takes (ConnectorSession, ?) to one that takes (Block, int, ConnectorSession), which will be invoked by the implementation
            // The first two arguments (Block, int) are filtered through the element type's getXXX method to produce the underlying value that needs to be passed to
            // the cast.
            cast = MethodHandles.permuteArguments(cast, MethodType.methodType(Slice.class, cast.type().parameterArray()[1], cast.type().parameterArray()[0]), 1, 0);
            cast = MethodHandles.dropArguments(cast, 1, int.class);
            cast = MethodHandles.dropArguments(cast, 1, Block.class);
            cast = MethodHandles.foldArguments(cast, getter.bindTo(type));
            MethodHandle target = MethodHandles.insertArguments(methodHandle, 0, cast);
            return new ScalarFunctionImplementation(false, nullableArguments, target, true);
        } catch (PrestoException e) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Input type %s not supported", type), e);
        }
    }
}
Also used : UnknownType(com.facebook.presto.type.UnknownType) Type(com.facebook.presto.spi.type.Type) UnknownType(com.facebook.presto.type.UnknownType) MethodType(java.lang.invoke.MethodType) Slice(io.airlift.slice.Slice) Block(com.facebook.presto.spi.block.Block) ConnectorSession(com.facebook.presto.spi.ConnectorSession) PrestoException(com.facebook.presto.spi.PrestoException) MethodHandle(java.lang.invoke.MethodHandle)

Example 83 with PrestoException

use of com.facebook.presto.spi.PrestoException in project presto by prestodb.

the class StringFunctions method splitToMap.

@Description("creates a map using entryDelimiter and keyValueDelimiter")
@ScalarFunction
@SqlType("map<varchar,varchar>")
public static Block splitToMap(@SqlType(StandardTypes.VARCHAR) Slice string, @SqlType(StandardTypes.VARCHAR) Slice entryDelimiter, @SqlType(StandardTypes.VARCHAR) Slice keyValueDelimiter) {
    checkCondition(entryDelimiter.length() > 0, INVALID_FUNCTION_ARGUMENT, "entryDelimiter is empty");
    checkCondition(keyValueDelimiter.length() > 0, INVALID_FUNCTION_ARGUMENT, "keyValueDelimiter is empty");
    checkCondition(!entryDelimiter.equals(keyValueDelimiter), INVALID_FUNCTION_ARGUMENT, "entryDelimiter and keyValueDelimiter must not be the same");
    Map<Slice, Slice> map = new HashMap<>();
    int entryStart = 0;
    while (entryStart < string.length()) {
        // Extract key-value pair based on current index
        // then add the pair if it can be split by keyValueDelimiter
        Slice keyValuePair;
        int entryEnd = string.indexOf(entryDelimiter, entryStart);
        if (entryEnd >= 0) {
            keyValuePair = string.slice(entryStart, entryEnd - entryStart);
        } else {
            // The rest of the string is the last possible pair.
            keyValuePair = string.slice(entryStart, string.length() - entryStart);
        }
        int keyEnd = keyValuePair.indexOf(keyValueDelimiter);
        if (keyEnd >= 0) {
            int valueStart = keyEnd + keyValueDelimiter.length();
            Slice key = keyValuePair.slice(0, keyEnd);
            Slice value = keyValuePair.slice(valueStart, keyValuePair.length() - valueStart);
            if (value.indexOf(keyValueDelimiter) >= 0) {
                throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Key-value delimiter must appear exactly once in each entry. Bad input: '" + keyValuePair.toStringUtf8() + "'");
            }
            if (map.containsKey(key)) {
                throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Duplicate keys (%s) are not allowed", key.toStringUtf8()));
            }
            map.put(key, value);
        } else {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Key-value delimiter must appear exactly once in each entry. Bad input: '" + keyValuePair.toStringUtf8() + "'");
        }
        if (entryEnd < 0) {
            // No more pairs to add
            break;
        }
        // Next possible pair is placed next to the current entryDelimiter
        entryStart = entryEnd + entryDelimiter.length();
    }
    BlockBuilder builder = VARCHAR.createBlockBuilder(new BlockBuilderStatus(), map.size());
    for (Map.Entry<Slice, Slice> entry : map.entrySet()) {
        VARCHAR.writeSlice(builder, entry.getKey());
        VARCHAR.writeSlice(builder, entry.getValue());
    }
    return builder.build();
}
Also used : HashMap(java.util.HashMap) Slice(io.airlift.slice.Slice) Slices.utf8Slice(io.airlift.slice.Slices.utf8Slice) PrestoException(com.facebook.presto.spi.PrestoException) HashMap(java.util.HashMap) Map(java.util.Map) Constraint(com.facebook.presto.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder) BlockBuilderStatus(com.facebook.presto.spi.block.BlockBuilderStatus) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Example 84 with PrestoException

use of com.facebook.presto.spi.PrestoException in project presto by prestodb.

the class StringFunctions method safeCountCodePoints.

private static int safeCountCodePoints(Slice slice) {
    int codePoints = 0;
    for (int position = 0; position < slice.length(); ) {
        int codePoint = tryGetCodePointAt(slice, position);
        if (codePoint < 0) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Invalid UTF-8 encoding in characters: " + slice.toStringUtf8());
        }
        position += lengthOfCodePoint(codePoint);
        codePoints++;
    }
    return codePoints;
}
Also used : PrestoException(com.facebook.presto.spi.PrestoException) Constraint(com.facebook.presto.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint)

Example 85 with PrestoException

use of com.facebook.presto.spi.PrestoException in project presto by prestodb.

the class StringFunctions method fromUtf8.

@Description("decodes the UTF-8 encoded string")
@ScalarFunction
@LiteralParameters("x")
@SqlType(StandardTypes.VARCHAR)
public static Slice fromUtf8(@SqlType(StandardTypes.VARBINARY) Slice slice, @SqlType("varchar(x)") Slice replacementCharacter) {
    int count = countCodePoints(replacementCharacter);
    if (count > 1) {
        throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Replacement character string must empty or a single character");
    }
    OptionalInt replacementCodePoint;
    if (count == 1) {
        try {
            replacementCodePoint = OptionalInt.of(getCodePointAt(replacementCharacter, 0));
        } catch (InvalidUtf8Exception e) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Invalid replacement character");
        }
    } else {
        replacementCodePoint = OptionalInt.empty();
    }
    return SliceUtf8.fixInvalidUtf8(slice, replacementCodePoint);
}
Also used : InvalidUtf8Exception(io.airlift.slice.InvalidUtf8Exception) PrestoException(com.facebook.presto.spi.PrestoException) OptionalInt(java.util.OptionalInt) Constraint(com.facebook.presto.type.Constraint) SliceUtf8.lengthOfCodePoint(io.airlift.slice.SliceUtf8.lengthOfCodePoint) SliceUtf8.offsetOfCodePoint(io.airlift.slice.SliceUtf8.offsetOfCodePoint) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) LiteralParameters(com.facebook.presto.spi.function.LiteralParameters) SqlType(com.facebook.presto.spi.function.SqlType)

Aggregations

PrestoException (com.facebook.presto.spi.PrestoException)273 IOException (java.io.IOException)58 Type (com.facebook.presto.spi.type.Type)48 ImmutableList (com.google.common.collect.ImmutableList)40 SchemaTableName (com.facebook.presto.spi.SchemaTableName)32 ArrayList (java.util.ArrayList)32 List (java.util.List)28 Path (org.apache.hadoop.fs.Path)28 Map (java.util.Map)24 Slice (io.airlift.slice.Slice)23 TableNotFoundException (com.facebook.presto.spi.TableNotFoundException)22 SqlType (com.facebook.presto.spi.function.SqlType)22 ImmutableMap (com.google.common.collect.ImmutableMap)22 Optional (java.util.Optional)20 ColumnMetadata (com.facebook.presto.spi.ColumnMetadata)19 Block (com.facebook.presto.spi.block.Block)19 Test (org.testng.annotations.Test)19 ConnectorSession (com.facebook.presto.spi.ConnectorSession)17 Table (com.facebook.presto.hive.metastore.Table)15 Session (com.facebook.presto.Session)14