From a504e2c0b3286465cad3914c34ff0e241b695d60 Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Fri, 20 Sep 2024 10:50:43 -0700 Subject: [PATCH 1/2] Adds UDT to PType --- partiql-types/README.adoc | 317 ------------------ partiql-types/api/partiql-types.api | 1 + .../main/java/org/partiql/types/PType.java | 10 + 3 files changed, 11 insertions(+), 317 deletions(-) delete mode 100644 partiql-types/README.adoc diff --git a/partiql-types/README.adoc b/partiql-types/README.adoc deleted file mode 100644 index 3f27adbb33..0000000000 --- a/partiql-types/README.adoc +++ /dev/null @@ -1,317 +0,0 @@ -= PartiQL Types & Values -:toc: -:sectlinks: - -This package contains classes for manipulating both PartiQL types and values. APIs for `org.partiql.types.StaticType` -are stable, but the value representation classes (PartiQLValue) are early in their lifecycle and are subject to change. -These particular classes have been marked with xref:https://kotlinlang.org/docs/opt-in-requirements.html[@RequiresOptIn]. - -[#types] -== Types - -PartiQL's data model extends SQL to Ion's type system to cover schema-less and nested data. This section should be -considered a draft, but the _StaticType_ class within `org.partiql.types` is stable. - -.Boolean Type -[cols="1m,3,>2",grid=rows,frame=all] -|=== -| Type | Description | Values - -| bool -| Boolean value -| `TRUE` or `FALSE` - -|=== - -.Numeric Types -[cols="1m,3,>2a",grid=rows,frame=all] -|=== -| Type | Description | Range - -| int8 -| Signed integer that can be stored in one byte -| -128 to +127 - -| int16 -| Signed integer that can be stored in two bytes -| -32768 to +32767 - -| int32 -| Signed integer that can be stored in four bytes -| -2147483648 to +2147483647 - -| int64 -| Signed integer that can be stored in eight bytes -| -9223372036854775808 to +9223372036854775807 - -| int -| Signed integer of arbitrary size -| ... - -| decimal -| Exact numeric type with arbitrary precision -| ... - -| decimal(p,s) -| Exact numeric with fixed precision and scale -| ... - -| float32 -| Single-precision, binary floating point (IEEE 754 32-bit) -| ... - -| float64 -| Double-precision, binary floating point (IEEE 754 64-bit) -| ... - -|=== - -.Character String Types -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| char(n) -| Unicode codepoint sequence of fixed length _n_ - -| string -| Unicode codepoint sequence of arbitrary length - -| string(n) -| Unicode codepoint sequence of variable length up to _n_. This is equivalent to the SQL type `CHARACTER VARYING(n)`, `VARCHAR(n)`. - -| symbol -| Unicode codepoint sequences of arbitrary length. The primary difference is the intended semantics: symbols represent case-sensitive identifiers as opposed to textual literal values. - -|=== - -.Bit String Types -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| bit(n) -| Bit string of fixed length _n_ - -| binary -| Bit string of arbitrary length - -| binary(n) -| Bit string of variable length up to _n_ - -|=== - -.Byte String Types -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| byte(n) -| Octet string of fixed length _n_ - -| blob -| Octet string of arbitrary length - -| blob(n) -| Octet string of variable length up to _n_ - -| clob -| Unicode codepoint sequence of arbitrary length - -| clob(n) -| Unicode codepoint sequence of variable length up to _n_ - -|=== - -.Date/Time Types -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| date -| A date with no _time_ - -| time -| A _date_-less time with arbitrary precision and no time zone offset - -| time(p) -| A _date_-less time with seconds precision _p_ and no time zone offset - -| time(p,z) -| A _date_-less time with seconds precision _p_ and time zone offset _z_ - -| timestamp -| A _date_ and _time_ with arbitrary precision - -| timestamp(p) -| A _date_ and _time_ with seconds precision _p_ and no time zone offset - -| timestamp(p,z) -| A _date_ and _time_ with seconds precision _p_ and time zone offset _z_ - -// Open Question: Should we model timestamp that only has UTF offsets which are a strict subset of timezones. - -// SQL-99 4.7.2 -| interval(p) -| A time interval with seconds precision _p_ - -2+a| NOTE: A time zone offset _z_ is an hour/minute pair of integers - -|=== - -.Collection Types -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| bag -| Unordered collection of values - -| list -| Ordered collection of values - -| sexp -| Ordered collections of values with application-defined semantics - -|=== - -.Struct Type -[cols="1m,5",grid=rows,frame=all] -|=== -| Type | Description - -| struct -| Unordered collection of unconstrained fields - -2+a| NOTE: Fields are name-value pairs where names are strings - -|=== - -.Absent Types -[cols="1m,3,>2m",grid=rows,frame=all] -|=== -| Type | Description | Value - -| null -| The null value -| NULL - -| missing -| The missing value -| MISSING - -|=== - -.Union Types -[cols="1m,5",grid=rows,frame=all] -|=== - -s| Type s| Description - -| any -| The union of all types - -| absent -| `missing\|null` - -| number -| `int8\|int16\|int32\|int64\|decimal\|float32\|float64` - -| exact_numeric -| `int8\|int16\|int32\|int64\|decimal` - -| collection -| `bag\|list\|sexp` - -|=== - -== Values - -PartiQL's value classes are based upon xref:https://github.com/amazon-ion/ion-element-kotlin[IonElement]. - -IMPORTANT: Like SQL, all values are nullable. - -=== Examples - -[source,kotlin] ----- -// simple value -intValue(1) // 1 - -// complex values -structValue(sequenceOf( - "a" to intValue(1, listOf("hello")), // second parameter is a list of annotations - "b" to sexpValue(sequenceOf( - symbolValue("x"), - stringValue("y"), - boolValue(null), - )), - "c" to bagValue(sequenceOf( - intValue(1), - intValue(2), - intValue(3), - )) -)) - -// PartiQL Text -// { -// 'a': hello::1, -// 'b': (x 'y' null), -// 'c': << 1, 2, 3 >>, -// } ----- - -=== Ion Usage - -PartiQL Value classes can be serialized and deserialized from both Ion text and binary Ion via the standard IonReader. -You can write PartiQL Values as plain Ion, or PartiQL values encoded as Ion (as some types in PartiQL to not exist in Ion). - -IMPORTANT: The encoding of PartiQL data as Ion has not been standardized. - -.Ion Encoding Type -[source,kotlin] ----- -/** - * The ion value annotations are always treated as annotations on PartiQL value. - * For example, $missing::null will be treated as nullValue(annotations = ["missing"]) - */ -IonGeneric - -/** - * We examine the **last** annotation before convert to PartiQL Value. - * If the annotation is PartiQL reserved, we validate Semantics and the constructed PartiQL value may be different. - * For example: - * - $missing::null will be treated as missingValue(annotations = []) - * - a::b::$missing:null will be treated as missingValue(annotations = ["a", "b"]) - * - a::$missing::b::null will be treated as nullValue(annotation = ["a", "$missing", "b"] - * - $missing::1 will cause an exception. - */ -IonForPartiQL ----- - -These APIs mirror IonJava, but we are working on the appropriate APIs for easier reading and writing. In the future, -we would like entry points such as `myValue.encode(PartiQLValueEncoding.ION)` and `decode(input, PartiQLValueEncoding.ION)`. -For DOM to DOM, we may have `myValue.toIon()`. - -[source,kotlin] ----- -val bag = bagValue(sequenceOf( - intValue(1), - intValue(2), - intValue(3), -)) - -// PartiQL Text writer -val pBuffer = ByteArrayOutputStream() -val pWriter = PartiQLValueWriterBuilder.standard().build(pBuffer) - -pWriter.append(bag) -println(pBuffer.toString()) // > <<1,2,3>> - -// PartiQL to Ion writer -val iBuffer = ByteArrayOutputStream() -val iWriter = PartiQLValueIonWriterBuilder.standardIonTextBuilder().build(iBuffer) - -iWriter.append(bag) -println(iBuffer.toString()) // > $bag::[1,2,3] ----- diff --git a/partiql-types/api/partiql-types.api b/partiql-types/api/partiql-types.api index fd6340a1ac..5a444a2898 100644 --- a/partiql-types/api/partiql-types.api +++ b/partiql-types/api/partiql-types.api @@ -375,6 +375,7 @@ public final class org/partiql/types/PType$Kind : java/lang/Enum { public static final field TIMESTAMPZ Lorg/partiql/types/PType$Kind; public static final field TIMEZ Lorg/partiql/types/PType$Kind; public static final field TINYINT Lorg/partiql/types/PType$Kind; + public static final field UDT Lorg/partiql/types/PType$Kind; public static final field UNKNOWN Lorg/partiql/types/PType$Kind; public static final field VARCHAR Lorg/partiql/types/PType$Kind; public static fun valueOf (Ljava/lang/String;)Lorg/partiql/types/PType$Kind; diff --git a/partiql-types/src/main/java/org/partiql/types/PType.java b/partiql-types/src/main/java/org/partiql/types/PType.java index 600e89f561..77ea865aba 100644 --- a/partiql-types/src/main/java/org/partiql/types/PType.java +++ b/partiql-types/src/main/java/org/partiql/types/PType.java @@ -431,6 +431,16 @@ enum Kind { */ STRUCT, + /** + * UDT represents a user-defined type. + *
+ *
+ * Type Syntax: CURRENTLY NOT APPLICABLE + *
+ * Applicable methods: Implementation defined. + */ + UDT, + /** * PartiQL's unknown type. This temporarily represents literal null and missing values. *
From 832c2ec501be1ac0bfeba37330b2ff105cb30cfb Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Fri, 20 Sep 2024 14:34:56 -0700 Subject: [PATCH 2/2] Begins removing PartiQLValue from planner --- partiql-ast/api/partiql-ast.api | 81 ++++++++++--------- .../org/partiql/ast/helpers/ToLegacyAst.kt | 14 +++- .../kotlin/org/partiql/ast/sql/SqlDialect.kt | 8 +- .../ast/sql/internal/InternalSqlDialect.kt | 8 +- .../src/main/resources/partiql_ast.ion | 9 ++- .../parser/internal/PartiQLParserDefault.kt | 13 +-- partiql-plan/api/partiql-plan.api | 26 +++--- partiql-plan/build.gradle.kts | 1 - .../src/main/resources/partiql_plan.ion | 2 +- .../org/partiql/planner/internal/ir/Nodes.kt | 4 +- .../internal/transforms/PlanTransform.kt | 1 - .../internal/transforms/PlanTransformV1.kt | 5 +- .../internal/transforms/RelConverter.kt | 6 +- .../internal/transforms/RexConverter.kt | 43 +++++----- .../main/resources/partiql_plan_internal.ion | 4 +- .../org/partiql/spi/value/ion/IonDatum.kt | 11 +++ partiql-types/api/partiql-types.api | 4 +- .../main/java/org/partiql/types/PType.java | 26 +++++- .../java/org/partiql/types/PTypeVariant.java | 47 +++++++++++ 19 files changed, 204 insertions(+), 109 deletions(-) create mode 100644 partiql-types/src/main/java/org/partiql/types/PTypeVariant.java diff --git a/partiql-ast/api/partiql-ast.api b/partiql-ast/api/partiql-ast.api index 498594d435..2672c0b24d 100644 --- a/partiql-ast/api/partiql-ast.api +++ b/partiql-ast/api/partiql-ast.api @@ -17,7 +17,6 @@ public final class org/partiql/ast/Ast { public static final fun exprDateDiff (Lorg/partiql/ast/DatetimeField;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;)Lorg/partiql/ast/Expr$DateDiff; public static final fun exprExtract (Lorg/partiql/ast/DatetimeField;Lorg/partiql/ast/Expr;)Lorg/partiql/ast/Expr$Extract; public static final fun exprInCollection (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Ljava/lang/Boolean;)Lorg/partiql/ast/Expr$InCollection; - public static final fun exprIon (Lcom/amazon/ionelement/api/IonElement;)Lorg/partiql/ast/Expr$Ion; public static final fun exprIsType (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Type;Ljava/lang/Boolean;)Lorg/partiql/ast/Expr$IsType; public static final fun exprLike (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Ljava/lang/Boolean;)Lorg/partiql/ast/Expr$Like; public static final fun exprLit (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/ast/Expr$Lit; @@ -43,6 +42,7 @@ public final class org/partiql/ast/Ast { public static final fun exprValues (Ljava/util/List;)Lorg/partiql/ast/Expr$Values; public static final fun exprValuesRow (Ljava/util/List;)Lorg/partiql/ast/Expr$Values$Row; public static final fun exprVar (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/Expr$Var$Scope;)Lorg/partiql/ast/Expr$Var; + public static final fun exprVariant (Ljava/lang/String;Ljava/lang/String;)Lorg/partiql/ast/Expr$Variant; public static final fun exprWindow (Lorg/partiql/ast/Expr$Window$Function;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr$Window$Over;)Lorg/partiql/ast/Expr$Window; public static final fun exprWindowOver (Ljava/util/List;Ljava/util/List;)Lorg/partiql/ast/Expr$Window$Over; public static final fun fromJoin (Lorg/partiql/ast/From;Lorg/partiql/ast/From;Lorg/partiql/ast/From$Join$Type;Lorg/partiql/ast/Expr;)Lorg/partiql/ast/From$Join; @@ -560,25 +560,6 @@ public final class org/partiql/ast/Expr$InCollection$Companion { public final fun builder ()Lorg/partiql/ast/builder/ExprInCollectionBuilder; } -public final class org/partiql/ast/Expr$Ion : org/partiql/ast/Expr { - public static final field Companion Lorg/partiql/ast/Expr$Ion$Companion; - public final field value Lcom/amazon/ionelement/api/IonElement; - public fun (Lcom/amazon/ionelement/api/IonElement;)V - public fun accept (Lorg/partiql/ast/visitor/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object; - public static final fun builder ()Lorg/partiql/ast/builder/ExprIonBuilder; - public final fun component1 ()Lcom/amazon/ionelement/api/IonElement; - public final fun copy (Lcom/amazon/ionelement/api/IonElement;)Lorg/partiql/ast/Expr$Ion; - public static synthetic fun copy$default (Lorg/partiql/ast/Expr$Ion;Lcom/amazon/ionelement/api/IonElement;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Ion; - public fun equals (Ljava/lang/Object;)Z - public fun getChildren ()Ljava/util/List; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class org/partiql/ast/Expr$Ion$Companion { - public final fun builder ()Lorg/partiql/ast/builder/ExprIonBuilder; -} - public final class org/partiql/ast/Expr$IsType : org/partiql/ast/Expr { public static final field Companion Lorg/partiql/ast/Expr$IsType$Companion; public final field not Ljava/lang/Boolean; @@ -1135,6 +1116,27 @@ public final class org/partiql/ast/Expr$Var$Scope : java/lang/Enum { public static fun values ()[Lorg/partiql/ast/Expr$Var$Scope; } +public final class org/partiql/ast/Expr$Variant : org/partiql/ast/Expr { + public static final field Companion Lorg/partiql/ast/Expr$Variant$Companion; + public final field encoding Ljava/lang/String; + public final field value Ljava/lang/String; + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun accept (Lorg/partiql/ast/visitor/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object; + public static final fun builder ()Lorg/partiql/ast/builder/ExprVariantBuilder; + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lorg/partiql/ast/Expr$Variant; + public static synthetic fun copy$default (Lorg/partiql/ast/Expr$Variant;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Variant; + public fun equals (Ljava/lang/Object;)Z + public fun getChildren ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class org/partiql/ast/Expr$Variant$Companion { + public final fun builder ()Lorg/partiql/ast/builder/ExprVariantBuilder; +} + public final class org/partiql/ast/Expr$Window : org/partiql/ast/Expr { public static final field Companion Lorg/partiql/ast/Expr$Window$Companion; public final field default Lorg/partiql/ast/Expr; @@ -3234,8 +3236,6 @@ public final class org/partiql/ast/builder/AstBuilder { public static synthetic fun exprExtract$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/DatetimeField;Lorg/partiql/ast/Expr;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Extract; public final fun exprInCollection (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Ljava/lang/Boolean;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$InCollection; public static synthetic fun exprInCollection$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Ljava/lang/Boolean;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$InCollection; - public final fun exprIon (Lcom/amazon/ionelement/api/IonElement;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Ion; - public static synthetic fun exprIon$default (Lorg/partiql/ast/builder/AstBuilder;Lcom/amazon/ionelement/api/IonElement;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Ion; public final fun exprIsType (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Type;Ljava/lang/Boolean;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$IsType; public static synthetic fun exprIsType$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Type;Ljava/lang/Boolean;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$IsType; public final fun exprLike (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Ljava/lang/Boolean;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Like; @@ -3286,6 +3286,8 @@ public final class org/partiql/ast/builder/AstBuilder { public static synthetic fun exprValuesRow$default (Lorg/partiql/ast/builder/AstBuilder;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Values$Row; public final fun exprVar (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/Expr$Var$Scope;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Var; public static synthetic fun exprVar$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Identifier;Lorg/partiql/ast/Expr$Var$Scope;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Var; + public final fun exprVariant (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Variant; + public static synthetic fun exprVariant$default (Lorg/partiql/ast/builder/AstBuilder;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Variant; public final fun exprWindow (Lorg/partiql/ast/Expr$Window$Function;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr$Window$Over;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Window; public static synthetic fun exprWindow$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Expr$Window$Function;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr$Window$Over;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Expr$Window; public final fun exprWindowOver (Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Expr$Window$Over; @@ -3701,16 +3703,6 @@ public final class org/partiql/ast/builder/ExprInCollectionBuilder { public final fun setRhs (Lorg/partiql/ast/Expr;)V } -public final class org/partiql/ast/builder/ExprIonBuilder { - public fun ()V - public fun (Lcom/amazon/ionelement/api/IonElement;)V - public synthetic fun (Lcom/amazon/ionelement/api/IonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun build ()Lorg/partiql/ast/Expr$Ion; - public final fun getValue ()Lcom/amazon/ionelement/api/IonElement; - public final fun setValue (Lcom/amazon/ionelement/api/IonElement;)V - public final fun value (Lcom/amazon/ionelement/api/IonElement;)Lorg/partiql/ast/builder/ExprIonBuilder; -} - public final class org/partiql/ast/builder/ExprIsTypeBuilder { public fun ()V public fun (Lorg/partiql/ast/Expr;Lorg/partiql/ast/Type;Ljava/lang/Boolean;)V @@ -4023,6 +4015,19 @@ public final class org/partiql/ast/builder/ExprVarBuilder { public final fun setScope (Lorg/partiql/ast/Expr$Var$Scope;)V } +public final class org/partiql/ast/builder/ExprVariantBuilder { + public fun ()V + public fun (Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lorg/partiql/ast/Expr$Variant; + public final fun encoding (Ljava/lang/String;)Lorg/partiql/ast/builder/ExprVariantBuilder; + public final fun getEncoding ()Ljava/lang/String; + public final fun getValue ()Ljava/lang/String; + public final fun setEncoding (Ljava/lang/String;)V + public final fun setValue (Ljava/lang/String;)V + public final fun value (Ljava/lang/String;)Lorg/partiql/ast/builder/ExprVariantBuilder; +} + public final class org/partiql/ast/builder/ExprWindowBuilder { public fun ()V public fun (Lorg/partiql/ast/Expr$Window$Function;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr;Lorg/partiql/ast/Expr$Window$Over;)V @@ -5109,8 +5114,6 @@ public abstract class org/partiql/ast/sql/SqlDialect : org/partiql/ast/visitor/A public fun visitExprExtract (Lorg/partiql/ast/Expr$Extract;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public synthetic fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; - public synthetic fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Ljava/lang/Object;)Ljava/lang/Object; - public fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public synthetic fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public synthetic fun visitExprLike (Lorg/partiql/ast/Expr$Like;Ljava/lang/Object;)Ljava/lang/Object; @@ -5159,6 +5162,8 @@ public abstract class org/partiql/ast/sql/SqlDialect : org/partiql/ast/visitor/A public fun visitExprValuesRow (Lorg/partiql/ast/Expr$Values$Row;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public synthetic fun visitExprVar (Lorg/partiql/ast/Expr$Var;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprVar (Lorg/partiql/ast/Expr$Var;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; + public synthetic fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public fun visitExprWrapped (Lorg/partiql/ast/Expr;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; public synthetic fun visitFromJoin (Lorg/partiql/ast/From$Join;Ljava/lang/Object;)Ljava/lang/Object; public fun visitFromJoin (Lorg/partiql/ast/From$Join;Lorg/partiql/ast/sql/SqlBlock;)Lorg/partiql/ast/sql/SqlBlock; @@ -5365,8 +5370,6 @@ public abstract class org/partiql/ast/util/AstRewriter : org/partiql/ast/visitor public fun visitExprExtract (Lorg/partiql/ast/Expr$Extract;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; - public synthetic fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Ljava/lang/Object;)Ljava/lang/Object; - public fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprLike (Lorg/partiql/ast/Expr$Like;Ljava/lang/Object;)Ljava/lang/Object; @@ -5417,6 +5420,8 @@ public abstract class org/partiql/ast/util/AstRewriter : org/partiql/ast/visitor public fun visitExprValuesRow (Lorg/partiql/ast/Expr$Values$Row;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprVar (Lorg/partiql/ast/Expr$Var;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprVar (Lorg/partiql/ast/Expr$Var;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; + public synthetic fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprWindow (Lorg/partiql/ast/Expr$Window;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprWindow (Lorg/partiql/ast/Expr$Window;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitExprWindowOver (Lorg/partiql/ast/Expr$Window$Over;Ljava/lang/Object;)Ljava/lang/Object; @@ -5626,7 +5631,6 @@ public abstract class org/partiql/ast/visitor/AstBaseVisitor : org/partiql/ast/v public fun visitExprDateDiff (Lorg/partiql/ast/Expr$DateDiff;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprExtract (Lorg/partiql/ast/Expr$Extract;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Ljava/lang/Object;)Ljava/lang/Object; - public fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprLike (Lorg/partiql/ast/Expr$Like;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprLit (Lorg/partiql/ast/Expr$Lit;Ljava/lang/Object;)Ljava/lang/Object; @@ -5653,6 +5657,7 @@ public abstract class org/partiql/ast/visitor/AstBaseVisitor : org/partiql/ast/v public fun visitExprValues (Lorg/partiql/ast/Expr$Values;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprValuesRow (Lorg/partiql/ast/Expr$Values$Row;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprVar (Lorg/partiql/ast/Expr$Var;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprWindow (Lorg/partiql/ast/Expr$Window;Ljava/lang/Object;)Ljava/lang/Object; public fun visitExprWindowOver (Lorg/partiql/ast/Expr$Window$Over;Ljava/lang/Object;)Ljava/lang/Object; public fun visitFrom (Lorg/partiql/ast/From;Ljava/lang/Object;)Ljava/lang/Object; @@ -5782,7 +5787,6 @@ public abstract interface class org/partiql/ast/visitor/AstVisitor { public abstract fun visitExprDateDiff (Lorg/partiql/ast/Expr$DateDiff;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprExtract (Lorg/partiql/ast/Expr$Extract;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprInCollection (Lorg/partiql/ast/Expr$InCollection;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun visitExprIon (Lorg/partiql/ast/Expr$Ion;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprIsType (Lorg/partiql/ast/Expr$IsType;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprLike (Lorg/partiql/ast/Expr$Like;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprLit (Lorg/partiql/ast/Expr$Lit;Ljava/lang/Object;)Ljava/lang/Object; @@ -5809,6 +5813,7 @@ public abstract interface class org/partiql/ast/visitor/AstVisitor { public abstract fun visitExprValues (Lorg/partiql/ast/Expr$Values;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprValuesRow (Lorg/partiql/ast/Expr$Values$Row;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprVar (Lorg/partiql/ast/Expr$Var;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun visitExprVariant (Lorg/partiql/ast/Expr$Variant;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprWindow (Lorg/partiql/ast/Expr$Window;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitExprWindowOver (Lorg/partiql/ast/Expr$Window$Over;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitFrom (Lorg/partiql/ast/From;Ljava/lang/Object;)Ljava/lang/Object; diff --git a/partiql-ast/src/main/kotlin/org/partiql/ast/helpers/ToLegacyAst.kt b/partiql-ast/src/main/kotlin/org/partiql/ast/helpers/ToLegacyAst.kt index a75898c6c3..0995ee9788 100644 --- a/partiql-ast/src/main/kotlin/org/partiql/ast/helpers/ToLegacyAst.kt +++ b/partiql-ast/src/main/kotlin/org/partiql/ast/helpers/ToLegacyAst.kt @@ -7,6 +7,7 @@ import com.amazon.ionelement.api.DecimalElement import com.amazon.ionelement.api.FloatElement import com.amazon.ionelement.api.IntElement import com.amazon.ionelement.api.IntElementSize +import com.amazon.ionelement.api.IonElementException import com.amazon.ionelement.api.MetaContainer import com.amazon.ionelement.api.emptyMetaContainer import com.amazon.ionelement.api.ionDecimal @@ -14,6 +15,7 @@ import com.amazon.ionelement.api.ionFloat import com.amazon.ionelement.api.ionInt import com.amazon.ionelement.api.ionString import com.amazon.ionelement.api.ionSymbol +import com.amazon.ionelement.api.loadSingleElement import com.amazon.ionelement.api.metaContainerOf import org.partiql.ast.AstNode import org.partiql.ast.DatetimeField @@ -270,8 +272,16 @@ private class AstTranslator(val metas: Map) : AstBaseVisi } } - override fun visitExprIon(node: Expr.Ion, ctx: Ctx) = translate(node) { metas -> - lit(node.value, metas) + override fun visitExprVariant(node: Expr.Variant, ctx: Ctx) = translate(node) { metas -> + if (node.encoding != "ion") { + error("Only `ion` variant encoding is supported in legacy AST") + } + val value = try { + loadSingleElement(node.value) + } catch (e: IonElementException) { + error("Unable to parse Ion value.") + } + lit(value, metas) } override fun visitExprVar(node: Expr.Var, ctx: Ctx) = translate(node) { metas -> diff --git a/partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt b/partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt index 59b799bc4f..d7d0547aac 100644 --- a/partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt +++ b/partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt @@ -224,9 +224,11 @@ public abstract class SqlDialect : AstBaseVisitor() { return head concat r(value) } - override fun visitExprIon(node: Expr.Ion, head: SqlBlock): SqlBlock { - // simplified Ion value writing, as this intentionally omits formatting - val value = node.value.toString() + override fun visitExprVariant(node: Expr.Variant, head: SqlBlock): SqlBlock { + if (node.encoding != "ion") { + error("Unsupported encoding ${node.encoding}") + } + val value = node.value return head concat r("`$value`") } diff --git a/partiql-ast/src/main/kotlin/org/partiql/ast/sql/internal/InternalSqlDialect.kt b/partiql-ast/src/main/kotlin/org/partiql/ast/sql/internal/InternalSqlDialect.kt index ec4ee0af2e..ab996b283f 100644 --- a/partiql-ast/src/main/kotlin/org/partiql/ast/sql/internal/InternalSqlDialect.kt +++ b/partiql-ast/src/main/kotlin/org/partiql/ast/sql/internal/InternalSqlDialect.kt @@ -247,9 +247,11 @@ internal abstract class InternalSqlDialect : AstBaseVisitor` - ion::{ - value: '.ion', + // Variant literals such as `` + variant::{ + value: string, + encoding: string, }, // Variable Reference diff --git a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt index 706a9a3f70..dfdcc3591f 100644 --- a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt +++ b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt @@ -17,8 +17,6 @@ package org.partiql.parser.internal import com.amazon.ionelement.api.IntElement import com.amazon.ionelement.api.IntElementSize import com.amazon.ionelement.api.IonElement -import com.amazon.ionelement.api.IonElementException -import com.amazon.ionelement.api.loadSingleElement import org.antlr.v4.runtime.BailErrorStrategy import org.antlr.v4.runtime.BaseErrorListener import org.antlr.v4.runtime.CharStreams @@ -67,7 +65,6 @@ import org.partiql.ast.exprDateAdd import org.partiql.ast.exprDateDiff import org.partiql.ast.exprExtract import org.partiql.ast.exprInCollection -import org.partiql.ast.exprIon import org.partiql.ast.exprIsType import org.partiql.ast.exprLike import org.partiql.ast.exprLit @@ -91,6 +88,7 @@ import org.partiql.ast.exprStructField import org.partiql.ast.exprSubstring import org.partiql.ast.exprTrim import org.partiql.ast.exprVar +import org.partiql.ast.exprVariant import org.partiql.ast.exprWindow import org.partiql.ast.exprWindowOver import org.partiql.ast.fromJoin @@ -1820,12 +1818,9 @@ internal class PartiQLParserDefault : PartiQLParser { } override fun visitLiteralIon(ctx: GeneratedParser.LiteralIonContext) = translate(ctx) { - val value = try { - loadSingleElement(ctx.ION_CLOSURE().getStringValue()) - } catch (e: IonElementException) { - throw error(ctx, "Unable to parse Ion value.", e) - } - exprIon(value) + val value = ctx.ION_CLOSURE().getStringValue() + val encoding = "ion" + exprVariant(value, encoding) } override fun visitLiteralString(ctx: GeneratedParser.LiteralStringContext) = translate(ctx) { diff --git a/partiql-plan/api/partiql-plan.api b/partiql-plan/api/partiql-plan.api index d46203ced0..2ca8b4d204 100644 --- a/partiql-plan/api/partiql-plan.api +++ b/partiql-plan/api/partiql-plan.api @@ -210,7 +210,7 @@ public final class org/partiql/plan/Plan { public static final fun rexOpCollection (Ljava/util/List;)Lorg/partiql/plan/Rex$Op$Collection; public static final fun rexOpErr (Ljava/lang/String;Ljava/util/List;)Lorg/partiql/plan/Rex$Op$Err; public static final fun rexOpGlobal (Lorg/partiql/plan/Ref;)Lorg/partiql/plan/Rex$Op$Global; - public static final fun rexOpLit (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/plan/Rex$Op$Lit; + public static final fun rexOpLit (Lorg/partiql/spi/value/Datum;)Lorg/partiql/plan/Rex$Op$Lit; public static final fun rexOpMissing (Ljava/lang/String;Ljava/util/List;)Lorg/partiql/plan/Rex$Op$Missing; public static final fun rexOpNullif (Lorg/partiql/plan/Rex;Lorg/partiql/plan/Rex;)Lorg/partiql/plan/Rex$Op$Nullif; public static final fun rexOpPathIndex (Lorg/partiql/plan/Rex;Lorg/partiql/plan/Rex;)Lorg/partiql/plan/Rex$Op$Path$Index; @@ -1143,13 +1143,13 @@ public final class org/partiql/plan/Rex$Op$Global$Companion { public final class org/partiql/plan/Rex$Op$Lit : org/partiql/plan/Rex$Op { public static final field Companion Lorg/partiql/plan/Rex$Op$Lit$Companion; - public final field value Lorg/partiql/value/PartiQLValue; - public fun (Lorg/partiql/value/PartiQLValue;)V + public final field value Lorg/partiql/spi/value/Datum; + public fun (Lorg/partiql/spi/value/Datum;)V public fun accept (Lorg/partiql/plan/visitor/PlanVisitor;Ljava/lang/Object;)Ljava/lang/Object; public static final fun builder ()Lorg/partiql/plan/builder/RexOpLitBuilder; - public final fun component1 ()Lorg/partiql/value/PartiQLValue; - public final fun copy (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/plan/Rex$Op$Lit; - public static synthetic fun copy$default (Lorg/partiql/plan/Rex$Op$Lit;Lorg/partiql/value/PartiQLValue;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Lit; + public final fun component1 ()Lorg/partiql/spi/value/Datum; + public final fun copy (Lorg/partiql/spi/value/Datum;)Lorg/partiql/plan/Rex$Op$Lit; + public static synthetic fun copy$default (Lorg/partiql/plan/Rex$Op$Lit;Lorg/partiql/spi/value/Datum;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Lit; public fun equals (Ljava/lang/Object;)Z public fun getChildren ()Ljava/util/List; public fun hashCode ()I @@ -1644,8 +1644,8 @@ public final class org/partiql/plan/builder/PlanBuilder { public static synthetic fun rexOpErr$default (Lorg/partiql/plan/builder/PlanBuilder;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Err; public final fun rexOpGlobal (Lorg/partiql/plan/Ref;Lkotlin/jvm/functions/Function1;)Lorg/partiql/plan/Rex$Op$Global; public static synthetic fun rexOpGlobal$default (Lorg/partiql/plan/builder/PlanBuilder;Lorg/partiql/plan/Ref;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Global; - public final fun rexOpLit (Lorg/partiql/value/PartiQLValue;Lkotlin/jvm/functions/Function1;)Lorg/partiql/plan/Rex$Op$Lit; - public static synthetic fun rexOpLit$default (Lorg/partiql/plan/builder/PlanBuilder;Lorg/partiql/value/PartiQLValue;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Lit; + public final fun rexOpLit (Lorg/partiql/spi/value/Datum;Lkotlin/jvm/functions/Function1;)Lorg/partiql/plan/Rex$Op$Lit; + public static synthetic fun rexOpLit$default (Lorg/partiql/plan/builder/PlanBuilder;Lorg/partiql/spi/value/Datum;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Lit; public final fun rexOpMissing (Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lorg/partiql/plan/Rex$Op$Missing; public static synthetic fun rexOpMissing$default (Lorg/partiql/plan/builder/PlanBuilder;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/plan/Rex$Op$Missing; public final fun rexOpNullif (Lorg/partiql/plan/Rex;Lorg/partiql/plan/Rex;Lkotlin/jvm/functions/Function1;)Lorg/partiql/plan/Rex$Op$Nullif; @@ -2191,12 +2191,12 @@ public final class org/partiql/plan/builder/RexOpGlobalBuilder { public final class org/partiql/plan/builder/RexOpLitBuilder { public fun ()V - public fun (Lorg/partiql/value/PartiQLValue;)V - public synthetic fun (Lorg/partiql/value/PartiQLValue;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lorg/partiql/spi/value/Datum;)V + public synthetic fun (Lorg/partiql/spi/value/Datum;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun build ()Lorg/partiql/plan/Rex$Op$Lit; - public final fun getValue ()Lorg/partiql/value/PartiQLValue; - public final fun setValue (Lorg/partiql/value/PartiQLValue;)V - public final fun value (Lorg/partiql/value/PartiQLValue;)Lorg/partiql/plan/builder/RexOpLitBuilder; + public final fun getValue ()Lorg/partiql/spi/value/Datum; + public final fun setValue (Lorg/partiql/spi/value/Datum;)V + public final fun value (Lorg/partiql/spi/value/Datum;)Lorg/partiql/plan/builder/RexOpLitBuilder; } public final class org/partiql/plan/builder/RexOpMissingBuilder { diff --git a/partiql-plan/build.gradle.kts b/partiql-plan/build.gradle.kts index 180327261f..580ef5b92c 100644 --- a/partiql-plan/build.gradle.kts +++ b/partiql-plan/build.gradle.kts @@ -63,7 +63,6 @@ val generate = tasks.register("generate") { "--poems", "visitor", "--poems", "builder", "--poems", "util", - "--opt-in", "org.partiql.value.PartiQLValueExperimental", "./src/main/resources/partiql_plan.ion" ) } diff --git a/partiql-plan/src/main/resources/partiql_plan.ion b/partiql-plan/src/main/resources/partiql_plan.ion index 19414e918f..3d6caac4ce 100644 --- a/partiql-plan/src/main/resources/partiql_plan.ion +++ b/partiql-plan/src/main/resources/partiql_plan.ion @@ -1,6 +1,6 @@ imports::{ kotlin: [ - partiql_value::'org.partiql.value.PartiQLValue', + partiql_value::'org.partiql.spi.value.Datum', partiql_value_type::'org.partiql.types.PType', static_type::'org.partiql.types.PType', function::'org.partiql.spi.fn.Function', diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/ir/Nodes.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/ir/Nodes.kt index 428588d38e..a097cb317f 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/ir/Nodes.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/ir/Nodes.kt @@ -72,7 +72,7 @@ import org.partiql.spi.catalog.Name import org.partiql.spi.catalog.Table import org.partiql.spi.fn.Aggregation import org.partiql.spi.fn.Function -import org.partiql.value.PartiQLValue +import org.partiql.spi.value.Datum import org.partiql.value.PartiQLValueExperimental import kotlin.random.Random @@ -234,7 +234,7 @@ internal data class Rex( } internal data class Lit( - @JvmField internal val `value`: PartiQLValue, + @JvmField internal val `value`: Datum, ) : Op() { public override val children: List = emptyList() 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 2da241825f..2d0c88c2d5 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 @@ -99,7 +99,6 @@ internal class PlanTransform( override fun visitRexOp(node: Rex.Op, ctx: Unit) = super.visitRexOp(node, ctx) as org.partiql.plan.Rex.Op - @OptIn(PartiQLValueExperimental::class) override fun visitRexOpLit(node: Rex.Op.Lit, ctx: Unit) = org.partiql.plan.rexOpLit(node.value) override fun visitRexOpVar(node: Rex.Op.Var, ctx: Unit) = diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransformV1.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransformV1.kt index 99012e03f5..abd17b07e8 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransformV1.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransformV1.kt @@ -21,10 +21,8 @@ import org.partiql.planner.internal.PlannerFlag import org.partiql.planner.internal.ProblemGenerator import org.partiql.planner.internal.ir.SetQuantifier import org.partiql.planner.internal.ir.visitor.PlanBaseVisitor -import org.partiql.spi.value.Datum import org.partiql.types.Field import org.partiql.types.PType -import org.partiql.value.PartiQLValueExperimental import org.partiql.planner.internal.ir.PartiQLPlan as IPlan import org.partiql.planner.internal.ir.PlanNode as INode import org.partiql.planner.internal.ir.Rel as IRel @@ -244,9 +242,8 @@ internal class PlanTransformV1(private val flags: Set) { return factory.rexVar(depth = node.depth, offset = node.ref) } - @OptIn(PartiQLValueExperimental::class) override fun visitRexOpLit(node: IRex.Op.Lit, ctx: PType): Any { - return factory.rexLit(Datum.of(node.value)) + return factory.rexLit(node.value) } // RELATION OPERATORS diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt index 6579a873fa..ac264cf880 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt @@ -71,6 +71,7 @@ import org.partiql.planner.internal.ir.rexOpStruct import org.partiql.planner.internal.ir.rexOpStructField import org.partiql.planner.internal.ir.rexOpVarLocal import org.partiql.planner.internal.typer.CompilerType +import org.partiql.spi.value.Datum import org.partiql.types.PType import org.partiql.value.PartiQLValueExperimental import org.partiql.value.boolValue @@ -276,13 +277,12 @@ internal object RelConverter { * * TODO compute basic schema */ - @OptIn(PartiQLValueExperimental::class) override fun visitFromJoin(node: From.Join, nil: Rel): Rel { val lhs = visitFrom(node.lhs, nil) val rhs = visitFrom(node.rhs, nil) val schema = lhs.type.schema + rhs.type.schema // Note: This gets more specific in PlanTyper. It is only used to find binding names here. val props = emptySet() - val condition = node.condition?.let { RexConverter.apply(it, env) } ?: rex(BOOL, rexOpLit(boolValue(true))) + val condition = node.condition?.let { RexConverter.apply(it, env) } ?: rex(BOOL, rexOpLit(Datum.bool(true))) val joinType = when (node.type) { From.Join.Type.LEFT_OUTER, From.Join.Type.LEFT -> Rel.Op.Join.Type.LEFT From.Join.Type.RIGHT_OUTER, From.Join.Type.RIGHT -> Rel.Op.Join.Type.RIGHT @@ -423,7 +423,7 @@ internal object RelConverter { schema.add(binding) val fields = input.type.schema.mapIndexed { bindingIndex, currBinding -> rexOpStructField( - k = rex(STRING, rexOpLit(stringValue(currBinding.name))), + k = rex(STRING, rexOpLit(Datum.string(currBinding.name))), v = rex(ANY, rexOpVarLocal(0, bindingIndex)) ) } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt index 33a7e1de89..01058cfca2 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt @@ -54,16 +54,12 @@ import org.partiql.planner.internal.ir.rexOpVarUnresolved import org.partiql.planner.internal.typer.CompilerType import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType import org.partiql.spi.catalog.Identifier +import org.partiql.spi.value.Datum +import org.partiql.spi.value.ion.IonDatum import org.partiql.types.PType import org.partiql.value.MissingValue import org.partiql.value.PartiQLValueExperimental import org.partiql.value.StringValue -import org.partiql.value.boolValue -import org.partiql.value.int32Value -import org.partiql.value.int64Value -import org.partiql.value.io.PartiQLValueIonReaderBuilder -import org.partiql.value.nullValue -import org.partiql.value.stringValue import org.partiql.ast.Identifier as AstIdentifier /** @@ -99,15 +95,17 @@ internal object RexConverter { isNullValue = node.value.isNull, isMissingValue = node.value is MissingValue ) - val op = rexOpLit(node.value) + // TODO update in https://github.com/partiql/partiql-lang-kotlin/issues/1589 + val op = rexOpLit(Datum.of(node.value)) return rex(type, op) } - override fun visitExprIon(node: Expr.Ion, ctx: Env): Rex { - val value = - PartiQLValueIonReaderBuilder - .standard().build(node.value).read() - val type = CompilerType(value.type.toPType()) + override fun visitExprVariant(node: Expr.Variant, ctx: Env): Rex { + val value = when (node.encoding) { + "ion" -> IonDatum.of(node.value) + else -> throw IllegalArgumentException("unsupported variant encoding ${node.encoding}") + } + val type = CompilerType(value.type) return rex(type, rexOpLit(value)) } @@ -410,7 +408,7 @@ internal object RexConverter { val schema = acc.type.schema + scan.type.schema val props = emptySet() val type = relType(schema, props) - rel(type, relOpJoin(acc, scan, rex(BOOL, rexOpLit(boolValue(true))), Rel.Op.Join.Type.INNER)) + rel(type, relOpJoin(acc, scan, rex(BOOL, rexOpLit(Datum.bool(true))), Rel.Op.Join.Type.INNER)) } // compute the ref used by select construct @@ -466,7 +464,7 @@ internal object RexConverter { return rel(relType, relOpUnpivot(path)) } - private fun rexString(str: String) = rex(STRING, rexOpLit(stringValue(str))) + private fun rexString(str: String) = rex(STRING, rexOpLit(Datum.string(str))) override fun visitExprCall(node: Expr.Call, context: Env): Rex { val type = (ANY) @@ -574,7 +572,7 @@ internal object RexConverter { }.toMutableList() val defaultRex = when (val default = node.default) { - null -> rex(type = ANY, op = rexOpLit(value = nullValue())) + null -> rex(type = ANY, op = rexOpLit(value = Datum.nullValue())) else -> visitExprCoerce(default, context) } val op = rexOpCase(branches = branches, default = defaultRex) @@ -752,7 +750,7 @@ internal object RexConverter { val type = ANY // Args val arg0 = visitExprCoerce(node.value, ctx) - val arg1 = node.start?.let { visitExprCoerce(it, ctx) } ?: rex(INT, rexOpLit(int64Value(1))) + val arg1 = node.start?.let { visitExprCoerce(it, ctx) } ?: rex(INT, rexOpLit(Datum.bigint(1))) val arg2 = node.length?.let { visitExprCoerce(it, ctx) } // Call Variants val call = when (arg2) { @@ -830,8 +828,8 @@ internal object RexConverter { call( "substring", cv, - rex(INT4, rexOpLit(int32Value(1))), - rex(ANY, call("minus", sp, rex(INT4, rexOpLit(int32Value(1))))) + rex(INT4, rexOpLit(Datum.integer(1))), + rex(ANY, call("minus", sp, rex(INT4, rexOpLit(Datum.integer(1))))) ) ) val p2 = rex(ANY, call("concat", p1, rs)) @@ -962,7 +960,14 @@ internal object RexConverter { return rexOpCallUnresolved(id, args.toList()) } - private fun Int?.toRex() = rex(INT4, rexOpLit(int32Value(this))) + private fun Int?.toRex(): Rex { + val datum = if (this == null) { + Datum.nullValue(PType.integer()) + } else { + Datum.integer(this) + } + return rex(INT4, rexOpLit(datum)) + } private val ANY: CompilerType = CompilerType(PType.dynamic()) private val BOOL: CompilerType = CompilerType(PType.bool()) diff --git a/partiql-planner/src/main/resources/partiql_plan_internal.ion b/partiql-planner/src/main/resources/partiql_plan_internal.ion index a45efb3bdc..2689bc6825 100644 --- a/partiql-planner/src/main/resources/partiql_plan_internal.ion +++ b/partiql-planner/src/main/resources/partiql_plan_internal.ion @@ -2,7 +2,7 @@ imports::{ kotlin: [ identifier::'org.partiql.spi.catalog.Identifier', name::'org.partiql.spi.catalog.Name', - partiql_value::'org.partiql.value.PartiQLValue', + datum::'org.partiql.spi.value.Datum', partiql_value_type::'org.partiql.planner.internal.typer.CompilerType', static_type::'org.partiql.planner.internal.typer.CompilerType', fn_signature::'org.partiql.spi.fn.Function', @@ -73,7 +73,7 @@ rex::{ op:[ lit::{ - value: partiql_value, + value: datum, }, var::[ diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/value/ion/IonDatum.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/value/ion/IonDatum.kt index 525a48a067..13018d988a 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/value/ion/IonDatum.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/value/ion/IonDatum.kt @@ -14,6 +14,7 @@ import com.amazon.ionelement.api.ElementType.STRING import com.amazon.ionelement.api.ElementType.STRUCT import com.amazon.ionelement.api.ElementType.SYMBOL import com.amazon.ionelement.api.ElementType.TIMESTAMP +import com.amazon.ionelement.api.loadSingleElement import org.partiql.spi.value.Datum import org.partiql.spi.value.Field import org.partiql.types.PType @@ -132,6 +133,16 @@ public class IonDatum private constructor(value: AnyElement, type: PType) : } return IonDatum(value, type) } + + @JvmStatic + public fun of(value: String): Datum { + val ion = try { + loadSingleElement(value) + } catch (e: Exception) { + throw IllegalArgumentException("Invalid Ion value: $value", e) + } + return of(ion) + } } override fun getType(): PType = _type diff --git a/partiql-types/api/partiql-types.api b/partiql-types/api/partiql-types.api index 5a444a2898..c20627b88e 100644 --- a/partiql-types/api/partiql-types.api +++ b/partiql-types/api/partiql-types.api @@ -323,6 +323,7 @@ public abstract interface class org/partiql/types/PType { public static fun doublePrecision ()Lorg/partiql/types/PType; public static fun dynamic ()Lorg/partiql/types/PType; public static fun fromStaticType (Lorg/partiql/types/StaticType;)Lorg/partiql/types/PType; + public fun getEncoding ()Ljava/lang/String; public fun getFields ()Ljava/util/Collection; public abstract fun getKind ()Lorg/partiql/types/PType$Kind; public fun getLength ()I @@ -346,6 +347,7 @@ public abstract interface class org/partiql/types/PType { public static fun tinyint ()Lorg/partiql/types/PType; public static fun unknown ()Lorg/partiql/types/PType; public static fun varchar (I)Lorg/partiql/types/PType; + public static fun variant (Ljava/lang/String;)Lorg/partiql/types/PType; } public final class org/partiql/types/PType$Kind : java/lang/Enum { @@ -375,9 +377,9 @@ public final class org/partiql/types/PType$Kind : java/lang/Enum { public static final field TIMESTAMPZ Lorg/partiql/types/PType$Kind; public static final field TIMEZ Lorg/partiql/types/PType$Kind; public static final field TINYINT Lorg/partiql/types/PType$Kind; - public static final field UDT Lorg/partiql/types/PType$Kind; public static final field UNKNOWN Lorg/partiql/types/PType$Kind; public static final field VARCHAR Lorg/partiql/types/PType$Kind; + public static final field VARIANT Lorg/partiql/types/PType$Kind; public static fun valueOf (Ljava/lang/String;)Lorg/partiql/types/PType$Kind; public static fun values ()[Lorg/partiql/types/PType$Kind; } diff --git a/partiql-types/src/main/java/org/partiql/types/PType.java b/partiql-types/src/main/java/org/partiql/types/PType.java index 77ea865aba..6000c357ce 100644 --- a/partiql-types/src/main/java/org/partiql/types/PType.java +++ b/partiql-types/src/main/java/org/partiql/types/PType.java @@ -44,6 +44,16 @@ public interface PType { @NotNull Kind getKind(); + /** + * Returns the variant type encoding. + * + * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: + * {@link Kind#VARIANT} + */ + default String getEncoding() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + /** * The fields of the type * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: @@ -432,14 +442,16 @@ enum Kind { STRUCT, /** - * UDT represents a user-defined type. + * PartiQL's variant type. *
+ * @see Spark VARIANT + * @see Snowflake VARIANT *
- * Type Syntax: CURRENTLY NOT APPLICABLE + * Type Syntax: NOT APPLICABLE *
* Applicable methods: Implementation defined. */ - UDT, + VARIANT, /** * PartiQL's unknown type. This temporarily represents literal null and missing values. @@ -715,6 +727,14 @@ static PType struct() { return new PTypePrimitive(Kind.STRUCT); } + /** + * @return a PartiQL variant type with the given encoding. + */ + @NotNull + static PType variant(String encoding) { + return new PTypeVariant(encoding); + } + /** * @return a PartiQL unknown type * @deprecated this API is experimental and is subject to modification/deletion without prior notice. diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java b/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java new file mode 100644 index 0000000000..1fbf1c8ddf --- /dev/null +++ b/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java @@ -0,0 +1,47 @@ +package org.partiql.types; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +class PTypeVariant implements PType { + + @NotNull + final String _encoding; + + public PTypeVariant(@NotNull String encoding) { + this._encoding = encoding; + } + + @NotNull + @Override + public Kind getKind() { + return Kind.VARIANT; + } + + @Override + public String getEncoding() throws UnsupportedOperationException { + return _encoding; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PTypeVariant)) return false; + PTypeVariant that = (PTypeVariant) o; + return Objects.equals(_encoding, that._encoding); + } + + @Override + public int hashCode() { + int hashcode = 0; + hashcode += "variant".hashCode(); + hashcode += 31 * _encoding.hashCode(); + return hashcode; + } + + @Override + public String toString() { + return "VARIANT(" + _encoding + ")"; + } +}