From 85625e45d6aa4c5cf98c94d6414867b130a64db6 Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Wed, 20 Dec 2023 15:54:05 -0800 Subject: [PATCH 1/2] Moves ConnectorMetadata from Planner to Session --- .../src/main/kotlin/org/partiql/cli/Main.kt | 9 ++- .../org/partiql/planner/PartiQLPlanner.kt | 2 + .../partiql/planner/PartiQLPlannerBuilder.kt | 65 ++++--------------- .../partiql/planner/PartiQLPlannerDefault.kt | 6 +- .../org/partiql/planner/internal/Env.kt | 60 ++++++++++++----- .../partiql/planner/{ => internal}/Header.kt | 2 +- .../planner/{ => internal}/PartiQLHeader.kt | 2 +- .../planner/internal/typer/FnResolver.kt | 10 +-- .../kotlin/org/partiql/planner/HeaderTest.kt | 1 + .../org/partiql/planner/internal/EnvTest.kt | 8 +-- .../internal/typer/FunctionResolverTest.kt | 5 +- .../internal/typer/PartiQLTyperTestBase.kt | 17 +++-- .../planner/internal/typer/PlanTyperTest.kt | 8 +-- .../internal/typer/PlanTyperTestsPorted.kt | 11 ++-- .../spi/connector/ConnectorMetadata.kt | 19 ++++++ 15 files changed, 116 insertions(+), 109 deletions(-) rename partiql-planner/src/main/kotlin/org/partiql/planner/{ => internal}/Header.kt (98%) rename partiql-planner/src/main/kotlin/org/partiql/planner/{ => internal}/PartiQLHeader.kt (99%) diff --git a/partiql-cli/src/main/kotlin/org/partiql/cli/Main.kt b/partiql-cli/src/main/kotlin/org/partiql/cli/Main.kt index 6ff092079e..61267b6f66 100644 --- a/partiql-cli/src/main/kotlin/org/partiql/cli/Main.kt +++ b/partiql-cli/src/main/kotlin/org/partiql/cli/Main.kt @@ -52,12 +52,8 @@ object Debug { private val root = Paths.get(System.getProperty("user.home")).resolve(".partiql/local") - private val planner = PartiQLPlanner.builder() - .catalogs( - "local" to LocalConnector.Metadata(root) - ) - .build() private val parser = PartiQLParser.default() + private val planner = PartiQLPlanner.default() // !! // IMPLEMENT DEBUG BEHAVIOR HERE @@ -76,6 +72,9 @@ object Debug { val sess = PartiQLPlanner.Session( queryId = UUID.randomUUID().toString(), userId = "debug", + catalogs = mapOf( + "local" to LocalConnector.Metadata(root) + ) ) val result = planner.plan(statement, sess).plan out.info("-- Plan ----------") diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlanner.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlanner.kt index 8030703b34..7a0f09ec5a 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlanner.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlanner.kt @@ -4,6 +4,7 @@ import org.partiql.ast.Statement import org.partiql.errors.Problem import org.partiql.errors.ProblemCallback import org.partiql.plan.PartiQLPlan +import org.partiql.spi.connector.ConnectorMetadata import java.time.Instant /** @@ -45,6 +46,7 @@ public interface PartiQLPlanner { public val userId: String, public val currentCatalog: String? = null, public val currentDirectory: List = emptyList(), + public val catalogs: Map = emptyMap(), public val instant: Instant = Instant.now(), ) diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerBuilder.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerBuilder.kt index 275ff81dd9..0a3ba812df 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerBuilder.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerBuilder.kt @@ -1,82 +1,41 @@ package org.partiql.planner -import org.partiql.spi.connector.ConnectorMetadata -import org.partiql.types.function.FunctionSignature - /** * PartiQLPlannerBuilder is used to programmatically construct a [PartiQLPlanner] implementation. * * Usage: * PartiQLPlanner.builder() - * .addCatalog("foo", FooConnector()) - * .addCatalog("bar", BarConnector()) - * .builder() + * .addPass(myPass) + * .build() */ public class PartiQLPlannerBuilder { - private var fns: MutableList = mutableListOf() - private var catalogs: MutableMap = mutableMapOf() - private var passes: List = emptyList() + private val passes: MutableList = mutableListOf() /** * Build the builder, return an implementation of a [PartiQLPlanner]. * * @return */ - public fun build(): PartiQLPlanner { - val headers = mutableListOf
(PartiQLHeader) - if (fns.isNotEmpty()) { - val h = object : Header() { - override val namespace: String = "UDF" - override val functions = fns - } - headers.add(h) - } - return PartiQLPlannerDefault(headers, catalogs, passes) - } - - /** - * Java style method for assigning a Catalog name to [ConnectorMetadata]. - * - * @param catalog - * @param metadata - * @return - */ - public fun addCatalog(catalog: String, metadata: ConnectorMetadata): PartiQLPlannerBuilder = this.apply { - this.catalogs[catalog] = metadata - } - - /** - * Kotlin style method for assigning Catalog names to [ConnectorMetadata]. - * - * @param catalogs - * @return - */ - public fun catalogs(vararg catalogs: Pair): PartiQLPlannerBuilder = this.apply { - this.catalogs = mutableMapOf(*catalogs) - } + public fun build(): PartiQLPlanner = PartiQLPlannerDefault(passes) /** - * Java style method for adding a user-defined-function. + * Java style method for adding a planner pass to this planner builder. * - * @param function + * @param pass * @return */ - public fun addFunction(function: FunctionSignature.Scalar): PartiQLPlannerBuilder = this.apply { - this.fns.add(function) + public fun addPass(pass: PartiQLPlannerPass): PartiQLPlannerBuilder = this.apply { + this.passes.add(pass) } /** - * Kotlin style method for setting the user-defined functions. This replaces all existing user-defined functions previously passed to the builder. + * Kotlin style method for adding a list of planner passes to this planner builder. * - * @param function + * @param passes * @return */ - public fun functions(vararg functions: FunctionSignature.Scalar): PartiQLPlannerBuilder = this.apply { - this.fns = mutableListOf(*functions) - } - - public fun passes(passes: List): PartiQLPlannerBuilder = this.apply { - this.passes = passes + public fun addPasses(vararg passes: PartiQLPlannerPass): PartiQLPlannerBuilder = this.apply { + this.passes.addAll(passes) } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerDefault.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerDefault.kt index 9ba2281fed..19c728f06d 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerDefault.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerDefault.kt @@ -8,14 +8,11 @@ import org.partiql.planner.internal.ir.PartiQLVersion import org.partiql.planner.internal.transforms.AstToPlan import org.partiql.planner.internal.transforms.PlanTransform import org.partiql.planner.internal.typer.PlanTyper -import org.partiql.spi.connector.ConnectorMetadata /** * Default PartiQL logical query planner. */ internal class PartiQLPlannerDefault( - private val headers: List
, - private val catalogs: Map, private val passes: List, ) : PartiQLPlanner { @@ -24,8 +21,9 @@ internal class PartiQLPlannerDefault( session: PartiQLPlanner.Session, onProblem: ProblemCallback, ): PartiQLPlanner.Result { + // 0. Initialize the planning environment - val env = Env(headers, catalogs, session) + val env = Env(session) // 1. Normalize val ast = statement.normalize() diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Env.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Env.kt index 80a7eff38a..e2b0daec38 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Env.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Env.kt @@ -1,6 +1,5 @@ package org.partiql.planner.internal -import org.partiql.planner.Header import org.partiql.planner.PartiQLPlanner import org.partiql.planner.internal.ir.Agg import org.partiql.planner.internal.ir.Catalog @@ -20,6 +19,7 @@ import org.partiql.spi.connector.ConnectorSession import org.partiql.types.StaticType import org.partiql.types.StructType import org.partiql.types.TupleConstraint +import org.partiql.types.function.FunctionSignature /** * Handle for associating a catalog name with catalog related metadata objects. @@ -85,7 +85,7 @@ internal sealed interface ResolvedVar { override val ordinal: Int, val rootType: StaticType, val replacementSteps: List, - override val depth: Int + override val depth: Int, ) : ResolvedVar /** @@ -100,7 +100,7 @@ internal sealed interface ResolvedVar { override val type: StaticType, override val ordinal: Int, override val depth: Int, - val position: Int + val position: Int, ) : ResolvedVar } @@ -120,13 +120,9 @@ internal enum class ResolutionStrategy { /** * PartiQL Planner Global Environment of Catalogs backed by given plugins. * - * @property headers List of namespaced definitions - * @property catalogs List of plugins for global resolution * @property session Session details */ internal class Env( - private val headers: List
, - private val connectors: Map, private val session: PartiQLPlanner.Session, ) { @@ -135,10 +131,31 @@ internal class Env( */ public val catalogs = mutableListOf() + /** + * Catalog Metadata for this query session. + */ + private val connectors = session.catalogs + /** * Encapsulate all function resolving logic within [FnResolver]. + * + * TODO we should be using a search_path for resolving functions. This is not possible at the moment, so we flatten + * all builtin functions to live at the top-level. At the moment, we could technically use this to have + * single-level `catalog`.`function`() syntax but that is out-of-scope for this commit. */ - public val fnResolver = FnResolver(headers) + public val fnResolver = FnResolver(object : Header() { + + override val namespace: String = "builtins" + + override val functions: List = + PartiQLHeader.functions + connectors.values.flatMap { it.functions } + + override val operators: List = + PartiQLHeader.operators + connectors.values.flatMap { it.operators } + + override val aggregations: List = + PartiQLHeader.aggregations + connectors.values.flatMap { it.aggregations } + }) private val connectorSession = object : ConnectorSession { override fun getQueryId(): String = session.queryId @@ -146,13 +163,12 @@ internal class Env( } /** - - * Leverages a [FunctionResolver] to find a matching function defined in the [Header] scalar function catalog. + * Leverages a [FnResolver] to find a matching function defined in the [Header] scalar function catalog. */ internal fun resolveFn(fn: Fn.Unresolved, args: List) = fnResolver.resolveFn(fn, args) /** - * Leverages a [FunctionResolver] to find a matching function defined in the [Header] aggregation function catalog. + * Leverages a [FnResolver] to find a matching function defined in the [Header] aggregation function catalog. */ internal fun resolveAgg(agg: Agg.Unresolved, args: List) = fnResolver.resolveAgg(agg, args) @@ -211,7 +227,11 @@ internal class Env( getObjectHandle(cat, catalogPath)?.let { handle -> getObjectDescriptor(handle).let { type -> val depth = calculateMatched(originalPath, catalogPath, handle.second.absolutePath) - val (catalogIndex, valueIndex) = getOrAddCatalogValue(handle.first, handle.second.absolutePath.steps, type) + val (catalogIndex, valueIndex) = getOrAddCatalogValue( + handle.first, + handle.second.absolutePath.steps, + type + ) // Return resolution metadata ResolvedVar.Global(type, catalogIndex, depth, valueIndex) } @@ -222,7 +242,11 @@ internal class Env( /** * @return a [Pair] where [Pair.first] is the catalog index and [Pair.second] is the value index within that catalog */ - private fun getOrAddCatalogValue(catalogName: String, valuePath: List, valueType: StaticType): Pair { + private fun getOrAddCatalogValue( + catalogName: String, + valuePath: List, + valueType: StaticType, + ): Pair { val catalogIndex = getOrAddCatalog(catalogName) val symbols = catalogs[catalogIndex].symbols return symbols.indexOfFirst { value -> @@ -337,7 +361,13 @@ internal class Env( val varType = inferStructLookup(rootType, path) if (varType != null) { // we found this path within a struct! - val match = ResolvedVar.Local(varType.resolvedType, ordinal, rootType, varType.replacementPath.steps, varType.replacementPath.steps.size) + val match = ResolvedVar.Local( + varType.resolvedType, + ordinal, + rootType, + varType.replacementPath.steps, + varType.replacementPath.steps.size + ) matches.add(match) } } @@ -380,7 +410,7 @@ internal class Env( */ private class ResolvedPath( val replacementPath: BindingPath, - val resolvedType: StaticType + val resolvedType: StaticType, ) /** diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Header.kt similarity index 98% rename from partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt rename to partiql-planner/src/main/kotlin/org/partiql/planner/internal/Header.kt index 5c3a01b544..cfec05de70 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/Header.kt @@ -1,4 +1,4 @@ -package org.partiql.planner +package org.partiql.planner.internal import org.partiql.planner.internal.typer.TypeLattice import org.partiql.types.function.FunctionParameter diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/PartiQLHeader.kt similarity index 99% rename from partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt rename to partiql-planner/src/main/kotlin/org/partiql/planner/internal/PartiQLHeader.kt index 2bbae8b146..191e4f44e4 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/PartiQLHeader.kt @@ -1,4 +1,4 @@ -package org.partiql.planner +package org.partiql.planner.internal import org.partiql.ast.DatetimeField import org.partiql.types.function.FunctionParameter diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/FnResolver.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/FnResolver.kt index cb844089a4..ab5a88add8 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/FnResolver.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/FnResolver.kt @@ -1,6 +1,6 @@ package org.partiql.planner.internal.typer -import org.partiql.planner.Header +import org.partiql.planner.internal.Header import org.partiql.planner.internal.ir.Agg import org.partiql.planner.internal.ir.Fn import org.partiql.planner.internal.ir.Identifier @@ -109,7 +109,7 @@ internal sealed class FnMatch { * at the moment to keep that information (derived from the current TypeLattice) with the [FnResolver]. */ @OptIn(PartiQLValueExperimental::class) -internal class FnResolver(private val headers: List
) { +internal class FnResolver(private val header: Header) { /** * All headers use the same type lattice (we don't have a design for plugging type systems at the moment). @@ -140,10 +140,10 @@ internal class FnResolver(private val headers: List
) { val (casts, unsafeCasts) = casts() unsafeCastSet = unsafeCasts // combine all header definitions - val fns = headers.flatMap { it.functions } + val fns = header.functions functions = fns.toFnMap() - operators = (headers.flatMap { it.operators } + casts).toFnMap() - aggregations = headers.flatMap { it.aggregations }.toFnMap() + operators = (header.operators + casts).toFnMap() + aggregations = header.aggregations.toFnMap() } /** diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/HeaderTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/HeaderTest.kt index 3dad436cae..47b98ca0f3 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/HeaderTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/HeaderTest.kt @@ -2,6 +2,7 @@ package org.partiql.planner import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import org.partiql.planner.internal.PartiQLHeader class HeaderTest { diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/EnvTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/EnvTest.kt index d406eda7b7..cbdb3892e0 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/EnvTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/EnvTest.kt @@ -3,7 +3,6 @@ package org.partiql.planner.internal import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.partiql.planner.PartiQLHeader import org.partiql.planner.PartiQLPlanner import org.partiql.planner.internal.ir.Catalog import org.partiql.planner.internal.ir.Rex @@ -38,15 +37,14 @@ class EnvTest { @BeforeEach fun init() { env = Env( - listOf(PartiQLHeader), - mapOf( - "pql" to LocalConnector.Metadata(root) - ), PartiQLPlanner.Session( queryId = Random().nextInt().toString(), userId = "test-user", currentCatalog = "pql", currentDirectory = listOf("main"), + catalogs = mapOf( + "pql" to LocalConnector.Metadata(root) + ), ) ) } diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/FunctionResolverTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/FunctionResolverTest.kt index bc220377d0..feda1cb2aa 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/FunctionResolverTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/FunctionResolverTest.kt @@ -2,8 +2,7 @@ package org.partiql.planner.internal.typer import org.junit.jupiter.api.Test import org.junit.jupiter.api.fail -import org.partiql.planner.Header -import org.partiql.planner.PartiQLHeader +import org.partiql.planner.internal.Header import org.partiql.types.function.FunctionParameter import org.partiql.types.function.FunctionSignature import org.partiql.value.PartiQLValueExperimental @@ -67,7 +66,7 @@ class FunctionResolverTest { ) } - private val resolver = FnResolver(listOf(PartiQLHeader, myHeader)) + private val resolver = FnResolver(myHeader) } private sealed class Case { diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt index 897c8069d1..7ad14eb2e7 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt @@ -7,7 +7,6 @@ import org.partiql.parser.PartiQLParser import org.partiql.plan.Statement import org.partiql.plan.debug.PlanPrinter import org.partiql.planner.PartiQLPlanner -import org.partiql.planner.PartiQLPlannerBuilder import org.partiql.planner.test.PartiQLTest import org.partiql.planner.test.PartiQLTestProvider import org.partiql.planner.util.ProblemCollector @@ -29,11 +28,18 @@ abstract class PartiQLTyperTestBase { } companion object { - internal val session: ((String) -> PartiQLPlanner.Session) = { catalog -> + + public val parser = PartiQLParser.default() + public val planner = PartiQLPlanner.default() + + internal val session: ((String, ConnectorMetadata) -> PartiQLPlanner.Session) = { catalog, metadata -> PartiQLPlanner.Session( queryId = Random().nextInt().toString(), userId = "test-user", currentCatalog = catalog, + catalogs = mapOf( + catalog to metadata + ) ) } } @@ -41,11 +47,8 @@ abstract class PartiQLTyperTestBase { val inputs = PartiQLTestProvider().apply { load() } val testingPipeline: ((String, String, ConnectorMetadata, ProblemCallback) -> PartiQLPlanner.Result) = { query, catalog, metadata, collector -> - val ast = PartiQLParser.default().parse(query).root - val planner = PartiQLPlannerBuilder() - .addCatalog(catalog, metadata) - .build() - planner.plan(ast, session(catalog), collector) + val ast = parser.parse(query).root + planner.plan(ast, session(catalog, metadata), collector) } fun testGen( diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt index a2cc46dced..3645e13fa3 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt @@ -1,7 +1,6 @@ package org.partiql.planner.internal.typer import org.junit.jupiter.api.Test -import org.partiql.planner.PartiQLHeader import org.partiql.planner.PartiQLPlanner import org.partiql.planner.internal.Env import org.partiql.planner.internal.ir.Identifier @@ -174,15 +173,14 @@ class PlanTyperTest { private fun getTyper(): PlanTyperWrapper { val collector = ProblemCollector() val env = Env( - listOf(PartiQLHeader), - mapOf( - "pql" to LocalConnector.Metadata(root) - ), PartiQLPlanner.Session( queryId = Random().nextInt().toString(), userId = "test-user", currentCatalog = "pql", currentDirectory = listOf("main"), + catalogs = mapOf( + "pql" to LocalConnector.Metadata(root) + ), ) ) return PlanTyperWrapper(PlanTyper(env, collector), collector) diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt index b7601c561d..f88852c3c0 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt @@ -17,7 +17,6 @@ import org.partiql.plan.PartiQLPlan import org.partiql.plan.Statement import org.partiql.plan.debug.PlanPrinter import org.partiql.planner.PartiQLPlanner -import org.partiql.planner.PartiQLPlannerBuilder import org.partiql.planner.PlanningProblemDetails import org.partiql.planner.internal.typer.PlanTyperTestsPorted.TestCase.ErrorTestCase import org.partiql.planner.internal.typer.PlanTyperTestsPorted.TestCase.SuccessTestCase @@ -86,6 +85,9 @@ class PlanTyperTestsPorted { companion object { + private val parser = PartiQLParser.default() + private val planner = PartiQLPlanner.default() + private fun assertProblemExists(problem: () -> Problem) = ProblemHandler { problems, ignoreSourceLocation -> when (ignoreSourceLocation) { true -> assertTrue("Expected to find ${problem.invoke()} in $problems") { problems.any { it.details == problem.invoke().details } } @@ -2980,10 +2982,6 @@ class PlanTyperTestsPorted { session: PartiQLPlanner.Session, problemCollector: ProblemCollector ): PartiQLPlan { - val parser = PartiQLParser.default() - val planner = PartiQLPlannerBuilder() - .catalogs(*catalogs.toTypedArray()) - .build() val ast = parser.parse(query).root return planner.plan(ast, session, problemCollector).plan } @@ -3000,6 +2998,7 @@ class PlanTyperTestsPorted { USER_ID, tc.catalog, tc.catalogPath, + catalogs = mapOf(*catalogs.toTypedArray()) ) val hasQuery = tc.query != null @@ -3040,6 +3039,7 @@ class PlanTyperTestsPorted { USER_ID, tc.catalog, tc.catalogPath, + catalogs = mapOf(*catalogs.toTypedArray()) ) val collector = ProblemCollector() @@ -3085,6 +3085,7 @@ class PlanTyperTestsPorted { USER_ID, tc.catalog, tc.catalogPath, + catalogs = mapOf(*catalogs.toTypedArray()) ) val collector = ProblemCollector() val exception = assertThrows { diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorMetadata.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorMetadata.kt index 63bef3c8f7..8c29a4a5e8 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorMetadata.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorMetadata.kt @@ -16,12 +16,31 @@ package org.partiql.spi.connector import org.partiql.spi.BindingPath import org.partiql.types.StaticType +import org.partiql.types.function.FunctionSignature /** * Aids in retrieving relevant Catalog metadata for the purpose of planning and execution. */ public interface ConnectorMetadata { + /** + * Scalar function signatures available via call syntax. + */ + public val functions: List + get() = emptyList() + + /** + * Scalar function signatures available via operator or special form syntax. + */ + public val operators: List + get() = emptyList() + + /** + * Aggregation function signatures. + */ + public val aggregations: List + get() = emptyList() + /** * Returns the descriptor of an object. If the handle is unable to produce a [StaticType], implementers should * return null. From 031a5f910c2efab67e3a349004e50c8be32cc57f Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Wed, 20 Dec 2023 15:55:57 -0800 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dedc1c26c2..e24b83b33d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ Thank you to all who have contributed! ## [Unreleased] ### Added -- Adds the ability to pass a user-defined-function signature to the planner. +- Adds the ability to define a user-defined-function in ConnectorMetadata +- Move ConnectorMetadata map from PartiQLPlanner to PartiQLPlanner.Session for planner re-use. ### Changed @@ -42,7 +43,7 @@ Thank you to all who have contributed! ### Contributors Thank you to all who have contributed! -- @ +- @rchowell ## [0.14.0-alpha] - 2023-12-15