use of com.facebook.presto.spi.function.SqlNullable in project presto by prestodb.
the class JsonFunctions method jsonArrayContains.
@SqlNullable
@ScalarFunction
@SqlType(StandardTypes.BOOLEAN)
public static Boolean jsonArrayContains(@SqlType(StandardTypes.JSON) Slice json, @SqlType(StandardTypes.DOUBLE) double value) {
if (!Doubles.isFinite(value)) {
return false;
}
try (JsonParser parser = createJsonParser(JSON_FACTORY, json)) {
if (parser.nextToken() != START_ARRAY) {
return null;
}
while (true) {
JsonToken token = parser.nextToken();
if (token == null) {
return null;
}
if (token == END_ARRAY) {
return false;
}
parser.skipChildren();
// noinspection FloatingPointEquality
if ((token == VALUE_NUMBER_FLOAT) && (parser.getDoubleValue() == value) && (Doubles.isFinite(parser.getDoubleValue()))) {
return true;
}
}
} catch (IOException e) {
return null;
}
}
use of com.facebook.presto.spi.function.SqlNullable in project presto by prestodb.
the class HyperLogLogFunctions method scalarMerge.
@ScalarFunction("merge_hll")
@Description("merge the contents of an array of HyperLogLogs")
@SqlType(StandardTypes.HYPER_LOG_LOG)
@SqlNullable
public static Slice scalarMerge(@SqlType("array(HyperLogLog)") Block block) {
if (block.getPositionCount() == 0) {
return null;
}
HyperLogLog merged = null;
int firstNonNullIndex = 0;
while (firstNonNullIndex < block.getPositionCount() && block.isNull(firstNonNullIndex)) {
firstNonNullIndex++;
}
if (firstNonNullIndex == block.getPositionCount()) {
return null;
}
Slice initialSlice = block.getSlice(firstNonNullIndex, 0, block.getSliceLength(firstNonNullIndex));
merged = HyperLogLog.newInstance(initialSlice);
for (int i = firstNonNullIndex; i < block.getPositionCount(); i++) {
Slice currentSlice = block.getSlice(i, 0, block.getSliceLength(i));
if (!block.isNull(i)) {
merged.mergeWith(HyperLogLog.newInstance(currentSlice));
}
}
return merged.serialize();
}
use of com.facebook.presto.spi.function.SqlNullable in project presto by prestodb.
the class JoniRegexpReplaceLambdaFunction method regexpReplace.
@LiteralParameters("x")
@SqlType("varchar")
@SqlNullable
public Slice regexpReplace(@SqlType("varchar") Slice source, @SqlType(JoniRegexpType.NAME) Regex 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.getBytes());
if (matcher.search(0, source.length(), Option.DEFAULT) == -1) {
return source;
}
SliceOutput output = new DynamicSliceOutput(source.length());
// Prepare a BlockBuilder that will be used to create the target block
// that will be passed to the lambda function.
BlockBuilder blockBuilder = VARCHAR.createBlockBuilder(null, 0);
int groupCount = pattern.numberOfCaptures();
int appendPosition = 0;
int nextStart = 0;
do {
// In such case, nextStart is last appendPosition + 1.
if (matcher.getEnd() == matcher.getBegin()) {
nextStart = matcher.getEnd() + 1;
} else {
nextStart = matcher.getEnd();
}
// Append the un-matched part
Slice unmatched = source.slice(appendPosition, matcher.getBegin() - appendPosition);
appendPosition = matcher.getEnd();
output.appendBytes(unmatched);
// Append the capturing groups to the target block that will be passed to lambda
Region matchedRegion = matcher.getEagerRegion();
for (int i = 1; i <= groupCount; i++) {
// Add to the block builder if the matched region is not null. In Joni null is represented as [-1, -1]
if (matchedRegion.beg[i] >= 0 && matchedRegion.end[i] >= 0) {
VARCHAR.writeSlice(blockBuilder, source, matchedRegion.beg[i], matchedRegion.end[i] - matchedRegion.beg[i]);
} else {
blockBuilder.appendNull();
}
}
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.search(nextStart, source.length(), Option.DEFAULT) != -1);
// Append the last un-matched part
output.writeBytes(source, appendPosition, source.length() - appendPosition);
return output.slice();
}
use of com.facebook.presto.spi.function.SqlNullable in project presto by prestodb.
the class JsonFunctions method jsonArrayGet.
@SqlNullable
@ScalarFunction
@SqlType(StandardTypes.JSON)
public static Slice jsonArrayGet(@SqlType(StandardTypes.JSON) Slice json, @SqlType(StandardTypes.BIGINT) long index) {
// this value cannot be converted to positive number
if (index == Long.MIN_VALUE) {
return null;
}
try (JsonParser parser = createJsonParser(MAPPING_JSON_FACTORY, json)) {
if (parser.nextToken() != START_ARRAY) {
return null;
}
List<String> tokens = null;
if (index < 0) {
tokens = new LinkedList<>();
}
long count = 0;
while (true) {
JsonToken token = parser.nextToken();
if (token == null) {
return null;
}
if (token == END_ARRAY) {
if (tokens != null && count >= index * -1) {
return utf8Slice(tokens.get(0));
}
return null;
}
String arrayElement;
if (token == START_OBJECT || token == START_ARRAY) {
arrayElement = parser.readValueAsTree().toString();
} else {
arrayElement = parser.getValueAsString();
}
if (count == index) {
return arrayElement == null ? null : utf8Slice(arrayElement);
}
if (tokens != null) {
tokens.add(arrayElement);
if (count >= index * -1) {
tokens.remove(0);
}
}
count++;
}
} catch (IOException e) {
return null;
}
}
use of com.facebook.presto.spi.function.SqlNullable in project presto by prestodb.
the class ArrayAnyMatchFunction method anyMatchBlock.
@TypeParameter("T")
@TypeParameterSpecialization(name = "T", nativeContainerType = Block.class)
@SqlType(StandardTypes.BOOLEAN)
@SqlNullable
public static Boolean anyMatchBlock(@TypeParameter("T") Type elementType, @SqlType("array(T)") Block arrayBlock, @SqlType("function(T, boolean)") BlockToBooleanFunction function) {
boolean hasNullResult = false;
for (int i = 0; i < arrayBlock.getPositionCount(); i++) {
Block element = null;
if (!arrayBlock.isNull(i)) {
element = (Block) elementType.getObject(arrayBlock, i);
}
Boolean match = function.apply(element);
if (TRUE.equals(match)) {
return true;
}
if (match == null) {
hasNullResult = true;
}
}
if (hasNullResult) {
return null;
}
return false;
}
Aggregations