diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt index 1743bbde27..e1821d5617 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt @@ -302,7 +302,7 @@ internal class StandardCompiler(strategies: List) : PartiQLCompiler { val collations = rel.getCollations().map { val expr = compile(it.column, ctx) val desc = it.order.code() == Collation.Order.DESC - val last = it.order.code() == Collation.Nulls.LAST + val last = it.nulls.code() == Collation.Nulls.LAST RelOpSort.Collation(expr, desc, last) } return RelOpSort(input, collations) @@ -494,9 +494,9 @@ internal class StandardCompiler(strategies: List) : PartiQLCompiler { } override fun visitVar(rex: RexVar, ctx: Unit): ExprValue { - val depth = rex.getScope() + val scope = rex.scope val offset = rex.getOffset() - return ExprVar(depth, offset) + return ExprVar(scope, offset) } /** diff --git a/partiql-plan/api/partiql-plan.api b/partiql-plan/api/partiql-plan.api index 78d1206d0b..4b1e687f90 100644 --- a/partiql-plan/api/partiql-plan.api +++ b/partiql-plan/api/partiql-plan.api @@ -1,3 +1,10 @@ +public abstract interface class org/partiql/plan/Action { +} + +public abstract interface class org/partiql/plan/Action$Query : org/partiql/plan/Action { + public abstract fun getRex ()Lorg/partiql/plan/rex/Rex; +} + public abstract interface class org/partiql/plan/Collation { public abstract fun getColumn ()Lorg/partiql/plan/rex/Rex; public abstract fun getNulls ()Lorg/partiql/plan/Collation$Nulls; @@ -8,8 +15,8 @@ public final class org/partiql/plan/Collation$Nulls : org/partiql/spi/Enum { public static final field FIRST I public static final field LAST I public static final field UNKNOWN I - public static fun FIRST ()Lorg/partiql/plan/Collation$Order; - public static fun LAST ()Lorg/partiql/plan/Collation$Order; + public static fun FIRST ()Lorg/partiql/plan/Collation$Nulls; + public static fun LAST ()Lorg/partiql/plan/Collation$Nulls; public fun toString ()Ljava/lang/String; } @@ -117,13 +124,6 @@ public class org/partiql/plan/JoinType : org/partiql/spi/Enum { public static fun RIGHT ()Lorg/partiql/plan/JoinType; } -public abstract interface class org/partiql/plan/Operation { -} - -public abstract interface class org/partiql/plan/Operation$Query : org/partiql/plan/Operation { - public abstract fun getRex ()Lorg/partiql/plan/rex/Rex; -} - public abstract interface class org/partiql/plan/Operator { public abstract fun accept (Lorg/partiql/plan/OperatorVisitor;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getOperand (I)Lorg/partiql/plan/Operator; @@ -370,16 +370,19 @@ public final class org/partiql/plan/Operators$DefaultImpls { } public abstract interface class org/partiql/plan/Plan { - public abstract fun getOperations ()Ljava/util/List; - public abstract fun getVersion ()Lorg/partiql/plan/Version; + public abstract fun getActions ()Ljava/util/List; + public fun getVersion ()Lorg/partiql/plan/Version; } -public abstract interface class org/partiql/plan/Version { - public abstract fun toString ()Ljava/lang/String; +public class org/partiql/plan/Version : org/partiql/spi/Enum { + public static final field UNKNOWN I + public static fun UNKNOWN ()Lorg/partiql/plan/Version; + public fun toString ()Ljava/lang/String; } public abstract interface class org/partiql/plan/rel/Rel : org/partiql/plan/Operator { public abstract fun getType ()Lorg/partiql/plan/rel/RelType; + public abstract fun setType (Lorg/partiql/plan/rel/RelType;)V } public abstract class org/partiql/plan/rel/RelAggregate : org/partiql/plan/rel/RelBase { @@ -411,6 +414,7 @@ public abstract class org/partiql/plan/rel/RelBase : org/partiql/plan/rel/Rel { public final fun getType ()Lorg/partiql/plan/rel/RelType; protected abstract fun operands ()Ljava/util/List; public fun setTag (I)V + public fun setType (Lorg/partiql/plan/rel/RelType;)V protected abstract fun type ()Lorg/partiql/plan/rel/RelType; } @@ -569,11 +573,15 @@ public abstract class org/partiql/plan/rel/RelSort : org/partiql/plan/rel/RelBas protected final fun type ()Lorg/partiql/plan/rel/RelType; } -public abstract interface class org/partiql/plan/rel/RelType { - public abstract fun getField (Ljava/lang/String;)Lorg/partiql/types/Field; - public abstract fun getFieldSize ()I - public abstract fun getFields ()[Lorg/partiql/types/Field; - public abstract fun isOrdered ()Z +public class org/partiql/plan/rel/RelType { + public static final field ORDERED I + public fun getDegree ()I + public fun getField (I)Lorg/partiql/types/Field; + public fun getField (Ljava/lang/String;)Lorg/partiql/types/Field; + public fun getFields ()[Lorg/partiql/types/Field; + public fun isOrdered ()Z + public static fun of ([Lorg/partiql/types/Field;)Lorg/partiql/plan/rel/RelType; + public static fun of ([Lorg/partiql/types/Field;I)Lorg/partiql/plan/rel/RelType; } public abstract class org/partiql/plan/rel/RelUnion : org/partiql/plan/rel/RelBase { @@ -601,6 +609,7 @@ public abstract class org/partiql/plan/rel/RelUnpivot : org/partiql/plan/rel/Rel public abstract interface class org/partiql/plan/rex/Rex : org/partiql/plan/Operator { public abstract fun getType ()Lorg/partiql/plan/rex/RexType; + public abstract fun setType (Lorg/partiql/plan/rex/RexType;)V } public abstract class org/partiql/plan/rex/RexArray : org/partiql/plan/rex/RexBase { @@ -629,6 +638,7 @@ public abstract class org/partiql/plan/rex/RexBase : org/partiql/plan/rex/Rex { public final fun getType ()Lorg/partiql/plan/rex/RexType; protected abstract fun operands ()Ljava/util/List; public fun setTag (I)V + public final fun setType (Lorg/partiql/plan/rex/RexType;)V protected abstract fun type ()Lorg/partiql/plan/rex/RexType; } @@ -645,6 +655,7 @@ public abstract class org/partiql/plan/rex/RexCall : org/partiql/plan/rex/RexBas public abstract class org/partiql/plan/rex/RexCase : org/partiql/plan/rex/RexBase { public fun ()V public fun accept (Lorg/partiql/plan/OperatorVisitor;Ljava/lang/Object;)Ljava/lang/Object; + public static fun branch (Lorg/partiql/plan/rex/Rex;Lorg/partiql/plan/rex/Rex;)Lorg/partiql/plan/rex/RexCase$Branch; public static fun create (Lorg/partiql/plan/rex/Rex;Ljava/util/List;Lorg/partiql/plan/rex/Rex;)Lorg/partiql/plan/rex/RexCase; public abstract fun getBranches ()Ljava/util/List; public abstract fun getDefault ()Lorg/partiql/plan/rex/Rex; @@ -654,7 +665,6 @@ public abstract class org/partiql/plan/rex/RexCase : org/partiql/plan/rex/RexBas } public class org/partiql/plan/rex/RexCase$Branch { - public fun (Lorg/partiql/plan/rex/Rex;Lorg/partiql/plan/rex/Rex;)V public fun getCondition ()Lorg/partiql/plan/rex/Rex; public fun getResult ()Lorg/partiql/plan/rex/Rex; } @@ -878,11 +888,10 @@ public abstract class org/partiql/plan/rex/RexTable : org/partiql/plan/rex/RexBa } public class org/partiql/plan/rex/RexType { - public fun (Lorg/partiql/types/PType;)V - public static fun dynamic ()Lorg/partiql/plan/rex/RexType; public fun equals (Ljava/lang/Object;)Z public fun getPType ()Lorg/partiql/types/PType; public fun hashCode ()I + public static fun of (Lorg/partiql/types/PType;)Lorg/partiql/plan/rex/RexType; public fun toString ()Ljava/lang/String; } @@ -890,8 +899,8 @@ public abstract class org/partiql/plan/rex/RexVar : org/partiql/plan/rex/RexBase public fun ()V public fun accept (Lorg/partiql/plan/OperatorVisitor;Ljava/lang/Object;)Ljava/lang/Object; public static fun create (IILorg/partiql/types/PType;)Lorg/partiql/plan/rex/RexVar; - public abstract fun getDepth ()I public abstract fun getOffset ()I + public abstract fun getScope ()I protected final fun operands ()Ljava/util/List; } diff --git a/partiql-plan/src/main/java/org/partiql/plan/Exclusion.kt b/partiql-plan/src/main/java/org/partiql/plan/Exclusion.kt index b40d06af04..0b9b91bbb0 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/Exclusion.kt +++ b/partiql-plan/src/main/java/org/partiql/plan/Exclusion.kt @@ -34,17 +34,20 @@ public class Exclusion(variable: RexVar, items: List) { */ public fun getItems(): List = _items - // generated + /** + * UNSTABLE AND WILL BE DELETED (this only exists for unit tests) + */ override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Exclusion) return false if (_variable.scope != other._variable.scope || _variable.offset != other._variable.offset) return false if (_items != other._items) return false - return true } - // generated + /** + * UNSTABLE AND WILL BE DELETED (this only exists for unit tests) + */ override fun hashCode(): Int { var result = _variable.hashCode() result = 31 * result + _items.hashCode() diff --git a/partiql-plan/src/main/java/org/partiql/plan/rel/Rel.java b/partiql-plan/src/main/java/org/partiql/plan/rel/Rel.java index 2d7608b1fb..73727d2e67 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rel/Rel.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rel/Rel.java @@ -9,8 +9,13 @@ public interface Rel extends Operator { /** - * @return RelType. + * @return the type of the rows produced by this rel. */ @NotNull - RelType getType(); + public RelType getType(); + + /** + * @param type the new type of the rows produced by this Rex. + */ + public void setType(@NotNull RelType type); } diff --git a/partiql-plan/src/main/java/org/partiql/plan/rel/RelBase.java b/partiql-plan/src/main/java/org/partiql/plan/rel/RelBase.java index 85c592c9c3..8a046bce9d 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rel/RelBase.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rel/RelBase.java @@ -33,6 +33,11 @@ public final RelType getType() { return type; } + @Override + public void setType(@NotNull RelType type) { + this.type = type; + } + @NotNull @Override public final Operator getOperand(int index) { diff --git a/partiql-plan/src/main/java/org/partiql/plan/rel/RelType.java b/partiql-plan/src/main/java/org/partiql/plan/rel/RelType.java index 63dc672c6e..60bff0736a 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rel/RelType.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rel/RelType.java @@ -4,20 +4,62 @@ import org.partiql.types.Field; /** - * Analogous to a ROW type, consider rank/cardinality or other hint mechanisms. + * Analogous to a ROW type, consider cardinality estimates or other hint mechanisms. */ -public interface RelType { +public class RelType { - int getFieldSize(); + public static final int ORDERED = 0x01; + + private final Field[] fields; + private final boolean ordered; + + private RelType(Field[] fields, boolean ordered) { + this.fields = fields; + this.ordered = ordered; + } + + @NotNull + public static RelType of(Field... fields) { + return of(fields, 0); + } + + @NotNull + public static RelType of(Field[] fields, int properties) { + boolean ordered = (properties & ORDERED) != 0; + return new RelType(fields, ordered); + } + + public int getDegree() { + return fields.length; + } + + @NotNull + public Field[] getFields() { + return fields; + } @NotNull - Field[] getFields(); + public Field getField(int index) { + if (index < 0 || index >= fields.length) { + throw new IllegalArgumentException("field index out of bounds: " + index); + } + return fields[index]; // bounds check? + } @NotNull - Field getField(String name); + public Field getField(String name) { + for (Field field : fields) { + if (field.getName().equals(name)) { + return field; + } + } + throw new IllegalArgumentException("field name not found: " + name); + } /** * @return true if the rel produces an ordered stream of rows. */ - boolean isOrdered(); + public boolean isOrdered() { + return ordered; + } } diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/Rex.java b/partiql-plan/src/main/java/org/partiql/plan/rex/Rex.java index 8d5fa81710..8b8029bc8a 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/Rex.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/Rex.java @@ -9,13 +9,13 @@ public interface Rex extends Operator { /** - * @return the type of the value produced by this [Rex]. + * @return the type of the value produced by this rex. */ @NotNull public RexType getType(); /** - * @param type the new type of the value produced by this [Rex]. + * @param type the new type of the value produced by this rex. */ public void setType(RexType type); } diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexArray.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexArray.java index c785315354..955c2280f6 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexArray.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexArray.java @@ -29,7 +29,7 @@ public static RexArray create(@NotNull List values) { @NotNull @Override protected final RexType type() { - return new RexType(PType.array()); + return RexType.of(PType.array()); } @NotNull diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexBag.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexBag.java index a07fa26018..94c7b86040 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexBag.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexBag.java @@ -30,7 +30,7 @@ public static RexBag create(@NotNull Collection values) { @NotNull @Override protected final RexType type() { - return new RexType(PType.bag()); + return RexType.of(PType.bag()); } @NotNull diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexCall.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexCall.java index 1066620811..cee7621c80 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexCall.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexCall.java @@ -31,7 +31,7 @@ public static RexCall create(@NotNull Function.Instance function, @NotNull List< @Override protected RexType type() { - return new RexType(getFunction().returns); + return RexType.of(getFunction().returns); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexCast.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexCast.java index f146c09cdc..8da3edf2d5 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexCast.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexCast.java @@ -34,7 +34,7 @@ public static RexCast create(@NotNull Rex operand, @NotNull PType target) { @NotNull protected final RexType type() { - return new RexType(getTarget()); + return RexType.of(getTarget()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexDispatch.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexDispatch.java index b4e93b0e23..7191c9a3e4 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexDispatch.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexDispatch.java @@ -4,6 +4,7 @@ import org.partiql.plan.Operator; import org.partiql.plan.OperatorVisitor; import org.partiql.spi.function.Function; +import org.partiql.types.PType; import java.util.List; @@ -38,7 +39,7 @@ public static RexDispatch create(String name, List functions, List args) { @NotNull @Override protected final RexType type() { - return new RexType(PType.struct()); + return RexType.of(PType.struct()); } @NotNull diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexStruct.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexStruct.java index 0f8aeee574..db20868a5d 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexStruct.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexStruct.java @@ -37,7 +37,7 @@ public static Field field(Rex key, Rex value) { @NotNull @Override protected final RexType type() { - return new RexType(PType.struct()); + return RexType.of(PType.struct()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryComp.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryComp.java index 7586ea2f86..5e88bbd876 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryComp.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryComp.java @@ -56,7 +56,7 @@ public static RexSubqueryComp create( @NotNull @Override protected final RexType type() { - return new RexType(PType.bool()); + return RexType.of(PType.bool()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryIn.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryIn.java index c460b2524d..171c87e9dc 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryIn.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryIn.java @@ -35,7 +35,7 @@ public static RexSubqueryIn create(@NotNull Rel input, @NotNull List args) @Override protected final RexType type() { - return new RexType(PType.bool()); + return RexType.of(PType.bool()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryTest.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryTest.java index af734c3608..0d68fcc8b1 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryTest.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexSubqueryTest.java @@ -42,7 +42,7 @@ public static RexSubqueryTest create(@NotNull Rel input, @NotNull Test test) { @NotNull @Override protected final RexType type() { - return new RexType(PType.bool()); + return RexType.of(PType.bool()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexTable.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexTable.java index a6085c80c0..08d104a670 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexTable.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexTable.java @@ -28,7 +28,7 @@ public static RexTable create(@NotNull Table table) { @NotNull @Override protected final RexType type() { - return new RexType(getTable().getSchema()); + return RexType.of(getTable().getSchema()); } @Override diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexType.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexType.java index 9c651b34cd..5ca435186c 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexType.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexType.java @@ -1,5 +1,6 @@ package org.partiql.plan.rex; +import org.jetbrains.annotations.NotNull; import org.partiql.types.PType; /** @@ -12,10 +13,19 @@ public class RexType { private final PType type; - public RexType(PType type) { + private RexType(PType type) { this.type = type; } + /** + * @return a RexType from a PType. + */ + @NotNull + public static RexType of(@NotNull PType type) { + return new RexType(type); + } + + @NotNull public PType getPType() { return type; } @@ -43,11 +53,4 @@ public boolean equals(Object obj) { public String toString() { return type.toString(); } - - /** - * A [RexType] for an "untyped" logical plan node. - */ - public static RexType dynamic() { - return new RexType(PType.dynamic()); - } } diff --git a/partiql-plan/src/main/java/org/partiql/plan/rex/RexVar.java b/partiql-plan/src/main/java/org/partiql/plan/rex/RexVar.java index 0430fcd50c..f086ad4016 100644 --- a/partiql-plan/src/main/java/org/partiql/plan/rex/RexVar.java +++ b/partiql-plan/src/main/java/org/partiql/plan/rex/RexVar.java @@ -54,7 +54,7 @@ private Impl(int scope, int offset, PType type) { @Override protected RexType type() { - return new RexType(type); + return RexType.of(type); } @Override diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt index 802f1460c8..ebd30068dc 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt @@ -7,16 +7,19 @@ import org.partiql.plan.JoinType import org.partiql.plan.Operators import org.partiql.plan.Plan import org.partiql.plan.rel.RelAggregate +import org.partiql.plan.rel.RelType import org.partiql.plan.rex.Rex import org.partiql.plan.rex.RexCase import org.partiql.plan.rex.RexStruct import org.partiql.plan.rex.RexType import org.partiql.plan.rex.RexVar import org.partiql.planner.internal.PlannerFlag +import org.partiql.planner.internal.ir.Rel import org.partiql.planner.internal.ir.SetQuantifier import org.partiql.planner.internal.ir.visitor.PlanBaseVisitor import org.partiql.spi.errors.PErrorListener import org.partiql.spi.value.Datum +import org.partiql.types.Field import org.partiql.types.PType import org.partiql.value.DecimalValue import org.partiql.value.PartiQLValueExperimental @@ -87,30 +90,25 @@ internal class PlanTransform(private val flags: Set) { return operators.scan(operators.error(ctx)) } - /** - * Attach a PType to a rex. - */ - private fun typed(type: PType, f: () -> Rex): Rex { - val o = f() - o.type = RexType(type) - return o - } - // EXPRESSIONS - override fun visitRex(node: IRex, ctx: PType): Rex = super.visitRexOp(node.op, node.type) as Rex + override fun visitRex(node: IRex, ctx: PType): Rex { + val o = visitRexOp(node.op, node.type) + o.type = RexType.of(ctx) + return o + } override fun visitRexOp(node: IRex.Op, ctx: PType): Rex = super.visitRexOp(node, ctx) as Rex - override fun visitRexOpTupleUnion(node: IRex.Op.TupleUnion, ctx: PType) = typed(ctx) { + override fun visitRexOpTupleUnion(node: IRex.Op.TupleUnion, ctx: PType): Any { val args = node.args.map { visitRex(it, ctx) } - operators.spread(args) + return operators.spread(args) } - override fun visitRexOpSelect(node: IRex.Op.Select, ctx: PType) = typed(ctx) { + override fun visitRexOpSelect(node: IRex.Op.Select, ctx: PType): Any { val input = visitRel(node.rel, ctx) val constructor = visitRex(node.constructor, ctx) - operators.select(input, constructor) + return operators.select(input, constructor) } /** @@ -120,130 +118,134 @@ internal class PlanTransform(private val flags: Set) { * @param ctx * @return */ - override fun visitRexOpSubquery(node: IRex.Op.Subquery, ctx: PType) = typed(ctx) { + override fun visitRexOpSubquery(node: IRex.Op.Subquery, ctx: PType): Any { val input = visitRel(node.rel, ctx) val constructor = visitRex(node.constructor, ctx) val isScalar = node.coercion == IRex.Op.Subquery.Coercion.SCALAR - operators.subquery(input, constructor, isScalar) + return operators.subquery(input, constructor, isScalar) } - override fun visitRexOpPivot(node: IRex.Op.Pivot, ctx: PType) = typed(ctx) { + override fun visitRexOpPivot(node: IRex.Op.Pivot, ctx: PType): Any { val input = visitRel(node.rel, ctx) val key = visitRex(node.key, ctx) val value = visitRex(node.value, ctx) - operators.pivot(input, key, value) + return operators.pivot(input, key, value) } - override fun visitRexOpStruct(node: IRex.Op.Struct, ctx: PType) = typed(ctx) { + override fun visitRexOpStruct(node: IRex.Op.Struct, ctx: PType): Any { val fields = node.fields.map { field(it) } - operators.struct(fields) + return operators.struct(fields) } - override fun visitRexOpCollection(node: IRex.Op.Collection, ctx: PType) = typed(ctx) { + override fun visitRexOpCollection(node: IRex.Op.Collection, ctx: PType): Any { val values = node.values.map { visitRex(it, ctx) } - when (ctx.code()) { + return when (ctx.code()) { PType.ARRAY -> operators.array(values) PType.BAG -> operators.bag(values) else -> error("Expected bag or array, found ${ctx.name().lowercase()}") } } - override fun visitRexOpCoalesce(node: IRex.Op.Coalesce, ctx: PType) = typed(ctx) { + override fun visitRexOpCoalesce(node: IRex.Op.Coalesce, ctx: PType): Any { val args = node.args.map { visitRex(it, ctx) } - operators.coalesce(args) + return operators.coalesce(args) } - override fun visitRexOpNullif(node: IRex.Op.Nullif, ctx: PType) = typed(ctx) { + override fun visitRexOpNullif(node: IRex.Op.Nullif, ctx: PType): Any { val value = visitRex(node.value, ctx) val nullifier = visitRex(node.nullifier, ctx) - operators.nullIf(value, nullifier) + return operators.nullIf(value, nullifier) } - override fun visitRexOpCase(node: IRex.Op.Case, ctx: PType) = typed(ctx) { + override fun visitRexOpCase(node: IRex.Op.Case, ctx: PType): Any { val branches = node.branches.map { branch(it) } val default = visitRex(node.default, ctx) - operators.caseWhen(null, branches, default) + return operators.caseWhen(null, branches, default) } - override fun visitRexOpCallDynamic(node: IRex.Op.Call.Dynamic, ctx: PType) = typed(ctx) { + override fun visitRexOpCallDynamic(node: IRex.Op.Call.Dynamic, ctx: PType): Any { // TODO assert on function name in plan typer .. here is not the place. val args = node.args.map { visitRex(it, ctx) } val fns = node.candidates.map { it.fn.signature } val name = node.candidates.first().fn.name.getName() - operators.dispatch(name, fns, args) + return operators.dispatch(name, fns, args) } - override fun visitRexOpCallStatic(node: IRex.Op.Call.Static, ctx: PType) = typed(ctx) { + override fun visitRexOpCallStatic(node: IRex.Op.Call.Static, ctx: PType): Any { val fn = node.fn val args = node.args.map { visitRex(it, ctx) } - operators.call(fn, args) + return operators.call(fn, args) } - override fun visitRexOpCallUnresolved(node: IRex.Op.Call.Unresolved, ctx: PType) = typed(ctx) { + override fun visitRexOpCallUnresolved(node: IRex.Op.Call.Unresolved, ctx: PType): Any { error("The Internal Node Rex.Op.Call.Unresolved should be converted to an Err Node during type resolution if resolution failed") } - override fun visitRexOpCastUnresolved(node: IRex.Op.Cast.Unresolved, ctx: PType) = typed(ctx) { + override fun visitRexOpCastUnresolved(node: IRex.Op.Cast.Unresolved, ctx: PType): Any { error("This should have been converted to an error node.") } - override fun visitRexOpCastResolved(node: IRex.Op.Cast.Resolved, ctx: PType) = typed(ctx) { + override fun visitRexOpCastResolved(node: IRex.Op.Cast.Resolved, ctx: PType): Any { val operand = visitRex(node.arg, ctx) val target = node.cast.target - operators.cast(operand, target) + return operators.cast(operand, target) } - override fun visitRexOpPathSymbol(node: IRex.Op.Path.Symbol, ctx: PType) = typed(ctx) { + override fun visitRexOpPathSymbol(node: IRex.Op.Path.Symbol, ctx: PType): Any { val operand = visitRex(node.root, ctx) val symbol = node.key - operators.pathSymbol(operand, symbol) + return operators.pathSymbol(operand, symbol) } - override fun visitRexOpPathKey(node: IRex.Op.Path.Key, ctx: PType) = typed(ctx) { + override fun visitRexOpPathKey(node: IRex.Op.Path.Key, ctx: PType): Any { val operand = visitRex(node.root, ctx) val key = visitRex(node.key, ctx) - operators.pathKey(operand, key) + return operators.pathKey(operand, key) } - override fun visitRexOpPathIndex(node: IRex.Op.Path.Index, ctx: PType) = typed(ctx) { + override fun visitRexOpPathIndex(node: IRex.Op.Path.Index, ctx: PType): Any { val operand = visitRex(node.root, ctx) val index = visitRex(node.key, ctx) - operators.pathIndex(operand, index) + return operators.pathIndex(operand, index) } - override fun visitRexOpVarGlobal(node: IRex.Op.Var.Global, ctx: PType) = typed(ctx) { - operators.table(node.ref.table) + override fun visitRexOpVarGlobal(node: IRex.Op.Var.Global, ctx: PType): Any { + return operators.table(node.ref.table) } - override fun visitRexOpVarUnresolved(node: IRex.Op.Var.Unresolved, ctx: PType) = typed(ctx) { + override fun visitRexOpVarUnresolved(node: IRex.Op.Var.Unresolved, ctx: PType): Any { error("The Internal Plan Node Rex.Op.Var.Unresolved should be converted to an MISSING Node during type resolution if resolution failed") } - override fun visitRexOpVarLocal(node: IRex.Op.Var.Local, ctx: PType) = typed(ctx) { + override fun visitRexOpVarLocal(node: IRex.Op.Var.Local, ctx: PType): Any { val depth = node.depth val offset = node.ref - operators.variable(depth, offset, ctx) + return operators.variable(depth, offset, ctx) } @OptIn(PartiQLValueExperimental::class) - override fun visitRexOpLit(node: IRex.Op.Lit, ctx: PType) = typed(ctx) { + override fun visitRexOpLit(node: IRex.Op.Lit, ctx: PType): Any { val value = node.value // TODO: PartiQLValue doesn't have a finite decimal type, so we need to specially handle this until we remove // PartiQLValue. if (value is DecimalValue && ctx.code() == PType.DECIMAL) { - when (val dec = value.value) { + return when (val dec = value.value) { null -> operators.lit(Datum.nullValue(ctx)) else -> operators.lit(Datum.decimal(dec, ctx.precision, ctx.scale)) } - } else { - operators.lit(Datum.of(node.value)) } + return operators.lit(Datum.of(node.value)) } // RELATION OPERATORS - override fun visitRel(node: IRel, ctx: PType): org.partiql.plan.rel.Rel = - super.visitRelOp(node.op, ctx) as org.partiql.plan.rel.Rel + override fun visitRel(node: IRel, ctx: PType): org.partiql.plan.rel.Rel { + val o = visitRelOp(node.op, ctx) + val fields = node.type.schema.map { Field.of(it.name, it.type) }.toTypedArray() + val properties = if (node.type.props.contains(Rel.Prop.ORDERED)) RelType.ORDERED else 0 + o.type = RelType.of(fields, properties) + return o + } override fun visitRelOp(node: IRel.Op, ctx: PType): org.partiql.plan.rel.Rel = super.visitRelOp(node, ctx) as org.partiql.plan.rel.Rel diff --git a/test/partiql-tests-runner/src/test/kotlin/org/partiql/runner/executor/EvalExecutor.kt b/test/partiql-tests-runner/src/test/kotlin/org/partiql/runner/executor/EvalExecutor.kt index 942f35ad7e..a83e0ce6e5 100644 --- a/test/partiql-tests-runner/src/test/kotlin/org/partiql/runner/executor/EvalExecutor.kt +++ b/test/partiql-tests-runner/src/test/kotlin/org/partiql/runner/executor/EvalExecutor.kt @@ -193,7 +193,7 @@ class EvalExecutor( assertEquals(1, parseResult.statements.size) val stmt = parseResult.statements[0] val plan = planner.plan(stmt, session).plan - return (plan.getOperation() as Query).getRex().getType().getPType() + return (plan.actions[0] as Query).getRex().getType().getPType() } /**