Skip to content

Commit

Permalink
Plan generator now uses Cascades's FunctionCatalog. (#3061)
Browse files Browse the repository at this point in the history
- Remove plan generator own FunctionCatalog and rely on Cascades's FunctionCatalog.
- Reduces code complexity.
  • Loading branch information
hatyo authored Feb 7, 2025
1 parent 8de74f2 commit 83a2373
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package com.apple.foundationdb.record.query.plan.cascades.values;

import com.apple.foundationdb.record.query.plan.cascades.BuiltInFunction;
import com.apple.foundationdb.record.query.plan.cascades.typing.Type;
import com.apple.foundationdb.record.query.plan.cascades.typing.Typed;
import com.apple.foundationdb.record.util.ServiceLoaderProvider;
import com.google.common.base.Suppliers;
Expand All @@ -30,7 +29,6 @@
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -72,11 +70,7 @@ private static Map<FunctionKey, BuiltInFunction<? extends Typed>> loadFunctions(
return catalogBuilder.build();
}

public static Optional<BuiltInFunction<? extends Typed>> resolveAndValidate(@Nonnull final String functionName, List<Type> argumentTypes) {
return resolve(functionName, argumentTypes.size())
.flatMap(builtInFunction -> builtInFunction.validateCall(argumentTypes));
}

