@Description("substring of given length starting at an index") @ScalarFunction @SqlType(VarcharType.class) public static Slice substr( @SqlType(VarcharType.class) Slice slice, @SqlType(BigintType.class) long start, @SqlType(BigintType.class) long length) { if ((start == 0) || (length <= 0)) { return Slices.EMPTY_SLICE; } if (start > 0) { // make start zero-based start--; } else { // negative start is relative to end of string start += slice.length(); if (start < 0) { return Slices.EMPTY_SLICE; } } if ((start + length) > slice.length()) { length = slice.length() - start; } if (start >= slice.length()) { return Slices.EMPTY_SLICE; } return slice.slice((int) start, (int) length); }
private static int firstNonSpace(Slice slice) { for (int i = 0; i < slice.length(); i++) { if (slice.getByte(i) != ' ') { return i; } } return slice.length(); }
@Description("converts all the alphabets in the string to upper case") @ScalarFunction @SqlType(VarcharType.class) public static Slice upper(@SqlType(VarcharType.class) Slice slice) { Slice upper = Slices.allocate(slice.length()); for (int i = 0; i < slice.length(); i++) { upper.setByte(i, Ascii.toUpperCase((char) slice.getByte(i))); } return upper; }
@Description("concatenates given strings") @ScalarFunction @SqlType(VarcharType.class) public static Slice concat( @SqlType(VarcharType.class) Slice str1, @SqlType(VarcharType.class) Slice str2) { Slice concat = Slices.allocate(str1.length() + str2.length()); concat.setBytes(0, str1); concat.setBytes(str1.length(), str2); return concat; }
@Description("reverses the given string") @ScalarFunction @SqlType(VarcharType.class) public static Slice reverse(@SqlType(VarcharType.class) Slice slice) { Slice reverse = Slices.allocate(slice.length()); for (int i = 0, j = slice.length() - 1; i < slice.length(); i++, j--) { reverse.setByte(j, slice.getByte(i)); } return reverse; }
@Override public void serialize(MaxOrMinByState state, BlockBuilder out) { SliceOutput sliceOutput = new DynamicSliceOutput((int) state.getEstimatedSize()); int keyLength = 0; if (state.getKey() != null && !state.getKey().isNull(0)) { keyLength = state.getKey().getLength(0); } sliceOutput.writeInt(keyLength); int valueLength = 0; if (state.getValue() != null && !state.getValue().isNull(0)) { valueLength = state.getValue().getLength(0); } sliceOutput.writeInt(valueLength); if (state.getKey() != null && !state.getKey().isNull(0)) { appendTo(keyType, sliceOutput, state.getKey()); } if (state.getValue() != null && !state.getValue().isNull(0)) { appendTo(valueType, sliceOutput, state.getValue()); } Slice slice = sliceOutput.slice(); out.writeBytes(slice, 0, slice.length()); out.closeEntry(); }
@Description("removes spaces from the beginning of a string") @ScalarFunction("ltrim") @SqlType(VarcharType.class) public static Slice leftTrim(@SqlType(VarcharType.class) Slice slice) { int start = firstNonSpace(slice); return slice.slice(start, slice.length() - start); }
@Description("suffix starting at given index") @ScalarFunction @SqlType(VarcharType.class) public static Slice substr( @SqlType(VarcharType.class) Slice slice, @SqlType(BigintType.class) long start) { return substr(slice, start, slice.length()); }
private static int lastNonSpace(Slice slice) { for (int i = slice.length() - 1; i >= 0; i--) { if (slice.getByte(i) != ' ') { return i; } } return -1; }
private Block createZeroBlock(Type type, int rowsCount, Slice constantSlice) { checkArgument(isSupportedType(type), "Unsupported type [%s]", type); Slice slice; // do not exceed varchar limit if (isVarcharType(type)) { slice = constantSlice.slice( 0, Math.min(((VarcharType) type).getLength(), constantSlice.length())); } else if (isLongDecimal(type)) { slice = encodeScaledValue(ZERO); } else { slice = constantSlice; } BlockBuilder builder; if (type instanceof FixedWidthType) { builder = type.createBlockBuilder(new BlockBuilderStatus(), rowsCount); } else { builder = type.createBlockBuilder(new BlockBuilderStatus(), rowsCount, slice.length()); } for (int i = 0; i < rowsCount; i++) { Class<?> javaType = type.getJavaType(); if (javaType == boolean.class) { type.writeBoolean(builder, false); } else if (javaType == long.class) { type.writeLong(builder, 0); } else if (javaType == double.class) { type.writeDouble(builder, 0.0); } else if (javaType == Slice.class) { requireNonNull(slice, "slice is null"); type.writeSlice(builder, slice, 0, slice.length()); } else { throw new UnsupportedOperationException("Unknown javaType: " + javaType.getName()); } } return builder.build(); }
@Description("removes spaces from the beginning and end of a string") @ScalarFunction @SqlType(VarcharType.class) public static Slice trim(@SqlType(VarcharType.class) Slice slice) { int start = firstNonSpace(slice); if (start == slice.length()) { return Slices.EMPTY_SLICE; } int end = lastNonSpace(slice); assert (end >= 0) && (end >= start); return slice.slice(start, (end - start) + 1); }
// 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; }
@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; }
@Override public BlockBuilder appendSlice(Slice value) { return appendSlice(value, 0, value.length()); }
@SuppressWarnings("fallthrough") public static DateTimeFormatter createDateTimeFormatter(Slice format) { DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); String formatString = format.toString(Charsets.UTF_8); boolean escaped = false; for (int i = 0; i < format.length(); i++) { char character = formatString.charAt(i); if (escaped) { switch (character) { case 'a': // %a Abbreviated weekday name (Sun..Sat) builder.appendDayOfWeekShortText(); break; case 'b': // %b Abbreviated month name (Jan..Dec) builder.appendMonthOfYearShortText(); break; case 'c': // %c Month, numeric (0..12) builder.appendMonthOfYear(1); break; case 'd': // %d Day of the month, numeric (00..31) builder.appendDayOfMonth(2); break; case 'e': // %e Day of the month, numeric (0..31) builder.appendDayOfMonth(1); break; case 'f': // %f Microseconds (000000..999999) builder.appendMillisOfSecond(6); break; case 'H': // %H Hour (00..23) builder.appendHourOfDay(2); break; case 'h': // %h Hour (01..12) case 'I': // %I Hour (01..12) builder.appendClockhourOfHalfday(2); break; case 'i': // %i Minutes, numeric (00..59) builder.appendMinuteOfHour(2); break; case 'j': // %j Day of year (001..366) builder.appendDayOfYear(3); break; case 'k': // %k Hour (0..23) builder.appendClockhourOfDay(1); break; case 'l': // %l Hour (1..12) builder.appendClockhourOfHalfday(1); break; case 'M': // %M Month name (January..December) builder.appendMonthOfYearText(); break; case 'm': // %m Month, numeric (00..12) builder.appendMonthOfYear(2); break; case 'p': // %p AM or PM builder.appendHalfdayOfDayText(); break; case 'r': // %r Time, 12-hour (hh:mm:ss followed by AM or PM) builder .appendClockhourOfHalfday(2) .appendLiteral(':') .appendMinuteOfHour(2) .appendLiteral(':') .appendSecondOfMinute(2) .appendLiteral(' ') .appendHalfdayOfDayText(); break; case 'S': // %S Seconds (00..59) case 's': // %s Seconds (00..59) builder.appendSecondOfMinute(2); break; case 'T': // %T Time, 24-hour (hh:mm:ss) builder .appendHourOfDay(2) .appendLiteral(':') .appendMinuteOfHour(2) .appendLiteral(':') .appendSecondOfMinute(2); break; case 'v': // %v Week (01..53), where Monday is the first day of the week; used with %x builder.appendWeekOfWeekyear(2); break; case 'x': // %x Year for the week, where Monday is the first day of the week, numeric, // four digits; used with %v builder.appendWeekyear(4, 4); break; case 'W': // %W Weekday name (Sunday..Saturday) builder.appendDayOfWeekText(); break; case 'w': // %w Day of the week (0=Sunday..6=Saturday) builder.appendDayOfWeek(1); break; case 'Y': // %Y Year, numeric, four digits builder.appendYear(4, 4); break; case 'y': // %y Year, numeric (two digits) builder.appendYearOfCentury(2, 2); break; case 'U': // %U Week (00..53), where Sunday is the first day of the week case 'u': // %u Week (00..53), where Monday is the first day of the week case 'V': // %V Week (01..53), where Sunday is the first day of the week; used with %X case 'X': // %X Year for the week where Sunday is the first day of the week, numeric, four // digits; used with %V case 'D': // %D Day of the month with English suffix (0th, 1st, 2nd, 3rd, …) throw new PrestoException( INVALID_FUNCTION_ARGUMENT.toErrorCode(), String.format("%%%s not supported in date format string", character)); case '%': // %% A literal “%” character builder.appendLiteral('%'); break; default: // %<x> The literal character represented by <x> builder.appendLiteral(character); break; } escaped = false; } else if (character == '%') { escaped = true; } else { builder.appendLiteral(character); } } try { return builder.toFormatter(); } catch (UnsupportedOperationException e) { throw new PrestoException(INVALID_FUNCTION_ARGUMENT.toErrorCode(), e); } }
public long getMemorySize() { return slice.length() + sizeOf(positionOffsets.elements()); }
@Description("length of the given string") @ScalarFunction @SqlType(BigintType.class) public static long length(@SqlType(VarcharType.class) Slice slice) { return slice.length(); }