diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Compiler.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Compiler.kt index 506b6a72aa..f2bdd3ff2c 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Compiler.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Compiler.kt @@ -45,6 +45,7 @@ import org.partiql.eval.internal.operator.rex.ExprStructField import org.partiql.eval.internal.operator.rex.ExprStructPermissive import org.partiql.eval.internal.operator.rex.ExprStructStrict import org.partiql.eval.internal.operator.rex.ExprSubquery +import org.partiql.eval.internal.operator.rex.ExprTable import org.partiql.eval.internal.operator.rex.ExprTupleUnion import org.partiql.eval.internal.operator.rex.ExprVarLocal import org.partiql.eval.internal.operator.rex.ExprVarOuter @@ -172,7 +173,10 @@ internal class Compiler( } } - override fun visitRexOpGlobal(node: Rex.Op.Global, ctx: PType?): Operator = symbols.getGlobal(node.ref) + override fun visitRexOpGlobal(node: Rex.Op.Global, ctx: PType?): Operator { + val table = symbols.getGlobal(node.ref) + return ExprTable(table) + } override fun visitRelOpAggregate(node: Rel.Op.Aggregate, ctx: PType?): Operator.Relation { val input = visitRel(node.input, ctx) diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Symbols.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Symbols.kt index 815ebedeec..daff32ae4e 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Symbols.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/Symbols.kt @@ -2,45 +2,48 @@ package org.partiql.eval.internal import org.partiql.eval.PartiQLEngine -import org.partiql.eval.internal.operator.rex.ExprVarGlobal import org.partiql.plan.Catalog import org.partiql.plan.PartiQLPlan import org.partiql.plan.Ref import org.partiql.planner.catalog.Name -import org.partiql.spi.connector.ConnectorBindings +import org.partiql.planner.catalog.Session +import org.partiql.planner.catalog.Table import org.partiql.spi.fn.Agg import org.partiql.spi.fn.Fn import org.partiql.spi.fn.SqlFnProvider +import org.partiql.planner.catalog.Catalog as Cat /** - * - * - * @property catalogs + * TODO Symbols will be removed in the V1 plan as it is no longer necessary. */ - internal class Symbols private constructor(private val catalogs: Array) { private class C( val name: String, - val bindings: ConnectorBindings, + val catalog: Cat, val items: Array, ) { + // TEMPORARY UNTIL ENGINE USES V1 PLANS + private val session: Session = Session.empty(catalog.getName()) + // TEMPORARY FOR DEPENDENCY REASONS + fun getTable(name: Name): Table? = catalog.getTable(session, name) fun getFn(name: Name, specific: String): Fn? = SqlFnProvider.getFn(specific) fun getAgg(name: Name, specific: String): Agg? = SqlFnProvider.getAgg(specific) override fun toString(): String = name } - fun getGlobal(ref: Ref): ExprVarGlobal { + fun getGlobal(ref: Ref): Table { val catalog = catalogs[ref.catalog] val item = catalog.items.getOrNull(ref.symbol) if (item == null || item !is Catalog.Item.Value) { error("Invalid reference $ref; missing value entry for catalog `$catalog`.") } val name = Name.of(item.path) - return ExprVarGlobal(name, catalog.bindings) + return catalog.getTable(name) + ?: error("Catalog `$catalog` has no entry for table $item") } fun getFn(ref: Ref): Fn { @@ -83,10 +86,11 @@ internal class Symbols private constructor(private val catalogs: Array) { ?: error("The plan contains a catalog `${it.name}`, but this was absent from the engine's session") C( name = it.name, - bindings = connector.getBindings(), - items = it.items.toTypedArray() + catalog = connector.getCatalog(), + items = it.items.toTypedArray(), ) }.toTypedArray() + return Symbols(catalogs) } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprTable.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprTable.kt new file mode 100644 index 0000000000..eab80a10f7 --- /dev/null +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprTable.kt @@ -0,0 +1,21 @@ +package org.partiql.eval.internal.operator.rex + +import org.partiql.eval.internal.Environment +import org.partiql.eval.internal.operator.Operator +import org.partiql.eval.value.Datum +import org.partiql.planner.catalog.Table + +/** + * Wrap a [Table] as an expression operator. + * + * @constructor + * + * @param table + */ +internal class ExprTable(table: Table) : Operator.Expr { + + // DO NOT USE FINAL + private var _table = table + + override fun eval(env: Environment): Datum = _table.getDatum() +} diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprVarGlobal.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprVarGlobal.kt deleted file mode 100644 index 4ab4a7bc4f..0000000000 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprVarGlobal.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.partiql.eval.internal.operator.rex - -import org.partiql.eval.internal.Environment -import org.partiql.eval.internal.operator.Operator -import org.partiql.eval.value.Datum -import org.partiql.planner.catalog.Name -import org.partiql.spi.connector.ConnectorBindings - -internal class ExprVarGlobal( - private val name: Name, - private val bindings: ConnectorBindings, -) : Operator.Expr { - - // TODO: Potentially make ConnectorBindings return PQLValue - override fun eval(env: Environment): Datum { - return bindings.getBinding(name)!!.getDatum() - } -} diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/TestCatalog.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/TestCatalog.kt index 61c180b1bd..980c961a65 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/TestCatalog.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/TestCatalog.kt @@ -115,7 +115,7 @@ public class TestCatalog private constructor( // upsert namespaces curr = curr.getOrPut(part) } - curr.table = Table.of(name.getName(), schema) + curr.table = Table.empty(name.getName(), schema) return this } diff --git a/partiql-spi/api/partiql-spi.api b/partiql-spi/api/partiql-spi.api index 5f4868d57f..a5f41e584a 100644 --- a/partiql-spi/api/partiql-spi.api +++ b/partiql-spi/api/partiql-spi.api @@ -588,25 +588,37 @@ public final class org/partiql/planner/catalog/Session$DefaultImpls { public abstract interface class org/partiql/planner/catalog/Table { public static final field Companion Lorg/partiql/planner/catalog/Table$Companion; public static fun builder ()Lorg/partiql/planner/catalog/Table$Builder; + public static fun empty (Ljava/lang/String;)Lorg/partiql/planner/catalog/Table; + public static fun empty (Ljava/lang/String;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; + public static fun empty (Lorg/partiql/planner/catalog/Name;)Lorg/partiql/planner/catalog/Table; + public static fun empty (Lorg/partiql/planner/catalog/Name;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; + public abstract fun getDatum ()Lorg/partiql/eval/value/Datum; public abstract fun getName ()Lorg/partiql/planner/catalog/Name; public abstract fun getSchema ()Lorg/partiql/types/PType; - public static fun of (Ljava/lang/String;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; + public static fun of (Lorg/partiql/planner/catalog/Name;Lorg/partiql/eval/value/Datum;)Lorg/partiql/planner/catalog/Table; + public static fun of (Lorg/partiql/planner/catalog/Name;Lorg/partiql/eval/value/Datum;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; } public final class org/partiql/planner/catalog/Table$Builder { public fun ()V public final fun build ()Lorg/partiql/planner/catalog/Table; + public final fun datum (Lorg/partiql/eval/value/Datum;)Lorg/partiql/planner/catalog/Table$Builder; public final fun name (Ljava/lang/String;)Lorg/partiql/planner/catalog/Table$Builder; public final fun schema (Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table$Builder; } public final class org/partiql/planner/catalog/Table$Companion { public final fun builder ()Lorg/partiql/planner/catalog/Table$Builder; - public final fun of (Ljava/lang/String;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; - public static synthetic fun of$default (Lorg/partiql/planner/catalog/Table$Companion;Ljava/lang/String;Lorg/partiql/types/PType;ILjava/lang/Object;)Lorg/partiql/planner/catalog/Table; + public final fun empty (Ljava/lang/String;)Lorg/partiql/planner/catalog/Table; + public final fun empty (Ljava/lang/String;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; + public final fun empty (Lorg/partiql/planner/catalog/Name;)Lorg/partiql/planner/catalog/Table; + public final fun empty (Lorg/partiql/planner/catalog/Name;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; + public final fun of (Lorg/partiql/planner/catalog/Name;Lorg/partiql/eval/value/Datum;)Lorg/partiql/planner/catalog/Table; + public final fun of (Lorg/partiql/planner/catalog/Name;Lorg/partiql/eval/value/Datum;Lorg/partiql/types/PType;)Lorg/partiql/planner/catalog/Table; } public final class org/partiql/planner/catalog/Table$DefaultImpls { + public static fun getDatum (Lorg/partiql/planner/catalog/Table;)Lorg/partiql/eval/value/Datum; public static fun getSchema (Lorg/partiql/planner/catalog/Table;)Lorg/partiql/types/PType; } @@ -621,7 +633,6 @@ public abstract interface class org/partiql/spi/Plugin { } public abstract interface class org/partiql/spi/connector/Connector { - public abstract fun getBindings ()Lorg/partiql/spi/connector/ConnectorBindings; public abstract fun getCatalog ()Lorg/partiql/planner/catalog/Catalog; } @@ -634,14 +645,6 @@ public final class org/partiql/spi/connector/Connector$Factory$DefaultImpls { public static synthetic fun create$default (Lorg/partiql/spi/connector/Connector$Factory;Lcom/amazon/ionelement/api/StructElement;ILjava/lang/Object;)Lorg/partiql/spi/connector/Connector; } -public abstract interface class org/partiql/spi/connector/ConnectorBinding { - public abstract fun getDatum ()Lorg/partiql/eval/value/Datum; -} - -public abstract interface class org/partiql/spi/connector/ConnectorBindings { - public abstract fun getBinding (Lorg/partiql/planner/catalog/Name;)Lorg/partiql/spi/connector/ConnectorBinding; -} - public abstract interface class org/partiql/spi/fn/Agg { public abstract fun accumulator ()Lorg/partiql/spi/fn/Agg$Accumulator; public abstract fun getSignature ()Lorg/partiql/spi/fn/AggSignature; diff --git a/partiql-spi/src/main/kotlin/org/partiql/planner/catalog/Table.kt b/partiql-spi/src/main/kotlin/org/partiql/planner/catalog/Table.kt index f8def32b7f..051b028ec3 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/planner/catalog/Table.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/planner/catalog/Table.kt @@ -1,15 +1,18 @@ package org.partiql.planner.catalog +import org.partiql.eval.value.Datum import org.partiql.types.PType /** - * In PartiQL, a [Table] can take on any type and is not necessarily rows+columns. + * In PartiQL, a [Table] can take on any type and is not necessarily a collection of rows. */ public interface Table { /** * Handle holds both a table and its resolved name within its respective catalog. * + * TODO DELETE ME AS A TABLE ALREADY CONTAINS ITS NAME. + * * Note: This replaces ConnectorObjectHandle from versions < 1.0 */ public class Handle( @@ -27,19 +30,69 @@ public interface Table { */ public fun getSchema(): PType = PType.dynamic() + /** + * The table's data. + */ + public fun getDatum(): Datum = Datum.nullValue() + /** * Factory methods and builder. */ public companion object { + @JvmStatic + public fun empty(name: String): Table = _Table( + name = Name.of(name), + schema = PType.dynamic(), + datum = Datum.nullValue(), + ) + /** - * Create a simple table with a name and schema. + * Create an empty table with dynamic schema. */ @JvmStatic - public fun of(name: String, schema: PType = PType.dynamic()): Table = object : Table { - override fun getName(): Name = Name.of(name) - override fun getSchema(): PType = schema - } + public fun empty(name: Name): Table = _Table( + name = name, + schema = PType.dynamic(), + datum = Datum.nullValue(), + ) + + @JvmStatic + public fun empty(name: String, schema: PType): Table = _Table( + name = Name.of(name), + schema = schema, + datum = Datum.nullValue(), + ) + + /** + * Create an empty table with known schema. + */ + @JvmStatic + public fun empty(name: Name, schema: PType): Table = _Table( + name = name, + schema = schema, + datum = Datum.nullValue(), + ) + + /** + * Create a table from a Datum with dynamic schema. + */ + @JvmStatic + public fun of(name: Name, datum: Datum): Table = _Table( + name = name, + schema = PType.dynamic(), + datum = datum, + ) + + /** + * Create a table from a Datum with known schema. + */ + @JvmStatic + public fun of(name: Name, datum: Datum, schema: PType): Table = _Table( + name = name, + schema = schema, + datum = datum, + ) /** * Returns the Java-style builder. @@ -55,6 +108,7 @@ public interface Table { private var name: String? = null private var schema: PType = PType.dynamic() + private var datum: Datum = Datum.nullValue() public fun name(name: String): Builder { this.name = name @@ -66,14 +120,38 @@ public interface Table { return this } + public fun datum(datum: Datum): Builder { + this.datum = datum + return this + } + public fun build(): Table { // Validate builder parameters val name = this.name ?: throw IllegalStateException("Table name cannot be null") - // Default implementation - return object : Table { - override fun getName(): Name = Name.of(name) - override fun getSchema(): PType = schema - } + return _Table(Name.of(name), schema, datum) } } + + /** + * An internal, standard table implementation backed by simple fields. + * + * @constructor + * All arguments default constructor. + * + * @param name + * @param schema + * @param datum + */ + @Suppress("ClassName") + private class _Table(name: Name, schema: PType, datum: Datum) : Table { + + // DO NOT USE FINAL + private var _name = name + private var _schema = schema + private var _datum = datum + + override fun getName(): Name = _name + override fun getSchema(): PType = _schema + override fun getDatum(): Datum = _datum + } } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/Connector.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/Connector.kt index 34bbd4ce57..7442ca7c76 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/Connector.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/Connector.kt @@ -9,11 +9,6 @@ import org.partiql.planner.catalog.Catalog */ public interface Connector { - /** - * Returns a [ConnectorBindings] which the engine uses to load values. - */ - public fun getBindings(): ConnectorBindings - /** * Returns a [Catalog] which the planner uses to load catalog metadata. */ diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBinding.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBinding.kt deleted file mode 100644 index 27eb168aba..0000000000 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBinding.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.partiql.spi.connector - -import org.partiql.eval.value.Datum - -/** - * TODO REMOVE ME IN FAVOR OF EXTENSIONS TO TABLE - */ -public interface ConnectorBinding { - - /** - * Return the datum for this binding. - */ - public fun getDatum(): Datum -} diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBindings.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBindings.kt deleted file mode 100644 index b03085327f..0000000000 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/connector/ConnectorBindings.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.partiql.spi.connector - -import org.partiql.planner.catalog.Name - -/** - * TODO REMOVE ME IN FAVOR OF SCANNING FROM A CATALOG IMPLEMENTATION - * - * Top-level interface for loading data into the engine. - */ -public interface ConnectorBindings { - - /** - * Get a binding for the given name (or null). - */ - public fun getBinding(name: Name): ConnectorBinding? -} diff --git a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalBindings.kt b/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalBindings.kt deleted file mode 100644 index 9a4efbad21..0000000000 --- a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalBindings.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.partiql.plugins.local - -import org.partiql.planner.catalog.Name -import org.partiql.spi.connector.ConnectorBinding -import org.partiql.spi.connector.ConnectorBindings - -internal object LocalBindings : ConnectorBindings { - - override fun getBinding(name: Name): ConnectorBinding? = null -} diff --git a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalConnector.kt b/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalConnector.kt index 17ee7c3292..8f7ff76199 100644 --- a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalConnector.kt +++ b/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalConnector.kt @@ -17,7 +17,6 @@ package org.partiql.plugins.local import com.amazon.ionelement.api.StructElement import org.partiql.planner.catalog.Catalog import org.partiql.spi.connector.Connector -import org.partiql.spi.connector.ConnectorBindings import java.nio.file.Path import java.nio.file.Paths import kotlin.io.path.isDirectory @@ -65,8 +64,6 @@ public class LocalConnector private constructor( } } - override fun getBindings(): ConnectorBindings = LocalBindings - override fun getCatalog(): Catalog = catalog internal class Factory : Connector.Factory { diff --git a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalTable.kt b/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalTable.kt index 70931c66dc..cdd1f07996 100644 --- a/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalTable.kt +++ b/plugins/partiql-local/src/main/kotlin/org/partiql/plugins/local/LocalTable.kt @@ -19,7 +19,6 @@ import com.amazon.ionelement.api.loadSingleElement import org.partiql.eval.value.Datum import org.partiql.planner.catalog.Name import org.partiql.planner.catalog.Table -import org.partiql.spi.connector.ConnectorBinding import org.partiql.types.PType import org.partiql.types.StaticType import java.nio.file.Path @@ -32,7 +31,7 @@ import kotlin.io.path.reader internal class LocalTable( private val name: Name, private val path: Path, -) : Table, ConnectorBinding { +) : Table { init { assert(!path.isDirectory()) { "LocalTable path must be a file." } diff --git a/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryConnector.kt b/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryConnector.kt index 735c5067f1..26f73ef7af 100644 --- a/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryConnector.kt +++ b/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryConnector.kt @@ -22,8 +22,6 @@ import org.partiql.planner.catalog.Name import org.partiql.planner.catalog.Session import org.partiql.planner.catalog.Table import org.partiql.spi.connector.Connector -import org.partiql.spi.connector.ConnectorBinding -import org.partiql.spi.connector.ConnectorBindings import org.partiql.types.PType import org.partiql.types.StaticType @@ -35,8 +33,6 @@ public class MemoryConnector private constructor( private val tables: Map, ) : Connector { - override fun getBindings(): ConnectorBindings = bindings - override fun getCatalog(): Catalog = catalog /** @@ -76,13 +72,6 @@ public class MemoryConnector private constructor( public fun build(): MemoryConnector = MemoryConnector(name!!, tables) } - /** - * Implement [ConnectorBindings] over the tables map. - */ - private val bindings = object : ConnectorBindings { - override fun getBinding(name: Name): ConnectorBinding? = tables[name] - } - /** * Implement [Catalog] over the tables map. */ diff --git a/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryTable.kt b/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryTable.kt index ea14d28833..9cbfa8bcce 100644 --- a/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryTable.kt +++ b/plugins/partiql-memory/src/main/kotlin/org/partiql/plugins/memory/MemoryTable.kt @@ -3,14 +3,13 @@ package org.partiql.plugins.memory import org.partiql.eval.value.Datum import org.partiql.planner.catalog.Name import org.partiql.planner.catalog.Table -import org.partiql.spi.connector.ConnectorBinding import org.partiql.types.PType public class MemoryTable private constructor( private val name: Name, private val schema: PType, private val datum: Datum, -) : Table, ConnectorBinding { +) : Table { override fun getName(): Name = name override fun getSchema(): PType = schema