@Nonnull
@SuppressWarnings("java:S1066")
public static Optional<BuiltInFunction<? extends Typed>> resolve(@Nonnull final String functionName, int numberOfArguments) {
BuiltInFunction<? extends Typed> builtInFunction = getFunctionCatalog().get(new FunctionKey(functionName, numberOfArguments, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,14 @@ public final String getFunctionName() {
@Nonnull
protected abstract UdfValue newCallsite(@Nonnull List<Value> arguments);

@SuppressWarnings("unchecked")
@Nonnull
@Override
public final Typed encapsulate(@Nonnull final List<? extends Typed> arguments) {
arguments.forEach(argument -> Verify.verify(argument instanceof Value));
final List<Type> parameterTypes = getParameterTypes();
if (arguments.size() != parameterTypes.size()) {
final String udfName = getFunctionName();
throw new RecordCoreException("attempt to call '%s' with incorrect number of parameters", udfName);
throw new RecordCoreException("attempt to call " + udfName + " with incorrect number of parameters");
}

final ImmutableList.Builder<Value> promotedArgumentsList = ImmutableList.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2021-2024 Apple Inc. and the FoundationDB project authors
* Copyright 2021-2025 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,6 +25,7 @@
import com.apple.foundationdb.record.query.plan.cascades.Column;
import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier;
import com.apple.foundationdb.record.query.plan.cascades.Quantifier;
import com.apple.foundationdb.record.query.plan.cascades.typing.Type;
import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue;
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
import com.apple.foundationdb.relational.util.Assert;
Expand Down Expand Up @@ -196,6 +197,11 @@ public Iterable<Value> underlying() {
return Streams.stream(this).map(Expression::getUnderlying).collect(ImmutableList.toImmutableList());
}

@Nonnull
public List<Type> underlyingTypes() {
return Streams.stream(underlying()).map(Value::getResultType).collect(ImmutableList.toImmutableList());
}

@Nonnull
public Stream<Expression> stream() {
return underlying.stream();
Expand Down Expand Up @@ -229,6 +235,12 @@ public static Expressions of(@Nonnull Iterable<Expression> expressions) {
return new Expressions(expressions);
}

@Nonnull
public static Expressions of(@Nonnull final Expression[] expressions) {
List<Expression> expressionsList = ImmutableList.copyOf(expressions);
return Expressions.of(expressionsList);
}

@Nonnull
public static Expressions ofSingle(@Nonnull Expression expression) {
return new Expressions(ImmutableList.of(expression));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2021-2024 Apple Inc. and the FoundationDB project authors
* Copyright 2021-2025 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -36,7 +36,6 @@
import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue;
import com.apple.foundationdb.record.query.plan.cascades.values.InOpValue;
import com.apple.foundationdb.record.query.plan.cascades.values.IndexableAggregateValue;
import com.apple.foundationdb.record.query.plan.cascades.values.JavaCallFunction;
import com.apple.foundationdb.record.query.plan.cascades.values.LiteralValue;
import com.apple.foundationdb.record.query.plan.cascades.values.NotValue;
import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue;
Expand All @@ -52,8 +51,8 @@
import com.apple.foundationdb.relational.api.metadata.Table;
import com.apple.foundationdb.relational.generated.RelationalParser;
import com.apple.foundationdb.relational.recordlayer.metadata.DataTypeUtils;
import com.apple.foundationdb.relational.recordlayer.query.functions.FunctionCatalog;
import com.apple.foundationdb.relational.recordlayer.query.functions.SqlFunctionCatalog;
import com.apple.foundationdb.relational.recordlayer.query.functions.SqlFunctionCatalogImpl;
import com.apple.foundationdb.relational.recordlayer.query.visitors.QueryVisitor;
import com.apple.foundationdb.relational.util.Assert;
import com.google.common.base.Equivalence;
Expand Down Expand Up @@ -95,10 +94,10 @@ public class SemanticAnalyzer {
private final SchemaTemplate metadataCatalog;

@Nonnull
private final FunctionCatalog functionCatalog;
private final SqlFunctionCatalog functionCatalog;

public SemanticAnalyzer(@Nonnull SchemaTemplate metadataCatalog,
@Nonnull FunctionCatalog functionCatalog) {
@Nonnull SqlFunctionCatalog functionCatalog) {
this.metadataCatalog = metadataCatalog;
this.functionCatalog = functionCatalog;
}
Expand Down Expand Up @@ -723,39 +722,39 @@ public static void validateContinuation(@Nonnull Expression continuation) {
}

/**
* Resolves a function given its name and a list of arguments by looking it up in the {@link FunctionCatalog}.
* Resolves a function given its name and a list of arguments by looking it up in the {@link SqlFunctionCatalog}.
* <br>
* Ideally, this overload should not exist, in other words, the caller should not be responsible for determining
* whether the single-item records should be flattened or not.
* Currently almost all supported SQL functions do not expect {@code Record} objects,
* so this is probably ok, however, this does not necessarily hold for the future.
* See {@link SqlFunctionCatalog#flattenRecordWithOneField(Typed)} for more information.
* See {@link SqlFunctionCatalogImpl#flattenRecordWithOneField(Typed)} for more information.
* @param functionName The function name.
* @param flattenSingleItemRecords {@code true} if single-item records should be (recursively) replaced with their
* content, otherwise {@code false}.
* @param arguments The function arguments.
* @return A resolved SQL function {@code Expression}.
*/
@Nonnull
public Expression resolveFunction(@Nonnull String functionName, boolean flattenSingleItemRecords,
@Nonnull Expression... arguments) {
public Expression resolveFunction(@Nonnull final String functionName, boolean flattenSingleItemRecords,
@Nonnull final Expression... arguments) {
Assert.thatUnchecked(functionCatalog.containsFunction(functionName), ErrorCode.UNSUPPORTED_QUERY,
() -> String.format("Unsupported operator %s", functionName));
final var builtInFunction = functionCatalog.lookUpFunction(functionName);
final var builtInFunction = functionCatalog.lookUpFunction(functionName, arguments);
List<Expression> argumentList = new ArrayList<>();
argumentList.addAll(List.of(arguments));
if (BITMAP_SCALAR_FUNCTIONS.contains(functionName.toLowerCase(Locale.ROOT))) {
argumentList.add(Expression.ofUnnamed(new LiteralValue<>(BITMAP_DEFAULT_ENTRY_SIZE)));
}
final List<? extends Typed> valueArgs = argumentList.stream().map(Expression::getUnderlying)
.map(v -> flattenSingleItemRecords ? SqlFunctionCatalog.flattenRecordWithOneField(v) : v)
.map(v -> flattenSingleItemRecords ? SqlFunctionCatalogImpl.flattenRecordWithOneField(v) : v)
.collect(ImmutableList.toImmutableList());
final var resultingValue = Assert.castUnchecked(builtInFunction.encapsulate(valueArgs), Value.class);
return Expression.ofUnnamed(DataTypeUtils.toRelationalType(resultingValue.getResultType()), resultingValue);
}

public boolean isUdfFunction(@Nonnull String functionName) {
return functionCatalog.lookUpFunction(functionName).getClass().equals(JavaCallFunction.class);
public boolean isUdfFunction(@Nonnull final String functionName) {
return functionCatalog.isUdfFunction(functionName);
}

public boolean containsReferencesTo(@Nonnull final ParseTree parseTree,
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 83a2373

Please sign in to comment.