private static boolean valueEquals( Type type, Slice leftSlice, int leftOffset, Slice rightSlice, int rightOffset) { // check if null flags are the same boolean leftIsNull = leftSlice.getByte(leftOffset) != 0; boolean rightIsNull = rightSlice.getByte(rightOffset) != 0; if (leftIsNull != rightIsNull) { return false; } // if values are both null, they are equal if (leftIsNull) { return true; } if (type == Type.FIXED_INT_64 || type == Type.DOUBLE) { long leftValue = leftSlice.getLong(leftOffset + SIZE_OF_BYTE); long rightValue = rightSlice.getLong(rightOffset + SIZE_OF_BYTE); return leftValue == rightValue; } else if (type == Type.BOOLEAN) { boolean leftValue = leftSlice.getByte(leftOffset + SIZE_OF_BYTE) != 0; boolean rightValue = rightSlice.getByte(rightOffset + SIZE_OF_BYTE) != 0; return leftValue == rightValue; } else if (type == Type.VARIABLE_BINARY) { int leftLength = getVariableBinaryLength(leftSlice, leftOffset); int rightLength = getVariableBinaryLength(rightSlice, rightOffset); return leftSlice.equals( leftOffset + SIZE_OF_BYTE + SIZE_OF_INT, leftLength, rightSlice, rightOffset + SIZE_OF_BYTE + SIZE_OF_INT, rightLength); } else { throw new IllegalArgumentException("Unsupported type " + type); } }
@Description("returns index of first occurrence of a substring (or 0 if not found)") @ScalarFunction("strpos") @SqlType(BigintType.class) public static long stringPosition( @SqlType(VarcharType.class) Slice string, @SqlType(VarcharType.class) Slice substring) { if (substring.length() > string.length()) { return 0; } for (int i = 0; i <= (string.length() - substring.length()); i++) { if (string.equals(i, substring.length(), substring, 0, substring.length())) { return i + 1; } } return 0; }
// TODO: Implement a more efficient string search @Nullable @Description("splits a string by a delimiter and returns the specified field (counting from one)") @ScalarFunction @SqlType(VarcharType.class) public static Slice splitPart( @SqlType(VarcharType.class) Slice string, @SqlType(VarcharType.class) Slice delimiter, @SqlType(BigintType.class) long index) { checkArgument(index > 0, "Index must be greater than zero"); if (delimiter.length() == 0) { if (index > string.length()) { // index is too big, null is returned return null; } return string.slice((int) (index - 1), 1); } int previousIndex = 0; int matchCount = 0; for (int i = 0; i <= (string.length() - delimiter.length()); i++) { if (string.equals(i, delimiter.length(), delimiter, 0, delimiter.length())) { matchCount++; if (matchCount == index) { return string.slice(previousIndex, i - previousIndex); } // noinspection AssignmentToForLoopParameter i += (delimiter.length() - 1); previousIndex = i + 1; } } 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; }