use of com.facebook.presto.common.type.MapType in project presto by prestodb.
the class MapZipWithFunction method mapZipWith.
public static Block mapZipWith(Type keyType, Type leftValueType, Type rightValueType, MapType outputMapType, MethodHandle keyNativeHashCode, MethodHandle keyBlockNativeEquals, MethodHandle keyBlockHashCode, Block leftBlock, Block rightBlock, MapZipWithLambda function) {
SingleMapBlock leftMapBlock = (SingleMapBlock) leftBlock;
SingleMapBlock rightMapBlock = (SingleMapBlock) rightBlock;
Type outputValueType = outputMapType.getValueType();
BlockBuilder mapBlockBuilder = outputMapType.createBlockBuilder(null, max(leftMapBlock.getPositionCount(), rightMapBlock.getPositionCount()) / 2);
BlockBuilder blockBuilder = mapBlockBuilder.beginBlockEntry();
// seekKey() can take non-trivial time when key is complicated value, such as a long VARCHAR or ROW.
boolean[] keyFound = new boolean[rightMapBlock.getPositionCount()];
for (int leftKeyPosition = 0; leftKeyPosition < leftMapBlock.getPositionCount(); leftKeyPosition += 2) {
Object key = readNativeValue(keyType, leftMapBlock, leftKeyPosition);
Object leftValue = readNativeValue(leftValueType, leftMapBlock, leftKeyPosition + 1);
int rightValuePosition;
try {
rightValuePosition = rightMapBlock.seekKey(key, keyNativeHashCode, keyBlockNativeEquals, keyBlockHashCode);
} catch (NotSupportedException e) {
throw new PrestoException(NOT_SUPPORTED, e.getMessage(), e);
}
Object rightValue = null;
if (rightValuePosition != -1) {
rightValue = readNativeValue(rightValueType, rightMapBlock, rightValuePosition);
keyFound[rightValuePosition / 2] = true;
}
Object outputValue;
try {
outputValue = function.apply(key, leftValue, rightValue);
} catch (Throwable throwable) {
// Restore pageBuilder into a consistent state.
mapBlockBuilder.closeEntry();
throwIfUnchecked(throwable);
throw new RuntimeException(throwable);
}
keyType.appendTo(leftMapBlock, leftKeyPosition, blockBuilder);
writeNativeValue(outputValueType, blockBuilder, outputValue);
}
// iterate over keys that only exists in rightMapBlock
for (int rightKeyPosition = 0; rightKeyPosition < rightMapBlock.getPositionCount(); rightKeyPosition += 2) {
if (!keyFound[rightKeyPosition / 2]) {
Object key = readNativeValue(keyType, rightMapBlock, rightKeyPosition);
Object rightValue = readNativeValue(rightValueType, rightMapBlock, rightKeyPosition + 1);
Object outputValue;
try {
outputValue = function.apply(key, null, rightValue);
} catch (Throwable throwable) {
// Restore pageBuilder into a consistent state.
mapBlockBuilder.closeEntry();
throwIfUnchecked(throwable);
throw new RuntimeException(throwable);
}
keyType.appendTo(rightMapBlock, rightKeyPosition, blockBuilder);
writeNativeValue(outputValueType, blockBuilder, outputValue);
}
}
mapBlockBuilder.closeEntry();
return outputMapType.getObject(mapBlockBuilder, mapBlockBuilder.getPositionCount() - 1);
}
use of com.facebook.presto.common.type.MapType in project presto by prestodb.
the class JsonToMapCast method specialize.
@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
checkArgument(arity == 1, "Expected arity to be 1");
Type keyType = boundVariables.getTypeVariable("K");
Type valueType = boundVariables.getTypeVariable("V");
MapType mapType = (MapType) functionAndTypeManager.getParameterizedType(StandardTypes.MAP, ImmutableList.of(TypeSignatureParameter.of(keyType.getTypeSignature()), TypeSignatureParameter.of(valueType.getTypeSignature())));
checkCondition(canCastFromJson(mapType), INVALID_CAST_ARGUMENT, "Cannot cast JSON to %s", mapType);
BlockBuilderAppender keyAppender = createBlockBuilderAppender(mapType.getKeyType());
BlockBuilderAppender valueAppender = createBlockBuilderAppender(mapType.getValueType());
MethodHandle methodHandle = METHOD_HANDLE.bindTo(mapType).bindTo(keyAppender).bindTo(valueAppender);
return new BuiltInScalarFunctionImplementation(true, ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), methodHandle);
}
use of com.facebook.presto.common.type.MapType in project presto by prestodb.
the class MapConcatFunction method specialize.
@Override
public BuiltInScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, FunctionAndTypeManager functionAndTypeManager) {
if (arity < 2) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "There must be two or more concatenation arguments to " + FUNCTION_NAME);
}
Type keyType = boundVariables.getTypeVariable("K");
Type valueType = boundVariables.getTypeVariable("V");
MapType mapType = (MapType) functionAndTypeManager.getParameterizedType(StandardTypes.MAP, ImmutableList.of(TypeSignatureParameter.of(keyType.getTypeSignature()), TypeSignatureParameter.of(valueType.getTypeSignature())));
VarArgMethodHandle varArgMethodHandle = generateVarArgsToArrayAdapter(Block.class, Block.class, arity, METHOD_HANDLE.bindTo(mapType));
return new BuiltInScalarFunctionImplementation(false, nCopies(arity, valueTypeArgumentProperty(RETURN_NULL_ON_NULL)), varArgMethodHandle.getMethodHandle());
}
use of com.facebook.presto.common.type.MapType in project presto by prestodb.
the class MapConcatFunction method mapConcat.
@UsedByGeneratedCode
public static Block mapConcat(MapType mapType, Block[] maps) {
int entries = 0;
int lastMapIndex = maps.length - 1;
int firstMapIndex = lastMapIndex;
for (int i = 0; i < maps.length; i++) {
entries += maps[i].getPositionCount();
if (maps[i].getPositionCount() > 0) {
lastMapIndex = i;
firstMapIndex = min(firstMapIndex, i);
}
}
if (lastMapIndex == firstMapIndex) {
return maps[lastMapIndex];
}
Type keyType = mapType.getKeyType();
Type valueType = mapType.getValueType();
// We need to divide the entries by 2 because the maps array is SingleMapBlocks and it had the positionCount twice as large as a normal Block
OptimizedTypedSet typedSet = new OptimizedTypedSet(keyType, maps.length, entries / 2);
for (int i = lastMapIndex; i >= firstMapIndex; i--) {
SingleMapBlock singleMapBlock = (SingleMapBlock) maps[i];
Block keyBlock = singleMapBlock.getKeyBlock();
typedSet.union(keyBlock);
}
List<SelectedPositions> selectedPositionsList = typedSet.getPositionsForBlocks();
BlockBuilder mapBlockBuilder = mapType.createBlockBuilder(null, selectedPositionsList.size());
BlockBuilder blockBuilder = mapBlockBuilder.beginBlockEntry();
for (int i = lastMapIndex; i >= firstMapIndex; i--) {
SingleMapBlock singleMapBlock = (SingleMapBlock) maps[i];
// selectedPositions was ordered by addUnion sequence therefore the order should be reversed.
SelectedPositions selectedPositions = selectedPositionsList.get(lastMapIndex - i);
assert selectedPositions.isList();
int[] positions = selectedPositions.getPositions();
for (int j = 0; j < selectedPositions.size(); j++) {
int position = positions[j];
keyType.appendTo(singleMapBlock, 2 * position, blockBuilder);
valueType.appendTo(singleMapBlock, 2 * position + 1, blockBuilder);
}
}
mapBlockBuilder.closeEntry();
return mapType.getObject(mapBlockBuilder, mapBlockBuilder.getPositionCount() - 1);
}
use of com.facebook.presto.common.type.MapType in project presto by prestodb.
the class MapDistinctFromOperator method isDistinctFrom.
@TypeParameter("K")
@TypeParameter("V")
@SqlType(StandardTypes.BOOLEAN)
public static boolean isDistinctFrom(@OperatorDependency(operator = EQUAL, argumentTypes = { "K", "K" }) MethodHandle keyEqualsFunction, @OperatorDependency(operator = HASH_CODE, argumentTypes = { "K" }) MethodHandle keyHashcodeFunction, @OperatorDependency(operator = IS_DISTINCT_FROM, argumentTypes = { "V", "V" }, convention = @Convention(arguments = { BLOCK_POSITION, BLOCK_POSITION }, result = FAIL_ON_NULL)) MethodHandle valueDistinctFromFunction, @TypeParameter("map(K, V)") Type mapType, @SqlType("map(K,V)") Block leftMapBlock, @IsNull boolean leftMapNull, @SqlType("map(K,V)") Block rightMapBlock, @IsNull boolean rightMapNull) {
if (leftMapNull != rightMapNull) {
return true;
}
if (leftMapNull) {
return false;
}
Type keyType = ((MapType) mapType).getKeyType();
MethodHandle keyBlockEqualsFunction = compose(keyEqualsFunction, nativeValueGetter(keyType));
MethodHandle keyBlockHashCodeFunction = compose(keyHashcodeFunction, nativeValueGetter(keyType));
// Note that we compare to NOT distinct here and so negate the result.
return !MapGenericEquality.genericEqual(keyType, keyHashcodeFunction, keyBlockEqualsFunction, keyBlockHashCodeFunction, leftMapBlock, rightMapBlock, (leftMapIndex, rightMapIndex) -> !(boolean) valueDistinctFromFunction.invokeExact(leftMapBlock, leftMapIndex, rightMapBlock, rightMapIndex));
}
Aggregations