From bafb313d858d8bf0eb70103fae8494d46f934ba5 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Fri, 12 Sep 2025 16:44:15 +0100 Subject: [PATCH 1/6] reactivate amortization of plan generation of functions. - this works for both temporary and non-temporary functions. --- .../metadata/RecordLayerInvokedRoutine.java | 5 +- .../recordlayer/query/SemanticAnalyzer.java | 25 ++++++++- .../metadata/SchemaTemplateSerDeTests.java | 53 ++++++++++--------- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index 82f789bb7c..337af64e53 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -24,6 +24,7 @@ import com.apple.foundationdb.relational.api.metadata.InvokedRoutine; import com.apple.foundationdb.relational.recordlayer.query.functions.CompiledSqlFunction; import com.apple.foundationdb.relational.util.Assert; +import com.google.common.base.Suppliers; import javax.annotation.Nonnull; import java.util.Objects; @@ -55,7 +56,9 @@ public RecordLayerInvokedRoutine(@Nonnull final String description, this.name = name; this.isTemporary = isTemporary; // TODO this used to be memoized - this.compilableSqlFunctionSupplier = compilableSqlFunctionSupplier; + final var memoizedTrue = Suppliers.memoize(() -> compilableSqlFunctionSupplier.apply(true)); + final var memoizedFalse = Suppliers.memoize(() -> compilableSqlFunctionSupplier.apply(false)); + this.compilableSqlFunctionSupplier = param -> param ? memoizedTrue.get() : memoizedFalse.get(); } @Nonnull diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index e8e4bdca2a..9c227bc1b3 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -29,8 +29,11 @@ import com.apple.foundationdb.record.query.plan.cascades.Correlated; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; import com.apple.foundationdb.record.query.plan.cascades.IndexAccessHint; +import com.apple.foundationdb.record.query.plan.cascades.Memoizer; +import com.apple.foundationdb.record.query.plan.cascades.PlannerStage; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.Reference; +import com.apple.foundationdb.record.query.plan.cascades.References; import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.expressions.TableFunctionExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; @@ -48,6 +51,7 @@ import com.apple.foundationdb.record.query.plan.cascades.values.StreamableAggregateValue; import com.apple.foundationdb.record.query.plan.cascades.values.StreamingValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; +import com.apple.foundationdb.record.query.plan.cascades.values.translation.ToUniqueAliasesTranslationMap; import com.apple.foundationdb.record.util.pair.NonnullPair; import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; @@ -66,6 +70,7 @@ import com.google.common.base.Functions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.protobuf.ByteString; @@ -839,12 +844,28 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa : tableFunction.encapsulate(valueArgs); if (resultingValue instanceof StreamingValue) { final var tableFunctionExpression = new TableFunctionExpression(Assert.castUnchecked(resultingValue, StreamingValue.class)); - final var resultingQuantifier = Quantifier.forEach(Reference.initialOf(tableFunctionExpression)); + final var reference = Reference.initialOf(tableFunctionExpression); + long startTime = System.nanoTime(); + final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), + Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); + long endTime = System.nanoTime(); + long elapsedNanos = endTime - startTime; + double elapsedMillis = elapsedNanos / 1_000_000.0; + System.out.println("Translation plan took " + elapsedMillis); + final var resultingQuantifier = Quantifier.forEach(translatedReference); final var output = Expressions.of(LogicalOperator.convertToExpressions(resultingQuantifier)); return LogicalOperator.newNamedOperator(functionName, output, resultingQuantifier); } final var relationalExpression = Assert.castUnchecked(resultingValue, RelationalExpression.class); - final var topQun = Quantifier.forEach(Reference.initialOf(relationalExpression)); + final var reference = Reference.initialOf(relationalExpression); + long startTime = System.nanoTime(); + final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), + Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); + long endTime = System.nanoTime(); + long elapsedNanos = endTime - startTime; + double elapsedMillis = elapsedNanos / 1_000_000.0; + System.out.println("Translation plan took " + elapsedMillis); + final var topQun = Quantifier.forEach(translatedReference); return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java index e6397ecbd5..9e17ff50db 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/metadata/SchemaTemplateSerDeTests.java @@ -52,7 +52,6 @@ import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -61,6 +60,7 @@ import javax.annotation.Nonnull; import java.net.URI; +import java.sql.SQLException; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; @@ -362,11 +362,10 @@ public void findTableByNameWorksCorrectly() { Assertions.assertFalse(nonExisting.isPresent()); } - @Disabled @Test - public void sqlFunctionsAreLazilyParsed() throws RelationalException { + public void sqlFunctionsAreLazilyParsed() throws Exception { final var peekingDeserializer = recMetadataSampleWithFunctions( - "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE col1 < Q"); + "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE COL1 < Q"); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction1")); final var planGenerator = peekingDeserializer.getPlanGenerator(); @@ -378,12 +377,11 @@ public void sqlFunctionsAreLazilyParsed() throws RelationalException { Assertions.assertNotNull(plan); } - @Disabled @Test - public void nestedSqlFunctionsAreLazilyParsed() throws RelationalException { + public void nestedSqlFunctionsAreLazilyParsed() throws Exception { final var peekingDeserializer = recMetadataSampleWithFunctions( - "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE col1 < Q", - "CREATE FUNCTION SqlFunction2(IN Q BIGINT) AS SELECT * FROM SqlFunction1(100) WHERE col1 < Q"); + "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE COL1 < Q", + "CREATE FUNCTION SqlFunction2(IN Q BIGINT) AS SELECT * FROM SqlFunction1(100) WHERE COL1 < Q"); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction2")); @@ -396,17 +394,16 @@ public void nestedSqlFunctionsAreLazilyParsed() throws RelationalException { Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction2")); - Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction2(200) where col1 < 300")); + Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction2(200) where COL1 < 300")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction2")); } - @Disabled @Test - public void onlyQueriedSqlFunctionsAreCompiled() throws RelationalException { + public void onlyQueriedSqlFunctionsAreCompiled() throws Exception { final var peekingDeserializer = recMetadataSampleWithFunctions( - "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE col1 < Q", - "CREATE FUNCTION SqlFunction2(IN Q BIGINT) AS SELECT * FROM SqlFunction1(100) WHERE col1 < Q", + "CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE COL1 < Q", + "CREATE FUNCTION SqlFunction2(IN Q BIGINT) AS SELECT * FROM SqlFunction1(100) WHERE COL1 < Q", "CREATE FUNCTION SqlFunction3() AS SELECT * FROM T1"); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction2")); @@ -418,17 +415,19 @@ public void onlyQueriedSqlFunctionsAreCompiled() throws RelationalException { Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction2")); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction3")); + planGenerator.getPlan("select * from SqlFunction2(200)"); + Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction2(200)")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction2")); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction3")); - Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction2(200) where col1 < 300")); + Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction2(200) where COL1 < 300")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction2")); Assertions.assertTrue(peekingDeserializer.hasNoCompilationRequestsFor("SqlFunction4")); - Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction3() where col1 < 300")); + Assertions.assertDoesNotThrow(() -> planGenerator.getPlan("select * from SqlFunction3() where COL1 < 300")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction1")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction2")); Assertions.assertTrue(peekingDeserializer.hasOneCompilationRequestFor("SqlFunction3")); @@ -526,14 +525,16 @@ private static RecordMetadataDeserializerWithPeekingFunctionSupplier recMetadata // Verify that the provided functions match the ones we just deserialized Assertions.assertEquals(expectedFunctionMap, actualFunctionMap); - - Assertions.assertTrue(invokedRoutines.containsKey("SqlFunction1")); - final var function = invokedRoutines.get("SqlFunction1"); - Assertions.assertInstanceOf(RawSqlFunction.class, function); - final var rawSqlFunction = (RawSqlFunction)function; - Assertions.assertEquals("SqlFunction1", rawSqlFunction.getFunctionName()); - Assertions.assertEquals("CREATE FUNCTION SqlFunction1(IN Q BIGINT) AS SELECT * FROM T1 WHERE col1 < Q", - rawSqlFunction.getDefinition()); + for (final var entry : expectedFunctionMap.entrySet()) { + final var functionName = entry.getKey(); + final var functionDescription = entry.getValue(); + Assertions.assertTrue(invokedRoutines.containsKey(functionName)); + final var function = invokedRoutines.get(functionName); + Assertions.assertInstanceOf(RawSqlFunction.class, function); + final var rawSqlFunction = (RawSqlFunction)function; + Assertions.assertEquals(functionName, rawSqlFunction.getFunctionName()); + Assertions.assertEquals(functionDescription, rawSqlFunction.getDefinition()); + } // let's verify now that _no_ compilation is invoked when deserializing the record metadata. // for that, we use a deserializer with peeking supplier to the function compilation logic. @@ -586,8 +587,7 @@ boolean hasOneCompilationRequestFor(@Nonnull final String functionName) { } @Nonnull - public PlanGenerator getPlanGenerator() - throws RelationalException { + public PlanGenerator getPlanGenerator() throws RelationalException, SQLException { final var metricCollector = new MetricCollector() { @Override @@ -610,7 +610,8 @@ public T clock(@Nonnull RelationalMetric.RelationalEvent event, .withPlannerConfiguration(PlannerConfiguration.ofAllAvailableIndexes()) .withUserVersion(0) .build(); - return PlanGenerator.create(Optional.empty(), ctx, ctx.getMetaData(), new RecordStoreState(null, Map.of()), Options.NONE); + return PlanGenerator.create(Optional.empty(), ctx, ctx.getMetaData(), new RecordStoreState(null, Map.of()), + Options.builder().withOption(Options.Name.CASE_SENSITIVE_IDENTIFIERS, true).build()); } } } From 85755781396e55715953d7379e4f973affb3070b Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Mon, 15 Sep 2025 10:24:35 +0100 Subject: [PATCH 2/6] remove debugging code. --- .../relational/recordlayer/query/SemanticAnalyzer.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index 9c227bc1b3..8254997613 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -845,26 +845,16 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa if (resultingValue instanceof StreamingValue) { final var tableFunctionExpression = new TableFunctionExpression(Assert.castUnchecked(resultingValue, StreamingValue.class)); final var reference = Reference.initialOf(tableFunctionExpression); - long startTime = System.nanoTime(); final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); - long endTime = System.nanoTime(); - long elapsedNanos = endTime - startTime; - double elapsedMillis = elapsedNanos / 1_000_000.0; - System.out.println("Translation plan took " + elapsedMillis); final var resultingQuantifier = Quantifier.forEach(translatedReference); final var output = Expressions.of(LogicalOperator.convertToExpressions(resultingQuantifier)); return LogicalOperator.newNamedOperator(functionName, output, resultingQuantifier); } final var relationalExpression = Assert.castUnchecked(resultingValue, RelationalExpression.class); final var reference = Reference.initialOf(relationalExpression); - long startTime = System.nanoTime(); final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); - long endTime = System.nanoTime(); - long elapsedNanos = endTime - startTime; - double elapsedMillis = elapsedNanos / 1_000_000.0; - System.out.println("Translation plan took " + elapsedMillis); final var topQun = Quantifier.forEach(translatedReference); return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } From 2bdc94d674af64cddae76ece4c6e5ccd64ad63e0 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Tue, 28 Oct 2025 15:14:14 +0000 Subject: [PATCH 3/6] Avoid breaking correlations when rewriting the logical query graph. --- .../ToUniqueAliasesTranslationMap.java | 16 +++++++- .../query/plan/cascades/RuleTestHelper.java | 4 +- .../plan/cascades/TranslateGraphTest.java | 4 +- .../metadata/RecordLayerInvokedRoutine.java | 7 +--- .../recordlayer/query/SemanticAnalyzer.java | 5 ++- .../resources/sql-functions.metrics.binpb | 40 +++++++++---------- .../test/resources/sql-functions.metrics.yaml | 28 ++++++------- 7 files changed, 58 insertions(+), 46 deletions(-) diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java index 25de2a3e06..13d815c075 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java @@ -25,12 +25,14 @@ import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.values.LeafValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; +import com.google.common.base.Verify; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; +import java.util.Set; /** * Translation map that allows for rebasing of graphs in a way that the resulting rebased graph is only using unique @@ -43,8 +45,10 @@ public class ToUniqueAliasesTranslationMap implements TranslationMap { @Nonnull private final Map sourceToTargetMap; - public ToUniqueAliasesTranslationMap() { + private ToUniqueAliasesTranslationMap(@Nonnull final AliasMap identities) { + Verify.verify(identities.definesOnlyIdentities()); this.sourceToTargetMap = new LinkedHashMap<>(); + identities.forEachMapping(sourceToTargetMap::put); } @Nonnull @@ -87,4 +91,14 @@ private CorrelationIdentifier computeTargetIfAbsent(@Nonnull final CorrelationId return sourceToTargetMap.computeIfAbsent(sourceAlias, ignored0 -> Quantifier.uniqueId()); } + + @Nonnull + public static ToUniqueAliasesTranslationMap newInstance() { + return new ToUniqueAliasesTranslationMap(AliasMap.emptyMap()); + } + + @Nonnull + public static ToUniqueAliasesTranslationMap newInstance(@Nonnull final Set constantAliases) { + return new ToUniqueAliasesTranslationMap(AliasMap.identitiesFor(constantAliases)); + } } diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java index 77f7104e89..a1d1c52acc 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java @@ -149,7 +149,7 @@ private TestRuleExecution run(RelationalExpression original, EvaluationContext e // rewriting and planning final var copiedOriginal = Iterables.getOnlyElement(References.rebaseGraphs(ImmutableList.of(Reference.initialOf(original)), - Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)).get(); + Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(), false)).get(); ensureStage(PlannerStage.CANONICAL, copiedOriginal); if (rule instanceof ImplementationCascadesRule) { // @@ -245,7 +245,7 @@ public TestRuleExecution assertYields(RelationalExpression original, EvaluationC // final var copiedExpected = Iterables.getOnlyElement(References.rebaseGraphs(ImmutableList.of(Reference.initialOf(expression)), - Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)).get(); + Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(), false)).get(); ensureStage(PlannerStage.CANONICAL, copiedExpected); expectedListBuilder.add(copiedExpected); } diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java index 950e2be091..32c2fe569f 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java @@ -92,7 +92,7 @@ void rebaseGraphTest() { final var qun = Quantifier.forEach(Reference.initialOf(graphExpansionBuilder.build().buildSelect())); final var expression = LogicalSortExpression.unsorted(qun); final var reference = Reference.initialOf(expression); - final var translationMap = new ToUniqueAliasesTranslationMap(); + final var translationMap = ToUniqueAliasesTranslationMap.newInstance(); final var translatedReferences = References.rebaseGraphs(ImmutableList.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), @@ -159,7 +159,7 @@ void rebaseGraphTestWithDiamond() { final var qun = Quantifier.forEach(Reference.initialOf(graphExpansionBuilder.build().buildSelect())); final var expression = LogicalSortExpression.unsorted(qun); final var reference = Reference.initialOf(expression); - final var translationMap = new ToUniqueAliasesTranslationMap(); + final var translationMap = ToUniqueAliasesTranslationMap.newInstance(); final var translatedReferences = References.rebaseGraphs(ImmutableList.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index 337af64e53..1ab13e5200 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -23,8 +23,8 @@ import com.apple.foundationdb.record.query.plan.cascades.RawSqlFunction; import com.apple.foundationdb.relational.api.metadata.InvokedRoutine; import com.apple.foundationdb.relational.recordlayer.query.functions.CompiledSqlFunction; +import com.apple.foundationdb.relational.recordlayer.util.MemoizedFunction; import com.apple.foundationdb.relational.util.Assert; -import com.google.common.base.Suppliers; import javax.annotation.Nonnull; import java.util.Objects; @@ -55,10 +55,7 @@ public RecordLayerInvokedRoutine(@Nonnull final String description, this.normalizedDescription = normalizedDescription; this.name = name; this.isTemporary = isTemporary; - // TODO this used to be memoized - final var memoizedTrue = Suppliers.memoize(() -> compilableSqlFunctionSupplier.apply(true)); - final var memoizedFalse = Suppliers.memoize(() -> compilableSqlFunctionSupplier.apply(false)); - this.compilableSqlFunctionSupplier = param -> param ? memoizedTrue.get() : memoizedFalse.get(); + this.compilableSqlFunctionSupplier = MemoizedFunction.memoize(compilableSqlFunctionSupplier::apply); } @Nonnull diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index 8254997613..8ca02d91fb 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -842,11 +842,12 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa final var resultingValue = arguments.allNamedArguments() ? tableFunction.encapsulate(arguments.toNamedArgumentInvocation()) : tableFunction.encapsulate(valueArgs); + final var correlations = ((Correlated)Assert.castUnchecked(resultingValue, Correlated.class)).getCorrelatedTo(); if (resultingValue instanceof StreamingValue) { final var tableFunctionExpression = new TableFunctionExpression(Assert.castUnchecked(resultingValue, StreamingValue.class)); final var reference = Reference.initialOf(tableFunctionExpression); final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), - Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); + Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(correlations), false)); final var resultingQuantifier = Quantifier.forEach(translatedReference); final var output = Expressions.of(LogicalOperator.convertToExpressions(resultingQuantifier)); return LogicalOperator.newNamedOperator(functionName, output, resultingQuantifier); @@ -854,7 +855,7 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa final var relationalExpression = Assert.castUnchecked(resultingValue, RelationalExpression.class); final var reference = Reference.initialOf(relationalExpression); final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), - Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)); + Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(correlations), false)); final var topQun = Quantifier.forEach(translatedReference); return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } diff --git a/yaml-tests/src/test/resources/sql-functions.metrics.binpb b/yaml-tests/src/test/resources/sql-functions.metrics.binpb index 869ca09a29..39c986687b 100644 --- a/yaml-tests/src/test/resources/sql-functions.metrics.binpb +++ b/yaml-tests/src/test/resources/sql-functions.metrics.binpb @@ -98,51 +98,51 @@ h 3 [ label=<
Index
T1_IDX1
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 2 -> 1 [ label=< q208> label="q208" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; -} +}  -basic-sql-function-tests{EXPLAIN select A.col1 AS W, A.col2 AS X, B.col1 AS Y, B.col2 AS Z from f1(103, 'b') A, f1(103, 'b') B where A.col1 = B.col1 - F (08@ISCAN(T1_IDX1 <,>) | FLATMAP q0 -> { COVERING(T1_IDX1 [EQUALS promote(@c30 AS STRING), EQUALS q0.COL1] -> [COL1: KEY[1], COL2: KEY[0], COL3: KEY[2]]) | FILTER q0.COL1 LESS_THAN promote(@c28 AS LONG) AND q0.COL2 EQUALS promote(@c30 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }digraph G { +basic-sql-function-tests{EXPLAIN select A.col1 AS W, A.col2 AS X, B.col1 AS Y, B.col2 AS Z from f1(103, 'b') A, f1(103, 'b') B where A.col1 = B.col1 + Q Д!(0Ď8@ISCAN(T1_IDX1 <,>) | FLATMAP q0 -> { COVERING(T1_IDX1 [EQUALS promote(@c30 AS STRING), EQUALS q0.COL1] -> [COL1: KEY[1], COL2: KEY[0], COL3: KEY[2]]) | FILTER q0.COL1 LESS_THAN promote(@c28 AS LONG) AND q0.COL2 EQUALS promote(@c30 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }digraph G { fontname=courier; rankdir=BT; splines=polyline; - 1 [ label=<
Nested Loop Join
FLATMAP (q4.COL1 AS W, q4.COL2 AS X, q19.COL1 AS Y, q19.COL2 AS Z)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS W, STRING AS X, LONG AS Y, STRING AS Z)" ]; + 1 [ label=<
Nested Loop Join
FLATMAP (q15.COL1 AS W, q15.COL2 AS X, q32.COL1 AS Y, q32.COL2 AS Z)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS W, STRING AS X, LONG AS Y, STRING AS Z)" ]; 2 [ label=<
Index Scan
range: <-∞, ∞>
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 3 [ label=<
Index
T1_IDX1
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 4 [ label=<
Fetch Records
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="12" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; - 5 [ label=<
Predicate Filter
WHERE q19.COL1 LESS_THAN promote(@c28 AS LONG) AND q19.COL2 EQUALS promote(@c30 AS STRING)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; - 6 [ label=<
Covering Index Scan
comparisons: [EQUALS promote(@c30 AS STRING), EQUALS q19.COL1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; + 5 [ label=<
Predicate Filter
WHERE q32.COL1 LESS_THAN promote(@c28 AS LONG) AND q32.COL2 EQUALS promote(@c30 AS STRING)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; + 6 [ label=<
Covering Index Scan
comparisons: [EQUALS promote(@c30 AS STRING), EQUALS q32.COL1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 7 [ label=<
Index
T1_IDX1
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 2 -> 1 [ label=< q19> label="q19" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q258> label="q258" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 5 [ label=< q256> label="q256" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q32> label="q32" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q270> label="q270" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ label=< q268> label="q268" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 7 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 4 -> 1 [ label=< q4> label="q4" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q15> label="q15" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { rank=same; rankDir=LR; 2 -> 4 [ color="red" style="invis" ]; } -} +}  -basic-sql-function-testsEXPLAIN select A.col1 AS W, A.col2 AS X, B.col1 AS Y, B.col2 AS Z from f1(a => 103, b => 'b') A, f1(a => 103, b => 'b') B where A.col1 = B.col1 - A (08@ISCAN(T1_IDX1 <,>) | FLATMAP q0 -> { COVERING(T1_IDX1 [EQUALS promote(@c34 AS STRING), EQUALS q0.COL1] -> [COL1: KEY[1], COL2: KEY[0], COL3: KEY[2]]) | FILTER q0.COL1 LESS_THAN promote(@c30 AS LONG) AND q0.COL2 EQUALS promote(@c34 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }digraph G { +basic-sql-function-testsEXPLAIN select A.col1 AS W, A.col2 AS X, B.col1 AS Y, B.col2 AS Z from f1(a => 103, b => 'b') A, f1(a => 103, b => 'b') B where A.col1 = B.col1 + ] "(0ɛ8@ISCAN(T1_IDX1 <,>) | FLATMAP q0 -> { COVERING(T1_IDX1 [EQUALS promote(@c34 AS STRING), EQUALS q0.COL1] -> [COL1: KEY[1], COL2: KEY[0], COL3: KEY[2]]) | FILTER q0.COL1 LESS_THAN promote(@c30 AS LONG) AND q0.COL2 EQUALS promote(@c34 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }digraph G { fontname=courier; rankdir=BT; splines=polyline; - 1 [ label=<
Nested Loop Join
FLATMAP (q4.COL1 AS W, q4.COL2 AS X, q19.COL1 AS Y, q19.COL2 AS Z)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS W, STRING AS X, LONG AS Y, STRING AS Z)" ]; + 1 [ label=<
Nested Loop Join
FLATMAP (q15.COL1 AS W, q15.COL2 AS X, q32.COL1 AS Y, q32.COL2 AS Z)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS W, STRING AS X, LONG AS Y, STRING AS Z)" ]; 2 [ label=<
Index Scan
range: <-∞, ∞>
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 3 [ label=<
Index
T1_IDX1
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 4 [ label=<
Fetch Records
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="12" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; - 5 [ label=<
Predicate Filter
WHERE q19.COL1 LESS_THAN promote(@c30 AS LONG) AND q19.COL2 EQUALS promote(@c34 AS STRING)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; - 6 [ label=<
Covering Index Scan
comparisons: [EQUALS promote(@c34 AS STRING), EQUALS q19.COL1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; + 5 [ label=<
Predicate Filter
WHERE q32.COL1 LESS_THAN promote(@c30 AS LONG) AND q32.COL2 EQUALS promote(@c34 AS STRING)
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; + 6 [ label=<
Covering Index Scan
comparisons: [EQUALS promote(@c34 AS STRING), EQUALS q32.COL1]
> color="black" shape="plain" style="solid" fillcolor="black" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 7 [ label=<
Index
T1_IDX1
> color="black" shape="plain" style="filled" fillcolor="lightblue" fontname="courier" fontsize="8" tooltip="RELATION(LONG AS COL1, STRING AS COL2, INT AS COL3)" ]; 3 -> 2 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 2 -> 1 [ label=< q19> label="q19" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 5 -> 4 [ label=< q258> label="q258" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 6 -> 5 [ label=< q256> label="q256" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 2 -> 1 [ label=< q32> label="q32" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 5 -> 4 [ label=< q270> label="q270" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 6 -> 5 [ label=< q268> label="q268" color="gray20" style="bold" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; 7 -> 6 [ color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; - 4 -> 1 [ label=< q4> label="q4" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; + 4 -> 1 [ label=< q15> label="q15" color="gray20" style="solid" fontname="courier" fontsize="8" arrowhead="normal" arrowtail="none" dir="both" ]; { rank=same; rankDir=LR; diff --git a/yaml-tests/src/test/resources/sql-functions.metrics.yaml b/yaml-tests/src/test/resources/sql-functions.metrics.yaml index a493f61905..a93ed13c79 100644 --- a/yaml-tests/src/test/resources/sql-functions.metrics.yaml +++ b/yaml-tests/src/test/resources/sql-functions.metrics.yaml @@ -102,13 +102,13 @@ basic-sql-function-tests: | FILTER q0.COL1 LESS_THAN promote(@c28 AS LONG) AND q0.COL2 EQUALS promote(@c30 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }' - task_count: 1648 - task_total_time_ms: 148 - transform_count: 370 - transform_time_ms: 47 - transform_yield_count: 141 - insert_time_ms: 6 - insert_new_count: 252 + task_count: 1642 + task_total_time_ms: 171 + transform_count: 369 + transform_time_ms: 70 + transform_yield_count: 140 + insert_time_ms: 8 + insert_new_count: 251 insert_reused_count: 7 - query: EXPLAIN select A.col1 AS W, A.col2 AS X, B.col1 AS Y, B.col2 AS Z from f1(a => 103, b => 'b') A, f1(a => 103, b => 'b') B where A.col1 = B.col1 @@ -117,13 +117,13 @@ basic-sql-function-tests: | FILTER q0.COL1 LESS_THAN promote(@c30 AS LONG) AND q0.COL2 EQUALS promote(@c34 AS STRING) | FETCH AS q1 RETURN (q1.COL1 AS W, q1.COL2 AS X, q0.COL1 AS Y, q0.COL2 AS Z) }' - task_count: 1648 - task_total_time_ms: 138 - transform_count: 370 - transform_time_ms: 40 - transform_yield_count: 141 - insert_time_ms: 5 - insert_new_count: 252 + task_count: 1642 + task_total_time_ms: 195 + transform_count: 369 + transform_time_ms: 72 + transform_yield_count: 140 + insert_time_ms: 16 + insert_new_count: 251 insert_reused_count: 7 - query: EXPLAIN with x(y, z) as (select * from f1(b => 'b', a => 103)) select * from x From b6fde65588282ae1284f2091693dede3e9df8601 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Wed, 29 Oct 2025 11:08:59 +0000 Subject: [PATCH 4/6] Refactoring. --- .../ToUniqueAliasesTranslationMap.java | 16 +------ .../query/plan/cascades/RuleTestHelper.java | 4 +- .../plan/cascades/TranslateGraphTest.java | 4 +- .../recordlayer/query/SemanticAnalyzer.java | 16 +------ .../query/functions/CompiledSqlFunction.java | 48 ++++++++++++------- .../recordlayer/query/AstNormalizerTests.java | 6 +-- 6 files changed, 41 insertions(+), 53 deletions(-) diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java index 13d815c075..25de2a3e06 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/translation/ToUniqueAliasesTranslationMap.java @@ -25,14 +25,12 @@ import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.values.LeafValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; -import com.google.common.base.Verify; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; -import java.util.Set; /** * Translation map that allows for rebasing of graphs in a way that the resulting rebased graph is only using unique @@ -45,10 +43,8 @@ public class ToUniqueAliasesTranslationMap implements TranslationMap { @Nonnull private final Map sourceToTargetMap; - private ToUniqueAliasesTranslationMap(@Nonnull final AliasMap identities) { - Verify.verify(identities.definesOnlyIdentities()); + public ToUniqueAliasesTranslationMap() { this.sourceToTargetMap = new LinkedHashMap<>(); - identities.forEachMapping(sourceToTargetMap::put); } @Nonnull @@ -91,14 +87,4 @@ private CorrelationIdentifier computeTargetIfAbsent(@Nonnull final CorrelationId return sourceToTargetMap.computeIfAbsent(sourceAlias, ignored0 -> Quantifier.uniqueId()); } - - @Nonnull - public static ToUniqueAliasesTranslationMap newInstance() { - return new ToUniqueAliasesTranslationMap(AliasMap.emptyMap()); - } - - @Nonnull - public static ToUniqueAliasesTranslationMap newInstance(@Nonnull final Set constantAliases) { - return new ToUniqueAliasesTranslationMap(AliasMap.identitiesFor(constantAliases)); - } } diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java index a1d1c52acc..77f7104e89 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/RuleTestHelper.java @@ -149,7 +149,7 @@ private TestRuleExecution run(RelationalExpression original, EvaluationContext e // rewriting and planning final var copiedOriginal = Iterables.getOnlyElement(References.rebaseGraphs(ImmutableList.of(Reference.initialOf(original)), - Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(), false)).get(); + Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)).get(); ensureStage(PlannerStage.CANONICAL, copiedOriginal); if (rule instanceof ImplementationCascadesRule) { // @@ -245,7 +245,7 @@ public TestRuleExecution assertYields(RelationalExpression original, EvaluationC // final var copiedExpected = Iterables.getOnlyElement(References.rebaseGraphs(ImmutableList.of(Reference.initialOf(expression)), - Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(), false)).get(); + Memoizer.noMemoization(PlannerStage.INITIAL), new ToUniqueAliasesTranslationMap(), false)).get(); ensureStage(PlannerStage.CANONICAL, copiedExpected); expectedListBuilder.add(copiedExpected); } diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java index 32c2fe569f..950e2be091 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/TranslateGraphTest.java @@ -92,7 +92,7 @@ void rebaseGraphTest() { final var qun = Quantifier.forEach(Reference.initialOf(graphExpansionBuilder.build().buildSelect())); final var expression = LogicalSortExpression.unsorted(qun); final var reference = Reference.initialOf(expression); - final var translationMap = ToUniqueAliasesTranslationMap.newInstance(); + final var translationMap = new ToUniqueAliasesTranslationMap(); final var translatedReferences = References.rebaseGraphs(ImmutableList.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), @@ -159,7 +159,7 @@ void rebaseGraphTestWithDiamond() { final var qun = Quantifier.forEach(Reference.initialOf(graphExpansionBuilder.build().buildSelect())); final var expression = LogicalSortExpression.unsorted(qun); final var reference = Reference.initialOf(expression); - final var translationMap = ToUniqueAliasesTranslationMap.newInstance(); + final var translationMap = new ToUniqueAliasesTranslationMap(); final var translatedReferences = References.rebaseGraphs(ImmutableList.of(reference), Memoizer.noMemoization(PlannerStage.INITIAL), diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index f1ba069b94..1ce28a4b56 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -29,12 +29,8 @@ import com.apple.foundationdb.record.query.plan.cascades.Correlated; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; import com.apple.foundationdb.record.query.plan.cascades.IndexAccessHint; -import com.apple.foundationdb.record.query.plan.cascades.Memoizer; -import com.apple.foundationdb.record.query.plan.cascades.PlannerStage; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.Reference; -import com.apple.foundationdb.record.query.plan.cascades.References; -import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.expressions.TableFunctionExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; @@ -51,7 +47,6 @@ import com.apple.foundationdb.record.query.plan.cascades.values.StreamableAggregateValue; import com.apple.foundationdb.record.query.plan.cascades.values.StreamingValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; -import com.apple.foundationdb.record.query.plan.cascades.values.translation.ToUniqueAliasesTranslationMap; import com.apple.foundationdb.record.util.pair.NonnullPair; import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.api.exceptions.RelationalException; @@ -72,7 +67,6 @@ import com.google.common.base.Functions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.protobuf.ByteString; @@ -868,20 +862,14 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa final var resultingValue = arguments.allNamedArguments() ? tableFunction.encapsulate(arguments.toNamedArgumentInvocation()) : tableFunction.encapsulate(valueArgs); - final var correlations = ((Correlated)Assert.castUnchecked(resultingValue, Correlated.class)).getCorrelatedTo(); if (resultingValue instanceof StreamingValue) { final var tableFunctionExpression = new TableFunctionExpression(Assert.castUnchecked(resultingValue, StreamingValue.class)); final var reference = Reference.initialOf(tableFunctionExpression); - final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), - Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(correlations), false)); - final var resultingQuantifier = Quantifier.forEach(translatedReference); + final var resultingQuantifier = Quantifier.forEach(reference); final var output = Expressions.of(LogicalOperator.convertToExpressions(resultingQuantifier)); return LogicalOperator.newNamedOperator(functionName, output, resultingQuantifier); } - final var relationalExpression = Assert.castUnchecked(resultingValue, RelationalExpression.class); - final var reference = Reference.initialOf(relationalExpression); - final var translatedReference = Iterables.getOnlyElement(References.rebaseGraphs(List.of(reference), - Memoizer.noMemoization(PlannerStage.INITIAL), ToUniqueAliasesTranslationMap.newInstance(correlations), false)); + final var translatedReference = Assert.castUnchecked(resultingValue, Reference.class); final var topQun = Quantifier.forEach(translatedReference); return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java index 0ad456b23b..1d5796dc1b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java @@ -26,8 +26,11 @@ 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.GraphExpansion; +import com.apple.foundationdb.record.query.plan.cascades.Memoizer; +import com.apple.foundationdb.record.query.plan.cascades.PlannerStage; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.Reference; +import com.apple.foundationdb.record.query.plan.cascades.References; import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.expressions.TableFunctionExpression; @@ -39,12 +42,14 @@ import com.apple.foundationdb.record.query.plan.cascades.values.StreamingValue; import com.apple.foundationdb.record.query.plan.cascades.values.ThrowsValue; import com.apple.foundationdb.record.query.plan.cascades.values.Value; +import com.apple.foundationdb.record.query.plan.cascades.values.translation.ToUniqueAliasesTranslationMap; import com.apple.foundationdb.relational.api.exceptions.ErrorCode; import com.apple.foundationdb.relational.recordlayer.query.Expression; import com.apple.foundationdb.relational.recordlayer.query.Expressions; import com.apple.foundationdb.relational.recordlayer.query.Literals; import com.apple.foundationdb.relational.util.Assert; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import javax.annotation.Nonnull; @@ -92,12 +97,12 @@ public RecordMetaDataProto.PUserDefinedFunction toProto(@Nonnull final PlanSeria @Nonnull @Override - public RelationalExpression encapsulate(@Nonnull final List arguments) { + public Reference encapsulate(@Nonnull final List arguments) { if (parametersCorrelation.isEmpty()) { // this should never happen. Assert.thatUnchecked(arguments.isEmpty(), ErrorCode.INTERNAL_ERROR, "unexpected parameterless function invocation with non-zero arguments"); - return body; + return Reference.initialOf(body); } final var parametersCount = getParameterNames().size(); Assert.thatUnchecked(arguments.size() <= parametersCount, ErrorCode.UNDEFINED_FUNCTION, @@ -120,24 +125,18 @@ public RelationalExpression encapsulate(@Nonnull final List arg } resultBuilder.addResultColumn(Column.of(Optional.of(getParameterName(paramIdx)), argumentValue)); } - final var qun = Quantifier.forEach(Reference.initialOf(resultBuilder.addQuantifier(rangeOfOnePlan()).build().buildSelect()), - parametersCorrelation.get()); - final var bodyQun = Quantifier.forEach(Reference.initialOf(body)); - final var selectBuilder = GraphExpansion.builder() - .addQuantifier(bodyQun) - .addQuantifier(qun); - bodyQun.computeFlowedColumns().forEach(selectBuilder::addResultColumn); - return selectBuilder.build().buildSelect(); + final var argumentsExpression = resultBuilder.addQuantifier(rangeOfOnePlan()).build().buildSelect(); + return constructTableFunctionPlan(argumentsExpression); } @Nonnull @Override - public RelationalExpression encapsulate(@Nonnull final Map namedArguments) { + public Reference encapsulate(@Nonnull final Map namedArguments) { if (parametersCorrelation.isEmpty()) { // this should never happen. Assert.thatUnchecked(namedArguments.isEmpty(), ErrorCode.INTERNAL_ERROR, "unexpected parameterless function invocation with non-zero arguments"); - return body; + return Reference.initialOf(body); } Assert.thatUnchecked(hasNamedParameters(), ErrorCode.INTERNAL_ERROR, "unexpected invocation of function with named arguments"); @@ -156,14 +155,29 @@ public RelationalExpression encapsulate(@Nonnull final Map arguments) { + public Reference encapsulate(@Nonnull final List arguments) { throw new NotImplementedException("unexpected call"); } @Nonnull @Override - public RelationalExpression encapsulate(@Nonnull final Map namedArguments) { + public Reference encapsulate(@Nonnull final Map namedArguments) { throw new NotImplementedException("unexpected call"); } }) From 9af23cc6a13933d0064e32e221d418bd5a60fdc8 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Thu, 30 Oct 2025 10:43:13 +0000 Subject: [PATCH 5/6] Address comments. --- .../metadata/RecordLayerInvokedRoutine.java | 22 +++++++++---------- .../recordlayer/query/AstNormalizer.java | 2 +- .../recordlayer/query/SemanticAnalyzer.java | 5 +++-- .../query/functions/CompiledSqlFunction.java | 16 +++++++------- .../functions/SqlFunctionCatalogImpl.java | 2 +- .../recordlayer/query/AstNormalizerTests.java | 5 +++-- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index 1ab13e5200..2d174cb28e 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -44,18 +44,18 @@ public class RecordLayerInvokedRoutine implements InvokedRoutine { private final boolean isTemporary; @Nonnull - private final Function compilableSqlFunctionSupplier; + private final Function compilableSqlFunctionProvider; public RecordLayerInvokedRoutine(@Nonnull final String description, @Nonnull final String normalizedDescription, @Nonnull final String name, boolean isTemporary, - @Nonnull final Function compilableSqlFunctionSupplier) { + @Nonnull final Function compilableSqlFunctionProvider) { this.description = description; this.normalizedDescription = normalizedDescription; this.name = name; this.isTemporary = isTemporary; - this.compilableSqlFunctionSupplier = MemoizedFunction.memoize(compilableSqlFunctionSupplier::apply); + this.compilableSqlFunctionProvider = MemoizedFunction.memoize(compilableSqlFunctionProvider::apply); } @Nonnull @@ -71,8 +71,8 @@ public String getNormalizedDescription() { } @Nonnull - public Function getCompilableSqlFunctionSupplier() { - return compilableSqlFunctionSupplier; + public Function getCompilableSqlFunctionProvider() { + return compilableSqlFunctionProvider; } @Nonnull @@ -125,14 +125,14 @@ public Builder toBuilder() { .setDescription(getDescription()) .setNormalizedDescription(getNormalizedDescription()) .setTemporary(isTemporary()) - .withCompilableRoutine(getCompilableSqlFunctionSupplier()); + .withCompilableRoutine(getCompilableSqlFunctionProvider()); } public static final class Builder { private String description; private String normalizedDescription; private String name; - private Function compilableSqlFunctionSupplier; + private Function compilableSqlFunctionProvider; private boolean isTemporary; private Builder() { @@ -157,8 +157,8 @@ public Builder setName(@Nonnull final String name) { } @Nonnull - public Builder withCompilableRoutine(@Nonnull final Function compilableSqlFunctionSupplier) { - this.compilableSqlFunctionSupplier = compilableSqlFunctionSupplier; + public Builder withCompilableRoutine(@Nonnull final Function compilableSqlFunctionProvider) { + this.compilableSqlFunctionProvider = compilableSqlFunctionProvider; return this; } @@ -172,9 +172,9 @@ public Builder setTemporary(boolean isTemporary) { public RecordLayerInvokedRoutine build() { Assert.notNullUnchecked(name); Assert.notNullUnchecked(description); - Assert.notNullUnchecked(compilableSqlFunctionSupplier); + Assert.notNullUnchecked(compilableSqlFunctionProvider); return new RecordLayerInvokedRoutine(description, normalizedDescription, name, isTemporary, - compilableSqlFunctionSupplier); + compilableSqlFunctionProvider); } } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java index 35c18b6952..89482280d8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java @@ -628,7 +628,7 @@ public static NormalizationResult normalizeAst(@Nonnull final SchemaTemplate sch // immediate materialization of temporary function, this is required to collect any auxiliary literals discovered // during plan generation of the temporary function. The literals and combined with query literals and provided // for the execution of a (cached) physical plan. - final var compiledFunction = recordLayerRoutine.getCompilableSqlFunctionSupplier().apply(caseSensitive); + final var compiledFunction = recordLayerRoutine.getCompilableSqlFunctionProvider().apply(caseSensitive); astNormalizer.queryHasherContextBuilder.getLiteralsBuilder().importLiterals(compiledFunction.getAuxiliaryLiterals()); } return new NormalizationResult( diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java index 1ce28a4b56..756be5e753 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/SemanticAnalyzer.java @@ -31,6 +31,7 @@ import com.apple.foundationdb.record.query.plan.cascades.IndexAccessHint; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.Reference; +import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.expressions.TableFunctionExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; @@ -869,8 +870,8 @@ public LogicalOperator resolveTableFunction(@Nonnull final Identifier functionNa final var output = Expressions.of(LogicalOperator.convertToExpressions(resultingQuantifier)); return LogicalOperator.newNamedOperator(functionName, output, resultingQuantifier); } - final var translatedReference = Assert.castUnchecked(resultingValue, Reference.class); - final var topQun = Quantifier.forEach(translatedReference); + final var tableExpression = Assert.castUnchecked(resultingValue, RelationalExpression.class); + final var topQun = Quantifier.forEach(Reference.initialOf(tableExpression)); return LogicalOperator.newNamedOperator(functionName, Expressions.fromQuantifier(topQun), topQun); } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java index 1d5796dc1b..ccf2a2f7f8 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/CompiledSqlFunction.java @@ -97,12 +97,12 @@ public RecordMetaDataProto.PUserDefinedFunction toProto(@Nonnull final PlanSeria @Nonnull @Override - public Reference encapsulate(@Nonnull final List arguments) { + public RelationalExpression encapsulate(@Nonnull final List arguments) { if (parametersCorrelation.isEmpty()) { // this should never happen. Assert.thatUnchecked(arguments.isEmpty(), ErrorCode.INTERNAL_ERROR, "unexpected parameterless function invocation with non-zero arguments"); - return Reference.initialOf(body); + return body; } final var parametersCount = getParameterNames().size(); Assert.thatUnchecked(arguments.size() <= parametersCount, ErrorCode.UNDEFINED_FUNCTION, @@ -126,17 +126,17 @@ public Reference encapsulate(@Nonnull final List arguments) { resultBuilder.addResultColumn(Column.of(Optional.of(getParameterName(paramIdx)), argumentValue)); } final var argumentsExpression = resultBuilder.addQuantifier(rangeOfOnePlan()).build().buildSelect(); - return constructTableFunctionPlan(argumentsExpression); + return constructTableFunctionExpression(argumentsExpression); } @Nonnull @Override - public Reference encapsulate(@Nonnull final Map namedArguments) { + public RelationalExpression encapsulate(@Nonnull final Map namedArguments) { if (parametersCorrelation.isEmpty()) { // this should never happen. Assert.thatUnchecked(namedArguments.isEmpty(), ErrorCode.INTERNAL_ERROR, "unexpected parameterless function invocation with non-zero arguments"); - return Reference.initialOf(body); + return body; } Assert.thatUnchecked(hasNamedParameters(), ErrorCode.INTERNAL_ERROR, "unexpected invocation of function with named arguments"); @@ -156,11 +156,11 @@ public Reference encapsulate(@Nonnull final Map namedAr resultBuilder.addResultColumn(Column.of(Optional.of(name), maybePromotedArgument)); } final var argumentsExpression = resultBuilder.addQuantifier(rangeOfOnePlan()).build().buildSelect(); - return constructTableFunctionPlan(argumentsExpression); + return constructTableFunctionExpression(argumentsExpression); } @Nonnull - private Reference constructTableFunctionPlan(@Nonnull final RelationalExpression argumentsExpression) { + private RelationalExpression constructTableFunctionExpression(@Nonnull final RelationalExpression argumentsExpression) { final var aliasMap = new ToUniqueAliasesTranslationMap(); final var bodyRef = Reference.initialOf(body); @@ -177,7 +177,7 @@ private Reference constructTableFunctionPlan(@Nonnull final RelationalExpression .addQuantifier(bodyQun) .addQuantifier(parametersQun); bodyQun.computeFlowedColumns().forEach(selectBuilder::addResultColumn); - return Reference.initialOf(selectBuilder.build().buildSelect()); + return selectBuilder.build().buildSelect(); } @Nonnull diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java index 100d529827..81a28f021d 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java @@ -160,7 +160,7 @@ public static SqlFunctionCatalogImpl newInstance(@Nonnull final RecordLayerSchem metadata.getInvokedRoutines().forEach(func -> functionCatalog.registerUserDefinedFunction( Assert.notNullUnchecked(func.getName()), - func.getCompilableSqlFunctionSupplier())); + func.getCompilableSqlFunctionProvider())); return functionCatalog; } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java index a355fff5d0..b89c859db5 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java @@ -26,6 +26,7 @@ import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.Reference; +import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; import com.apple.foundationdb.relational.api.EmbeddedRelationalArray; import com.apple.foundationdb.relational.api.Options; @@ -417,13 +418,13 @@ public RecordMetaDataProto.PUserDefinedFunction toProto(@Nonnull final PlanSeria @Nonnull @Override - public Reference encapsulate(@Nonnull final List arguments) { + public RelationalExpression encapsulate(@Nonnull final List arguments) { throw new NotImplementedException("unexpected call"); } @Nonnull @Override - public Reference encapsulate(@Nonnull final Map namedArguments) { + public RelationalExpression encapsulate(@Nonnull final Map namedArguments) { throw new NotImplementedException("unexpected call"); } }) From 85ec6bd84c8afb9f8e93469c09481860c97bd600 Mon Sep 17 00:00:00 2001 From: Youssef Hatem Date: Thu, 30 Oct 2025 10:52:06 +0000 Subject: [PATCH 6/6] Post-merge adjustments. --- .../metadata/RecordLayerInvokedRoutine.java | 23 +++++++++---------- .../recordlayer/query/AstNormalizer.java | 2 +- .../functions/SqlFunctionCatalogImpl.java | 2 +- .../recordlayer/query/AstNormalizerTests.java | 1 - 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java index 3b92891ecd..c65eedb6a2 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerInvokedRoutine.java @@ -23,7 +23,6 @@ import com.apple.foundationdb.record.query.plan.cascades.RawSqlFunction; import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; import com.apple.foundationdb.relational.api.metadata.InvokedRoutine; -import com.apple.foundationdb.relational.recordlayer.query.functions.CompiledSqlFunction; import com.apple.foundationdb.relational.recordlayer.util.MemoizedFunction; import com.apple.foundationdb.relational.util.Assert; @@ -45,7 +44,7 @@ public class RecordLayerInvokedRoutine implements InvokedRoutine { private final boolean isTemporary; @Nonnull - private final Function userDefinedFunctionSupplier; + private final Function userDefinedFunctionProvider; @Nonnull private final UserDefinedFunction serializableFunction; @@ -54,14 +53,14 @@ public RecordLayerInvokedRoutine(@Nonnull final String description, @Nonnull final String normalizedDescription, @Nonnull final String name, boolean isTemporary, - @Nonnull final Function userDefinedFunctionSupplier, + @Nonnull final Function userDefinedFunctionProvider, @Nonnull final UserDefinedFunction serializableFunction) { this.description = description; this.normalizedDescription = normalizedDescription; this.name = name; this.isTemporary = isTemporary; // TODO this used to be memoized - this.userDefinedFunctionSupplier = MemoizedFunction.memoize(userDefinedFunctionSupplier::apply); + this.userDefinedFunctionProvider = MemoizedFunction.memoize(userDefinedFunctionProvider::apply); this.serializableFunction = serializableFunction; } @@ -78,8 +77,8 @@ public String getNormalizedDescription() { } @Nonnull - public Function getUserDefinedFunctionSupplier() { - return userDefinedFunctionSupplier; + public Function getUserDefinedFunctionProvider() { + return userDefinedFunctionProvider; } @Nonnull @@ -137,7 +136,7 @@ public Builder toBuilder() { .setDescription(getDescription()) .setNormalizedDescription(getNormalizedDescription()) .setTemporary(isTemporary()) - .withUserDefinedRoutine(getUserDefinedFunctionSupplier()) + .withUserDefinedRoutine(getUserDefinedFunctionProvider()) .withSerializableFunction(asSerializableFunction()); } @@ -145,7 +144,7 @@ public static final class Builder { private String description; private String normalizedDescription; private String name; - private Function userDefinedFunctionSupplier; + private Function userDefinedFunctionProvider; private UserDefinedFunction serializableFunction; private boolean isTemporary; @@ -171,8 +170,8 @@ public Builder setName(@Nonnull final String name) { } @Nonnull - public Builder withUserDefinedRoutine(@Nonnull final Function userDefinedFunctionSupplier) { - this.userDefinedFunctionSupplier = userDefinedFunctionSupplier; + public Builder withUserDefinedRoutine(@Nonnull final Function userDefinedFunctionProvider) { + this.userDefinedFunctionProvider = userDefinedFunctionProvider; return this; } @@ -192,10 +191,10 @@ public Builder setTemporary(boolean isTemporary) { public RecordLayerInvokedRoutine build() { Assert.notNullUnchecked(name); Assert.notNullUnchecked(description); - Assert.notNullUnchecked(userDefinedFunctionSupplier); + Assert.notNullUnchecked(userDefinedFunctionProvider); Assert.notNullUnchecked(serializableFunction); return new RecordLayerInvokedRoutine(description, normalizedDescription, name, isTemporary, - userDefinedFunctionSupplier, serializableFunction); + userDefinedFunctionProvider, serializableFunction); } } } diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java index 6e73e99136..57f7c67233 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizer.java @@ -629,7 +629,7 @@ public static NormalizationResult normalizeAst(@Nonnull final SchemaTemplate sch // immediate materialization of temporary function, this is required to collect any auxiliary literals discovered // during plan generation of the temporary function. The literals and combined with query literals and provided // for the execution of a (cached) physical plan. - final var compiledFunction = (CompiledSqlFunction)recordLayerRoutine.getUserDefinedFunctionSupplier().apply(caseSensitive); + final var compiledFunction = (CompiledSqlFunction)recordLayerRoutine.getUserDefinedFunctionProvider().apply(caseSensitive); astNormalizer.queryHasherContextBuilder.getLiteralsBuilder().importLiterals(compiledFunction.getAuxiliaryLiterals()); } return new NormalizationResult( diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java index acaa4584c5..405de7a682 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/functions/SqlFunctionCatalogImpl.java @@ -160,7 +160,7 @@ public static SqlFunctionCatalogImpl newInstance(@Nonnull final RecordLayerSchem metadata.getInvokedRoutines().forEach(func -> functionCatalog.registerUserDefinedFunction( Assert.notNullUnchecked(func.getName()), - func.getUserDefinedFunctionSupplier())); + func.getUserDefinedFunctionProvider())); return functionCatalog; } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java index de27d9b0d2..4680349d60 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/AstNormalizerTests.java @@ -25,7 +25,6 @@ import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.query.plan.cascades.Quantifier; import com.apple.foundationdb.record.query.plan.cascades.RawSqlFunction; -import com.apple.foundationdb.record.query.plan.cascades.Reference; import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; import com.apple.foundationdb.relational.api.EmbeddedRelationalArray;