diff --git a/partiql-ast/api/partiql-ast.api b/partiql-ast/api/partiql-ast.api index 2ba4a4c311..8f4b9a31c5 100644 --- a/partiql-ast/api/partiql-ast.api +++ b/partiql-ast/api/partiql-ast.api @@ -127,6 +127,7 @@ public final class org/partiql/ast/Ast { public static final fun tableDefinition (Ljava/util/List;Ljava/util/List;)Lorg/partiql/ast/TableDefinition; public static final fun tableDefinitionAttribute (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;)Lorg/partiql/ast/TableDefinition$Attribute; public static final fun typeAny ()Lorg/partiql/ast/Type$Any; + public static final fun typeArray (Lorg/partiql/ast/Type;)Lorg/partiql/ast/Type$Array; public static final fun typeBag ()Lorg/partiql/ast/Type$Bag; public static final fun typeBigint ()Lorg/partiql/ast/Type$Bigint; public static final fun typeBit (Ljava/lang/Integer;)Lorg/partiql/ast/Type$Bit; @@ -154,7 +155,8 @@ public final class org/partiql/ast/Ast { public static final fun typeSexp ()Lorg/partiql/ast/Type$Sexp; public static final fun typeSmallint ()Lorg/partiql/ast/Type$Smallint; public static final fun typeString (Ljava/lang/Integer;)Lorg/partiql/ast/Type$String; - public static final fun typeStruct ()Lorg/partiql/ast/Type$Struct; + public static final fun typeStruct (Ljava/util/List;)Lorg/partiql/ast/Type$Struct; + public static final fun typeStructField (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;)Lorg/partiql/ast/Type$Struct$Field; public static final fun typeSymbol ()Lorg/partiql/ast/Type$Symbol; public static final fun typeTime (Ljava/lang/Integer;)Lorg/partiql/ast/Type$Time; public static final fun typeTimeWithTz (Ljava/lang/Integer;)Lorg/partiql/ast/Type$TimeWithTz; @@ -3168,6 +3170,25 @@ public final class org/partiql/ast/Type$Any$Companion { public final fun builder ()Lorg/partiql/ast/builder/TypeAnyBuilder; } +public final class org/partiql/ast/Type$Array : org/partiql/ast/Type { + public static final field Companion Lorg/partiql/ast/Type$Array$Companion; + public final field type Lorg/partiql/ast/Type; + public fun (Lorg/partiql/ast/Type;)V + public fun accept (Lorg/partiql/ast/visitor/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object; + public static final fun builder ()Lorg/partiql/ast/builder/TypeArrayBuilder; + public final fun component1 ()Lorg/partiql/ast/Type; + public final fun copy (Lorg/partiql/ast/Type;)Lorg/partiql/ast/Type$Array; + public static synthetic fun copy$default (Lorg/partiql/ast/Type$Array;Lorg/partiql/ast/Type;ILjava/lang/Object;)Lorg/partiql/ast/Type$Array; + 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/Type$Array$Companion { + public final fun builder ()Lorg/partiql/ast/builder/TypeArrayBuilder; +} + public final class org/partiql/ast/Type$Bag : org/partiql/ast/Type { public final field C public static final field Companion Lorg/partiql/ast/Type$Bag$Companion; @@ -3718,16 +3739,14 @@ public final class org/partiql/ast/Type$String$Companion { } public final class org/partiql/ast/Type$Struct : org/partiql/ast/Type { - public final field C public static final field Companion Lorg/partiql/ast/Type$Struct$Companion; - public fun ()V - public fun (C)V - public synthetic fun (CILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final field fields Ljava/util/List; + public fun (Ljava/util/List;)V public fun accept (Lorg/partiql/ast/visitor/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object; public static final fun builder ()Lorg/partiql/ast/builder/TypeStructBuilder; - public final fun component1 ()C - public final fun copy (C)Lorg/partiql/ast/Type$Struct; - public static synthetic fun copy$default (Lorg/partiql/ast/Type$Struct;CILjava/lang/Object;)Lorg/partiql/ast/Type$Struct; + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lorg/partiql/ast/Type$Struct; + public static synthetic fun copy$default (Lorg/partiql/ast/Type$Struct;Ljava/util/List;ILjava/lang/Object;)Lorg/partiql/ast/Type$Struct; public fun equals (Ljava/lang/Object;)Z public fun getChildren ()Ljava/util/List; public fun hashCode ()I @@ -3738,6 +3757,29 @@ public final class org/partiql/ast/Type$Struct$Companion { public final fun builder ()Lorg/partiql/ast/builder/TypeStructBuilder; } +public final class org/partiql/ast/Type$Struct$Field : org/partiql/ast/AstNode { + public static final field Companion Lorg/partiql/ast/Type$Struct$Field$Companion; + public final field constraints Ljava/util/List; + public final field name Lorg/partiql/ast/Identifier$Symbol; + public final field type Lorg/partiql/ast/Type; + public fun (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;)V + public fun accept (Lorg/partiql/ast/visitor/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object; + public static final fun builder ()Lorg/partiql/ast/builder/TypeStructFieldBuilder; + public final fun component1 ()Lorg/partiql/ast/Identifier$Symbol; + public final fun component2 ()Lorg/partiql/ast/Type; + public final fun component3 ()Ljava/util/List; + public final fun copy (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;)Lorg/partiql/ast/Type$Struct$Field; + public static synthetic fun copy$default (Lorg/partiql/ast/Type$Struct$Field;Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;ILjava/lang/Object;)Lorg/partiql/ast/Type$Struct$Field; + 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/Type$Struct$Field$Companion { + public final fun builder ()Lorg/partiql/ast/builder/TypeStructFieldBuilder; +} + public final class org/partiql/ast/Type$Symbol : org/partiql/ast/Type { public final field C public static final field Companion Lorg/partiql/ast/Type$Symbol$Companion; @@ -4154,6 +4196,8 @@ public final class org/partiql/ast/builder/AstBuilder { public static synthetic fun tableDefinitionAttribute$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/TableDefinition$Attribute; public final fun typeAny (Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Any; public static synthetic fun typeAny$default (Lorg/partiql/ast/builder/AstBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Any; + public final fun typeArray (Lorg/partiql/ast/Type;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Array; + public static synthetic fun typeArray$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Type;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Array; public final fun typeBag (Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Bag; public static synthetic fun typeBag$default (Lorg/partiql/ast/builder/AstBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Bag; public final fun typeBigint (Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Bigint; @@ -4208,8 +4252,10 @@ public final class org/partiql/ast/builder/AstBuilder { public static synthetic fun typeSmallint$default (Lorg/partiql/ast/builder/AstBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Smallint; public final fun typeString (Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$String; public static synthetic fun typeString$default (Lorg/partiql/ast/builder/AstBuilder;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$String; - public final fun typeStruct (Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Struct; - public static synthetic fun typeStruct$default (Lorg/partiql/ast/builder/AstBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Struct; + public final fun typeStruct (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Struct; + public static synthetic fun typeStruct$default (Lorg/partiql/ast/builder/AstBuilder;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Struct; + public final fun typeStructField (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Struct$Field; + public static synthetic fun typeStructField$default (Lorg/partiql/ast/builder/AstBuilder;Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Struct$Field; public final fun typeSymbol (Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Symbol; public static synthetic fun typeSymbol$default (Lorg/partiql/ast/builder/AstBuilder;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/partiql/ast/Type$Symbol; public final fun typeTime (Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)Lorg/partiql/ast/Type$Time; @@ -5853,6 +5899,16 @@ public final class org/partiql/ast/builder/TypeAnyBuilder { public final fun build ()Lorg/partiql/ast/Type$Any; } +public final class org/partiql/ast/builder/TypeArrayBuilder { + public fun ()V + public fun (Lorg/partiql/ast/Type;)V + public synthetic fun (Lorg/partiql/ast/Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lorg/partiql/ast/Type$Array; + public final fun getType ()Lorg/partiql/ast/Type; + public final fun setType (Lorg/partiql/ast/Type;)V + public final fun type (Lorg/partiql/ast/Type;)Lorg/partiql/ast/builder/TypeArrayBuilder; +} + public final class org/partiql/ast/builder/TypeBagBuilder { public fun ()V public final fun build ()Lorg/partiql/ast/Type$Bag; @@ -6051,7 +6107,28 @@ public final class org/partiql/ast/builder/TypeStringBuilder { public final class org/partiql/ast/builder/TypeStructBuilder { public fun ()V + public fun (Ljava/util/List;)V + public synthetic fun (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun build ()Lorg/partiql/ast/Type$Struct; + public final fun fields (Ljava/util/List;)Lorg/partiql/ast/builder/TypeStructBuilder; + public final fun getFields ()Ljava/util/List; + public final fun setFields (Ljava/util/List;)V +} + +public final class org/partiql/ast/builder/TypeStructFieldBuilder { + public fun ()V + public fun (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;)V + public synthetic fun (Lorg/partiql/ast/Identifier$Symbol;Lorg/partiql/ast/Type;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lorg/partiql/ast/Type$Struct$Field; + public final fun constraints (Ljava/util/List;)Lorg/partiql/ast/builder/TypeStructFieldBuilder; + public final fun getConstraints ()Ljava/util/List; + public final fun getName ()Lorg/partiql/ast/Identifier$Symbol; + public final fun getType ()Lorg/partiql/ast/Type; + public final fun name (Lorg/partiql/ast/Identifier$Symbol;)Lorg/partiql/ast/builder/TypeStructFieldBuilder; + public final fun setConstraints (Ljava/util/List;)V + public final fun setName (Lorg/partiql/ast/Identifier$Symbol;)V + public final fun setType (Lorg/partiql/ast/Type;)V + public final fun type (Lorg/partiql/ast/Type;)Lorg/partiql/ast/builder/TypeStructFieldBuilder; } public final class org/partiql/ast/builder/TypeSymbolBuilder { @@ -6727,6 +6804,8 @@ public abstract class org/partiql/ast/util/AstRewriter : org/partiql/ast/visitor public fun visitTableDefinitionAttribute (Lorg/partiql/ast/TableDefinition$Attribute;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeAny (Lorg/partiql/ast/Type$Any;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeAny (Lorg/partiql/ast/Type$Any;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; + public synthetic fun visitTypeArray (Lorg/partiql/ast/Type$Array;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitTypeArray (Lorg/partiql/ast/Type$Array;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeBag (Lorg/partiql/ast/Type$Bag;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeBag (Lorg/partiql/ast/Type$Bag;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeBigint (Lorg/partiql/ast/Type$Bigint;Ljava/lang/Object;)Ljava/lang/Object; @@ -6783,6 +6862,8 @@ public abstract class org/partiql/ast/util/AstRewriter : org/partiql/ast/visitor public fun visitTypeString (Lorg/partiql/ast/Type$String;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeStruct (Lorg/partiql/ast/Type$Struct;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeStruct (Lorg/partiql/ast/Type$Struct;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; + public synthetic fun visitTypeStructField (Lorg/partiql/ast/Type$Struct$Field;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitTypeStructField (Lorg/partiql/ast/Type$Struct$Field;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeSymbol (Lorg/partiql/ast/Type$Symbol;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeSymbol (Lorg/partiql/ast/Type$Symbol;Ljava/lang/Object;)Lorg/partiql/ast/AstNode; public synthetic fun visitTypeTime (Lorg/partiql/ast/Type$Time;Ljava/lang/Object;)Ljava/lang/Object; @@ -6955,6 +7036,7 @@ public abstract class org/partiql/ast/visitor/AstBaseVisitor : org/partiql/ast/v public fun visitTableDefinitionAttribute (Lorg/partiql/ast/TableDefinition$Attribute;Ljava/lang/Object;)Ljava/lang/Object; public fun visitType (Lorg/partiql/ast/Type;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeAny (Lorg/partiql/ast/Type$Any;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitTypeArray (Lorg/partiql/ast/Type$Array;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeBag (Lorg/partiql/ast/Type$Bag;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeBigint (Lorg/partiql/ast/Type$Bigint;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeBit (Lorg/partiql/ast/Type$Bit;Ljava/lang/Object;)Ljava/lang/Object; @@ -6983,6 +7065,7 @@ public abstract class org/partiql/ast/visitor/AstBaseVisitor : org/partiql/ast/v public fun visitTypeSmallint (Lorg/partiql/ast/Type$Smallint;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeString (Lorg/partiql/ast/Type$String;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeStruct (Lorg/partiql/ast/Type$Struct;Ljava/lang/Object;)Ljava/lang/Object; + public fun visitTypeStructField (Lorg/partiql/ast/Type$Struct$Field;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeSymbol (Lorg/partiql/ast/Type$Symbol;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeTime (Lorg/partiql/ast/Type$Time;Ljava/lang/Object;)Ljava/lang/Object; public fun visitTypeTimeWithTz (Lorg/partiql/ast/Type$TimeWithTz;Ljava/lang/Object;)Ljava/lang/Object; @@ -7144,6 +7227,7 @@ public abstract interface class org/partiql/ast/visitor/AstVisitor { public abstract fun visitTableDefinitionAttribute (Lorg/partiql/ast/TableDefinition$Attribute;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitType (Lorg/partiql/ast/Type;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeAny (Lorg/partiql/ast/Type$Any;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun visitTypeArray (Lorg/partiql/ast/Type$Array;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeBag (Lorg/partiql/ast/Type$Bag;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeBigint (Lorg/partiql/ast/Type$Bigint;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeBit (Lorg/partiql/ast/Type$Bit;Ljava/lang/Object;)Ljava/lang/Object; @@ -7172,6 +7256,7 @@ public abstract interface class org/partiql/ast/visitor/AstVisitor { public abstract fun visitTypeSmallint (Lorg/partiql/ast/Type$Smallint;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeString (Lorg/partiql/ast/Type$String;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeStruct (Lorg/partiql/ast/Type$Struct;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun visitTypeStructField (Lorg/partiql/ast/Type$Struct$Field;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeSymbol (Lorg/partiql/ast/Type$Symbol;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeTime (Lorg/partiql/ast/Type$Time;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun visitTypeTimeWithTz (Lorg/partiql/ast/Type$TimeWithTz;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 0fb163cfe8..5f89431721 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 @@ -1346,11 +1346,22 @@ private class AstTranslator(val metas: Map) : AstBaseVisi override fun visitTypeList(node: Type.List, ctx: Ctx) = translate(node) { metas -> listType(metas) } + override fun visitTypeArray(node: Type.Array, ctx: Ctx) = translate(node) { metas -> + if (node.type != null) { + error("The legacy AST does not support element type declaration for list") + } + listType(metas) + } override fun visitTypeSexp(node: Type.Sexp, ctx: Ctx) = translate(node) { metas -> sexpType(metas) } override fun visitTypeTuple(node: Type.Tuple, ctx: Ctx) = translate(node) { metas -> tupleType(metas) } - override fun visitTypeStruct(node: Type.Struct, ctx: Ctx) = translate(node) { metas -> structType(metas) } + override fun visitTypeStruct(node: Type.Struct, ctx: Ctx) = translate(node) { metas -> + if (node.fields.isNotEmpty()) { + error("The legacy AST does not support field declaration in struct type") + } + structType(metas) + } override fun visitTypeAny(node: Type.Any, ctx: Ctx) = translate(node) { metas -> anyType(metas) } 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 4ecfb9d569..b01b56e680 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 @@ -201,10 +201,13 @@ internal abstract class InternalSqlDialect : AstBaseVisitor)] WITH TIMEZONE interval::{ precision: optional::int }, // INTERVAL bag::{}, // BAG + // Potential migration strategy: + // v0.14.x -- the current state in `main` + // typeList() + // + // v0.15.x -- the next release + // @Deprecated // recommend using `typeArray()` + // typeList() + // typeArray(...) + // + // v1.0.x + // typeArray(...) // `typeList` now deleted list::{}, // LIST + array::{ type: optional::type }, // ARRAY [] sexp::{}, // SEXP + // Potential migration strategy: + // v0.14.x -- the current state in `main` + // typeTuple() + // typeStruct() + // + // v0.15.x -- the next release + // @Deprecated // recommend using `typeStruct` + // typeTuple() + // typeStruct(fields = ...) + // + // v1.0.x + // typeStruct(fields = ...) // `typeTuple` now deleted tuple::{}, // TUPLE - struct::{}, // STRUCT + struct::{ + fields: list::[field], + _ : [ + field :: { + name: '.identifier.symbol', + type: '.type', + // This could be a boolean flag since we only support NOT NULL constraint + // for struct subfield. But modeling this to be a list of constraints + // to prevent future breaking changes. + constraints: list::[constraint], + } + ], + }, // STRUCT any::{}, // ANY custom::{ name: string }, // ] diff --git a/partiql-ast/src/test/kotlin/org/partiql/ast/helpers/ToLegacyAstTest.kt b/partiql-ast/src/test/kotlin/org/partiql/ast/helpers/ToLegacyAstTest.kt index 6f59c5069b..1fced537c7 100644 --- a/partiql-ast/src/test/kotlin/org/partiql/ast/helpers/ToLegacyAstTest.kt +++ b/partiql-ast/src/test/kotlin/org/partiql/ast/helpers/ToLegacyAstTest.kt @@ -407,15 +407,29 @@ class ToLegacyAstTest { expect("(struct_type)") { typeStruct() }, expect("(tuple_type)") { typeTuple() }, expect("(list_type)") { typeList() }, + expect("(list_type)") { typeArray(null) }, expect("(sexp_type)") { typeSexp() }, expect("(bag_type)") { typeBag() }, expect("(any_type)") { typeAny() }, // Other (??) expect("(integer4_type)") { typeInt4() }, expect("(integer8_type)") { typeInt8() }, - expect("(custom_type dog)") { typeCustom("dog") } + expect("(custom_type dog)") { typeCustom("dog") }, // LEGACY AST does not have TIMESTAMP or INTERVAL // LEGACY AST does not have parameterized blob/clob + // LEGACY AST does not support struct with field declaration + fail("The legacy AST does not support field declaration in struct type") { + typeStruct { + fields += org.partiql.ast.typeStructField( + org.partiql.ast.identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + typeInt2(), + emptyList() + ) + } + }, + fail("The legacy AST does not support element type declaration for list") { + typeArray(typeInt2()) + }, ) @JvmStatic diff --git a/partiql-lang/src/main/kotlin/org/partiql/lang/syntax/impl/PartiQLPigVisitor.kt b/partiql-lang/src/main/kotlin/org/partiql/lang/syntax/impl/PartiQLPigVisitor.kt index 8a799a8493..dea59f4483 100644 --- a/partiql-lang/src/main/kotlin/org/partiql/lang/syntax/impl/PartiQLPigVisitor.kt +++ b/partiql-lang/src/main/kotlin/org/partiql/lang/syntax/impl/PartiQLPigVisitor.kt @@ -1089,20 +1089,20 @@ internal class PartiQLPigVisitor( * SIMPLE EXPRESSIONS */ - override fun visitOr(ctx: PartiQLParser.OrContext) = visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.OR().symbol, null) + override fun visitOr(ctx: PartiQLParser.OrContext) = visitBinaryOperation(ctx.lhs, ctx.rhs, listOf(ctx.OR().symbol), null) - override fun visitAnd(ctx: PartiQLParser.AndContext) = visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op, null) + override fun visitAnd(ctx: PartiQLParser.AndContext) = visitBinaryOperation(ctx.lhs, ctx.rhs, listOf(ctx.op), null) override fun visitNot(ctx: PartiQLParser.NotContext) = visitUnaryOperation(ctx.rhs, ctx.op, null) override fun visitMathOp00(ctx: PartiQLParser.MathOp00Context): PartiqlAst.PartiqlAstNode = - visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op, ctx.parent) + visitBinaryOperation(ctx.lhs, ctx.rhs, listOf(ctx.op), ctx.parent) override fun visitMathOp01(ctx: PartiQLParser.MathOp01Context): PartiqlAst.PartiqlAstNode = - visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op, ctx.parent) + visitBinaryOperation(ctx.lhs, ctx.rhs, listOf(ctx.op), ctx.parent) override fun visitMathOp02(ctx: PartiQLParser.MathOp02Context): PartiqlAst.PartiqlAstNode = - visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op, ctx.parent) + visitBinaryOperation(ctx.lhs, ctx.rhs, listOf(ctx.op), ctx.parent) override fun visitValueExpr(ctx: PartiQLParser.ValueExprContext) = visitUnaryOperation(ctx.rhs, ctx.sign, ctx.parent) @@ -1114,7 +1114,7 @@ internal class PartiQLPigVisitor( */ override fun visitPredicateComparison(ctx: PartiQLParser.PredicateComparisonContext) = - visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op) + visitBinaryOperation(ctx.lhs, ctx.rhs, ctx.op.children.map { (it as TerminalNode).symbol }) /** * Note: This predicate can take a wrapped expression on the RHS, and it will wrap it in a LIST. However, if the @@ -1474,7 +1474,7 @@ internal class PartiQLPigVisitor( override fun visitBag(ctx: PartiQLParser.BagContext) = PartiqlAst.build { val exprList = ctx.expr().map { visitExpr(it) } - bag(exprList, ctx.ANGLE_DOUBLE_LEFT().getSourceMetaContainer()) + bag(exprList, ctx.ANGLE_LEFT(0).getSourceMetaContainer()) } override fun visitLiteralDecimal(ctx: PartiQLParser.LiteralDecimalContext) = PartiqlAst.build { @@ -1609,9 +1609,6 @@ internal class PartiQLPigVisitor( PartiQLParser.BLOB -> blobType(metas) PartiQLParser.CLOB -> clobType(metas) PartiQLParser.DATE -> dateType(metas) - PartiQLParser.STRUCT -> structType(metas) - PartiQLParser.TUPLE -> tupleType(metas) - PartiQLParser.LIST -> listType(metas) PartiQLParser.BAG -> bagType(metas) PartiQLParser.SEXP -> sexpType(metas) PartiQLParser.ANY -> anyType(metas) @@ -1677,6 +1674,32 @@ internal class PartiQLPigVisitor( customType_(SymbolPrimitive(customName, metas), metas) } + override fun visitTypeComplexUnparameterized(ctx: PartiQLParser.TypeComplexUnparameterizedContext) = PartiqlAst.build { + val metas = ctx.datatype.getSourceMetaContainer() + when (ctx.datatype.type) { + PartiQLParser.TUPLE -> tupleType(metas) + PartiQLParser.STRUCT -> structType(metas) + PartiQLParser.ARRAY, PartiQLParser.LIST -> listType(metas) + else -> throw ParserException("Unknown datatype", ErrorCode.PARSE_UNEXPECTED_TOKEN, PropertyValueMap()) + } + } + + override fun visitTypeStruct(ctx: PartiQLParser.TypeStructContext) = PartiqlAst.build { + throw ParserException( + "PIG Parser does not support struct type with field declaration", + ErrorCode.PARSE_UNEXPECTED_TOKEN, + PropertyValueMap() + ) + } + + override fun visitTypeList(ctx: PartiQLParser.TypeListContext): PartiqlAst.PartiqlAstNode { + throw ParserException( + "PIG Parser does not support element type declaration for list", + ErrorCode.PARSE_UNEXPECTED_TOKEN, + PropertyValueMap() + ) + } + /** * * HELPER METHODS @@ -1695,6 +1718,14 @@ internal class PartiQLPigVisitor( return com.amazon.ionelement.api.metaContainerOf(Pair(metas.tag, metas)) } + private fun List.getSourceMetaContainer(): MetaContainer { + val base = this.firstOrNull() ?: return emptyMetaContainer() + val length = this.fold(0) { acc, token -> + acc + token.stopIndex - token.startIndex + 1 + } + return metaContainerOf(SourceLocationMeta(base.line.toLong(), base.charPositionInLine.toLong() + 1, length.toLong())) + } + private fun TerminalNode.getSourceMetas(): SourceLocationMeta = this.symbol.getSourceMetas() private fun Token.getSourceMetas(): SourceLocationMeta { @@ -1705,13 +1736,13 @@ internal class PartiQLPigVisitor( private fun visitBinaryOperation( lhs: ParserRuleContext?, rhs: ParserRuleContext?, - op: Token?, + op: List, parent: ParserRuleContext? = null, ) = PartiqlAst.build { if (parent != null) return@build visit(parent) as PartiqlAst.Expr val args = listOf(lhs!!, rhs!!).map { visit(it) as PartiqlAst.Expr } val metas = op.getSourceMetaContainer() - when (op!!.type) { + when (op.first().type) { PartiQLParser.AND -> and(args, metas) PartiQLParser.OR -> or(args, metas) PartiQLParser.ASTERISK -> times(args, metas) @@ -1720,11 +1751,14 @@ internal class PartiQLPigVisitor( PartiQLParser.MINUS -> minus(args, metas) PartiQLParser.PERCENT -> modulo(args, metas) PartiQLParser.CONCAT -> concat(args, metas) - PartiQLParser.ANGLE_LEFT -> lt(args, metas) + PartiQLParser.ANGLE_LEFT -> { + if (op.size > 1) ne(args, metas) + else lt(args, metas) + } PartiQLParser.LT_EQ -> lte(args, metas) PartiQLParser.ANGLE_RIGHT -> gt(args, metas) PartiQLParser.GT_EQ -> gte(args, metas) - PartiQLParser.NEQ -> ne(args, metas) + PartiQLParser.BANG -> ne(args, metas) PartiQLParser.EQ -> eq(args, metas) PartiQLParser.AMPERSAND -> bitwiseAnd(args, metas) else -> throw ParserException("Unknown binary operator", ErrorCode.PARSE_INVALID_QUERY) diff --git a/partiql-lang/src/test/kotlin/org/partiql/lang/syntax/PartiQLParserDDLTest.kt b/partiql-lang/src/test/kotlin/org/partiql/lang/syntax/PartiQLParserDDLTest.kt index 4c61031c70..743348b69c 100644 --- a/partiql-lang/src/test/kotlin/org/partiql/lang/syntax/PartiQLParserDDLTest.kt +++ b/partiql-lang/src/test/kotlin/org/partiql/lang/syntax/PartiQLParserDDLTest.kt @@ -76,6 +76,60 @@ internal class PartiQLParserDDLTest : PartiQLParserTestBase() { code = ErrorCode.PARSE_UNEXPECTED_TOKEN, context = mapOf(), ), + ParserErrorTestCase( + description = "PIG Parser does not support Struct Type with field declaration", + query = """ + CREATE TABLE tbl ( + a STRUCT + ) + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), + ParserErrorTestCase( + description = "PIG Parser does not support element type declaration in Array Type", + query = """ + CREATE TABLE tbl ( + a ARRAY + ) + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), + + // Putting those tests here are they are impacted by DDL implementation + ParserErrorTestCase( + description = "PIG Parser does not support Struct Type with field declaration -- IS operator", + query = """ + a IS STRUCT + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), + ParserErrorTestCase( + description = "PIG Parser does not support Struct Type with field declaration -- CAST operator", + query = """ + CAST(a AS STRUCT) + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), + ParserErrorTestCase( + description = "PIG Parser does not support element type declaration in Array Type -- IS operator", + query = """ + a IS ARRAY + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), + ParserErrorTestCase( + description = "PIG Parser does not support element type declaration in Array Type -- cast operator", + query = """ + CAST(a AS ARRAY) + """.trimIndent(), + code = ErrorCode.PARSE_UNEXPECTED_TOKEN, + context = mapOf(), + ), ) } } diff --git a/partiql-parser/api/partiql-parser.api b/partiql-parser/api/partiql-parser.api index 4a5bebeba9..d0a0f1be1c 100644 --- a/partiql-parser/api/partiql-parser.api +++ b/partiql-parser/api/partiql-parser.api @@ -141,6 +141,7 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun enterColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)V public fun enterColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)V public fun enterColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)V + public fun enterComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)V public fun enterConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)V public fun enterConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)V public fun enterConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)V @@ -305,6 +306,7 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun enterSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)V public fun enterSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)V public fun enterSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)V + public fun enterStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)V public fun enterSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)V public fun enterSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)V public fun enterTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)V @@ -326,7 +328,10 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun enterTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)V public fun enterTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)V public fun enterTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)V + public fun enterTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)V public fun enterTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)V + public fun enterTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)V + public fun enterTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)V public fun enterTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)V public fun enterTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)V public fun enterUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)V @@ -365,6 +370,7 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun exitColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)V public fun exitColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)V public fun exitColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)V + public fun exitComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)V public fun exitConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)V public fun exitConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)V public fun exitConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)V @@ -529,6 +535,7 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun exitSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)V public fun exitSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)V public fun exitSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)V + public fun exitStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)V public fun exitSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)V public fun exitSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)V public fun exitTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)V @@ -550,7 +557,10 @@ public class org/partiql/parser/antlr/PartiQLBaseListener : org/partiql/parser/a public fun exitTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)V public fun exitTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)V public fun exitTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)V + public fun exitTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)V public fun exitTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)V + public fun exitTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)V + public fun exitTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)V public fun exitTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)V public fun exitTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)V public fun exitUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)V @@ -595,6 +605,7 @@ public class org/partiql/parser/antlr/PartiQLBaseVisitor : org/antlr/v4/runtime/ public fun visitColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)Ljava/lang/Object; public fun visitColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)Ljava/lang/Object; public fun visitColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)Ljava/lang/Object; + public fun visitComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)Ljava/lang/Object; public fun visitConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)Ljava/lang/Object; public fun visitConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)Ljava/lang/Object; public fun visitConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)Ljava/lang/Object; @@ -758,6 +769,7 @@ public class org/partiql/parser/antlr/PartiQLBaseVisitor : org/antlr/v4/runtime/ public fun visitSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)Ljava/lang/Object; public fun visitSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)Ljava/lang/Object; public fun visitSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)Ljava/lang/Object; + public fun visitStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)Ljava/lang/Object; public fun visitSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)Ljava/lang/Object; public fun visitSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)Ljava/lang/Object; public fun visitTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)Ljava/lang/Object; @@ -779,7 +791,10 @@ public class org/partiql/parser/antlr/PartiQLBaseVisitor : org/antlr/v4/runtime/ public fun visitTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)Ljava/lang/Object; public fun visitTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)Ljava/lang/Object; public fun visitTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)Ljava/lang/Object; + public fun visitTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)Ljava/lang/Object; public fun visitTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)Ljava/lang/Object; + public fun visitTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)Ljava/lang/Object; + public fun visitTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)Ljava/lang/Object; public fun visitTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)Ljava/lang/Object; public fun visitTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)Ljava/lang/Object; public fun visitUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)Ljava/lang/Object; @@ -821,6 +836,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun enterColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)V public abstract fun enterColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)V public abstract fun enterColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)V + public abstract fun enterComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)V public abstract fun enterConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)V public abstract fun enterConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)V public abstract fun enterConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)V @@ -984,6 +1000,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun enterSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)V public abstract fun enterSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)V public abstract fun enterSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)V + public abstract fun enterStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)V public abstract fun enterSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)V public abstract fun enterSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)V public abstract fun enterTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)V @@ -1005,7 +1022,10 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun enterTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)V public abstract fun enterTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)V public abstract fun enterTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)V + public abstract fun enterTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)V public abstract fun enterTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)V + public abstract fun enterTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)V + public abstract fun enterTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)V public abstract fun enterTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)V public abstract fun enterTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)V public abstract fun enterUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)V @@ -1044,6 +1064,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun exitColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)V public abstract fun exitColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)V public abstract fun exitColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)V + public abstract fun exitComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)V public abstract fun exitConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)V public abstract fun exitConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)V public abstract fun exitConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)V @@ -1207,6 +1228,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun exitSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)V public abstract fun exitSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)V public abstract fun exitSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)V + public abstract fun exitStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)V public abstract fun exitSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)V public abstract fun exitSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)V public abstract fun exitTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)V @@ -1228,7 +1250,10 @@ public abstract interface class org/partiql/parser/antlr/PartiQLListener : org/a public abstract fun exitTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)V public abstract fun exitTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)V public abstract fun exitTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)V + public abstract fun exitTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)V public abstract fun exitTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)V + public abstract fun exitTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)V + public abstract fun exitTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)V public abstract fun exitTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)V public abstract fun exitTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)V public abstract fun exitUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)V @@ -1257,12 +1282,11 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public static final field ALTER I public static final field AMPERSAND I public static final field AND I - public static final field ANGLE_DOUBLE_LEFT I - public static final field ANGLE_DOUBLE_RIGHT I public static final field ANGLE_LEFT I public static final field ANGLE_RIGHT I public static final field ANY I public static final field ARE I + public static final field ARRAY I public static final field AS I public static final field ASC I public static final field ASSERTION I @@ -1441,7 +1465,6 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public static final field NATIONAL I public static final field NATURAL I public static final field NCHAR I - public static final field NEQ I public static final field NEW I public static final field NEXT I public static final field NO I @@ -1514,6 +1537,7 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public static final field RULE_columnConstraint I public static final field RULE_columnConstraintDef I public static final field RULE_columnName I + public static final field RULE_comparisonOp I public static final field RULE_conflictAction I public static final field RULE_conflictTarget I public static final field RULE_constraintName I @@ -1613,6 +1637,7 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public static final field RULE_setCommand I public static final field RULE_setQuantifierStrategy I public static final field RULE_statement I + public static final field RULE_structField I public static final field RULE_substring I public static final field RULE_symbolPrimitive I public static final field RULE_tableBaseReference I @@ -1726,6 +1751,7 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public final fun columnConstraint ()Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext; public final fun columnConstraintDef ()Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintDefContext; public final fun columnName ()Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext; + public final fun comparisonOp ()Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext; public final fun conflictAction ()Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext; public final fun conflictTarget ()Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext; public final fun constraintName ()Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext; @@ -1832,6 +1858,7 @@ public class org/partiql/parser/antlr/PartiQLParser : org/antlr/v4/runtime/Parse public final fun setCommand ()Lorg/partiql/parser/antlr/PartiQLParser$SetCommandContext; public final fun setQuantifierStrategy ()Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext; public final fun statement ()Lorg/partiql/parser/antlr/PartiQLParser$StatementContext; + public final fun structField ()Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext; public final fun substring ()Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext; public final fun symbolPrimitive ()Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext; public final fun tableBaseReference ()Lorg/partiql/parser/antlr/PartiQLParser$TableBaseReferenceContext; @@ -1937,8 +1964,10 @@ public class org/partiql/parser/antlr/PartiQLParser$AtIdentContext : org/antlr/v public class org/partiql/parser/antlr/PartiQLParser$BagContext : org/antlr/v4/runtime/ParserRuleContext { public fun (Lorg/antlr/v4/runtime/ParserRuleContext;I)V - public fun ANGLE_DOUBLE_LEFT ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun ANGLE_DOUBLE_RIGHT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ANGLE_LEFT ()Ljava/util/List; + public fun ANGLE_LEFT (I)Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ANGLE_RIGHT ()Ljava/util/List; + public fun ANGLE_RIGHT (I)Lorg/antlr/v4/runtime/tree/TerminalNode; public fun COMMA ()Ljava/util/List; public fun COMMA (I)Lorg/antlr/v4/runtime/tree/TerminalNode; public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; @@ -2131,6 +2160,20 @@ public class org/partiql/parser/antlr/PartiQLParser$ColumnNameContext : org/antl public fun symbolPrimitive ()Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext; } +public class org/partiql/parser/antlr/PartiQLParser$ComparisonOpContext : org/antlr/v4/runtime/ParserRuleContext { + public fun (Lorg/antlr/v4/runtime/ParserRuleContext;I)V + public fun ANGLE_LEFT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ANGLE_RIGHT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun BANG ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun GT_EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun LT_EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun getRuleIndex ()I +} + public class org/partiql/parser/antlr/PartiQLParser$ConflictActionContext : org/antlr/v4/runtime/ParserRuleContext { public fun (Lorg/antlr/v4/runtime/ParserRuleContext;I)V public fun DO ()Lorg/antlr/v4/runtime/tree/TerminalNode; @@ -3870,16 +3913,11 @@ public class org/partiql/parser/antlr/PartiQLParser$PredicateBetweenContext : or public class org/partiql/parser/antlr/PartiQLParser$PredicateComparisonContext : org/partiql/parser/antlr/PartiQLParser$ExprPredicateContext { public field lhs Lorg/partiql/parser/antlr/PartiQLParser$ExprPredicateContext; - public field op Lorg/antlr/v4/runtime/Token; + public field op Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext; public field rhs Lorg/partiql/parser/antlr/PartiQLParser$MathOp00Context; public fun (Lorg/partiql/parser/antlr/PartiQLParser$ExprPredicateContext;)V - public fun ANGLE_LEFT ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun ANGLE_RIGHT ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun GT_EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun LT_EQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun NEQ ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun comparisonOp ()Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext; public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V public fun exprPredicate ()Lorg/partiql/parser/antlr/PartiQLParser$ExprPredicateContext; @@ -4280,6 +4318,19 @@ public class org/partiql/parser/antlr/PartiQLParser$StatementContext : org/antlr public fun getRuleIndex ()I } +public class org/partiql/parser/antlr/PartiQLParser$StructFieldContext : org/antlr/v4/runtime/ParserRuleContext { + public fun (Lorg/antlr/v4/runtime/ParserRuleContext;I)V + public fun COLON ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun columnConstraint ()Ljava/util/List; + public fun columnConstraint (I)Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext; + public fun columnName ()Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext; + public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun getRuleIndex ()I + public fun type ()Lorg/partiql/parser/antlr/PartiQLParser$TypeContext; +} + public class org/partiql/parser/antlr/PartiQLParser$SubstringContext : org/antlr/v4/runtime/ParserRuleContext { public fun (Lorg/antlr/v4/runtime/ParserRuleContext;I)V public fun COMMA ()Ljava/util/List; @@ -4576,7 +4627,6 @@ public class org/partiql/parser/antlr/PartiQLParser$TypeAtomicContext : org/part public fun INTEGER2 ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun INTEGER4 ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun INTEGER8 ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun LIST ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun MISSING ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun NULL ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun PRECISION ()Lorg/antlr/v4/runtime/tree/TerminalNode; @@ -4584,8 +4634,18 @@ public class org/partiql/parser/antlr/PartiQLParser$TypeAtomicContext : org/part public fun SEXP ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun SMALLINT ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun STRING ()Lorg/antlr/v4/runtime/tree/TerminalNode; - public fun STRUCT ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun SYMBOL ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V +} + +public class org/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext : org/partiql/parser/antlr/PartiQLParser$TypeContext { + public field datatype Lorg/antlr/v4/runtime/Token; + public fun (Lorg/partiql/parser/antlr/PartiQLParser$TypeContext;)V + public fun ARRAY ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun LIST ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun STRUCT ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun TUPLE ()Lorg/antlr/v4/runtime/tree/TerminalNode; public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V @@ -4607,6 +4667,35 @@ public class org/partiql/parser/antlr/PartiQLParser$TypeCustomContext : org/part public fun symbolPrimitive ()Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext; } +public class org/partiql/parser/antlr/PartiQLParser$TypeListContext : org/partiql/parser/antlr/PartiQLParser$TypeContext { + public field datatype Lorg/antlr/v4/runtime/Token; + public fun (Lorg/partiql/parser/antlr/PartiQLParser$TypeContext;)V + public fun ANGLE_LEFT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ANGLE_RIGHT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ARRAY ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun LIST ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun type ()Lorg/partiql/parser/antlr/PartiQLParser$TypeContext; +} + +public class org/partiql/parser/antlr/PartiQLParser$TypeStructContext : org/partiql/parser/antlr/PartiQLParser$TypeContext { + public field datatype Lorg/antlr/v4/runtime/Token; + public fun (Lorg/partiql/parser/antlr/PartiQLParser$TypeContext;)V + public fun ANGLE_LEFT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun ANGLE_RIGHT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun COMMA ()Ljava/util/List; + public fun COMMA (I)Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun STRUCT ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun TUPLE ()Lorg/antlr/v4/runtime/tree/TerminalNode; + public fun accept (Lorg/antlr/v4/runtime/tree/ParseTreeVisitor;)Ljava/lang/Object; + public fun enterRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V + public fun structField ()Ljava/util/List; + public fun structField (I)Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext; +} + public class org/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext : org/partiql/parser/antlr/PartiQLParser$TypeContext { public field datatype Lorg/antlr/v4/runtime/Token; public field precision Lorg/antlr/v4/runtime/Token; @@ -4858,12 +4947,11 @@ public class org/partiql/parser/antlr/PartiQLTokens : org/antlr/v4/runtime/Lexer public static final field ALTER I public static final field AMPERSAND I public static final field AND I - public static final field ANGLE_DOUBLE_LEFT I - public static final field ANGLE_DOUBLE_RIGHT I public static final field ANGLE_LEFT I public static final field ANGLE_RIGHT I public static final field ANY I public static final field ARE I + public static final field ARRAY I public static final field AS I public static final field ASC I public static final field ASSERTION I @@ -5043,7 +5131,6 @@ public class org/partiql/parser/antlr/PartiQLTokens : org/antlr/v4/runtime/Lexer public static final field NATIONAL I public static final field NATURAL I public static final field NCHAR I - public static final field NEQ I public static final field NEW I public static final field NEXT I public static final field NO I @@ -5204,6 +5291,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLVisitor : org/an public abstract fun visitColumnConstraint (Lorg/partiql/parser/antlr/PartiQLParser$ColumnConstraintContext;)Ljava/lang/Object; public abstract fun visitColumnDeclaration (Lorg/partiql/parser/antlr/PartiQLParser$ColumnDeclarationContext;)Ljava/lang/Object; public abstract fun visitColumnName (Lorg/partiql/parser/antlr/PartiQLParser$ColumnNameContext;)Ljava/lang/Object; + public abstract fun visitComparisonOp (Lorg/partiql/parser/antlr/PartiQLParser$ComparisonOpContext;)Ljava/lang/Object; public abstract fun visitConflictAction (Lorg/partiql/parser/antlr/PartiQLParser$ConflictActionContext;)Ljava/lang/Object; public abstract fun visitConflictTarget (Lorg/partiql/parser/antlr/PartiQLParser$ConflictTargetContext;)Ljava/lang/Object; public abstract fun visitConstraintName (Lorg/partiql/parser/antlr/PartiQLParser$ConstraintNameContext;)Ljava/lang/Object; @@ -5367,6 +5455,7 @@ public abstract interface class org/partiql/parser/antlr/PartiQLVisitor : org/an public abstract fun visitSetQuantifierStrategy (Lorg/partiql/parser/antlr/PartiQLParser$SetQuantifierStrategyContext;)Ljava/lang/Object; public abstract fun visitSfwBase (Lorg/partiql/parser/antlr/PartiQLParser$SfwBaseContext;)Ljava/lang/Object; public abstract fun visitSfwQuery (Lorg/partiql/parser/antlr/PartiQLParser$SfwQueryContext;)Ljava/lang/Object; + public abstract fun visitStructField (Lorg/partiql/parser/antlr/PartiQLParser$StructFieldContext;)Ljava/lang/Object; public abstract fun visitSubstring (Lorg/partiql/parser/antlr/PartiQLParser$SubstringContext;)Ljava/lang/Object; public abstract fun visitSymbolPrimitive (Lorg/partiql/parser/antlr/PartiQLParser$SymbolPrimitiveContext;)Ljava/lang/Object; public abstract fun visitTableBaseRefClauses (Lorg/partiql/parser/antlr/PartiQLParser$TableBaseRefClausesContext;)Ljava/lang/Object; @@ -5388,7 +5477,10 @@ public abstract interface class org/partiql/parser/antlr/PartiQLVisitor : org/an public abstract fun visitTypeArgDouble (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgDoubleContext;)Ljava/lang/Object; public abstract fun visitTypeArgSingle (Lorg/partiql/parser/antlr/PartiQLParser$TypeArgSingleContext;)Ljava/lang/Object; public abstract fun visitTypeAtomic (Lorg/partiql/parser/antlr/PartiQLParser$TypeAtomicContext;)Ljava/lang/Object; + public abstract fun visitTypeComplexUnparameterized (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexUnparameterizedContext;)Ljava/lang/Object; public abstract fun visitTypeCustom (Lorg/partiql/parser/antlr/PartiQLParser$TypeCustomContext;)Ljava/lang/Object; + public abstract fun visitTypeList (Lorg/partiql/parser/antlr/PartiQLParser$TypeListContext;)Ljava/lang/Object; + public abstract fun visitTypeStruct (Lorg/partiql/parser/antlr/PartiQLParser$TypeStructContext;)Ljava/lang/Object; public abstract fun visitTypeTimeZone (Lorg/partiql/parser/antlr/PartiQLParser$TypeTimeZoneContext;)Ljava/lang/Object; public abstract fun visitTypeVarChar (Lorg/partiql/parser/antlr/PartiQLParser$TypeVarCharContext;)Ljava/lang/Object; public abstract fun visitUnion (Lorg/partiql/parser/antlr/PartiQLParser$UnionContext;)Ljava/lang/Object; diff --git a/partiql-parser/src/main/antlr/PartiQL.g4 b/partiql-parser/src/main/antlr/PartiQL.g4 index 1d37acfcdb..90d693aa74 100644 --- a/partiql-parser/src/main/antlr/PartiQL.g4 +++ b/partiql-parser/src/main/antlr/PartiQL.g4 @@ -583,7 +583,7 @@ exprNot ; exprPredicate - : lhs=exprPredicate op=(LT_EQ|GT_EQ|ANGLE_LEFT|ANGLE_RIGHT|NEQ|EQ) rhs=mathOp00 # PredicateComparison + : lhs=exprPredicate op=comparisonOp rhs=mathOp00 # PredicateComparison | lhs=exprPredicate IS NOT? type # PredicateIs | lhs=exprPredicate NOT? IN PAREN_LEFT expr PAREN_RIGHT # PredicateIn | lhs=exprPredicate NOT? IN rhs=mathOp00 # PredicateIn @@ -592,6 +592,16 @@ exprPredicate | parent=mathOp00 # PredicateBase ; +comparisonOp + : LT_EQ + | GT_EQ + | ANGLE_LEFT + | ANGLE_RIGHT + | EQ + | ANGLE_LEFT ANGLE_RIGHT + | BANG EQ + ; + // TODO : Opreator precedence of BITWISE_AND (&) may change in the future. // SEE: https://github.com/partiql/partiql-docs/issues/50 mathOp00 @@ -786,7 +796,7 @@ array : BRACKET_LEFT ( expr ( COMMA expr )* )? BRACKET_RIGHT; bag - : ANGLE_DOUBLE_LEFT ( expr ( COMMA expr )* )? ANGLE_DOUBLE_RIGHT; + : ANGLE_LEFT ANGLE_LEFT ( expr ( COMMA expr )* )? ANGLE_RIGHT ANGLE_RIGHT; tuple : BRACE_LEFT ( pair ( COMMA pair )* )? BRACE_RIGHT; @@ -812,12 +822,19 @@ type : datatype=( NULL | BOOL | BOOLEAN | SMALLINT | INTEGER2 | INT2 | INTEGER | INT | INTEGER4 | INT4 | INTEGER8 | INT8 | BIGINT | REAL | CHAR | CHARACTER | MISSING - | STRING | SYMBOL | BLOB | CLOB | DATE | STRUCT | TUPLE | LIST | SEXP | BAG | ANY + | STRING | SYMBOL | BLOB | CLOB | DATE | SEXP | BAG | ANY ) # TypeAtomic + | datatype=(STRUCT|TUPLE|LIST|ARRAY) # TypeComplexUnparameterized | datatype=DOUBLE PRECISION # TypeAtomic | datatype=(CHARACTER|CHAR|FLOAT|VARCHAR) ( PAREN_LEFT arg0=LITERAL_INTEGER PAREN_RIGHT )? # TypeArgSingle | CHARACTER VARYING ( PAREN_LEFT arg0=LITERAL_INTEGER PAREN_RIGHT )? # TypeVarChar | datatype=(DECIMAL|DEC|NUMERIC) ( PAREN_LEFT arg0=LITERAL_INTEGER ( COMMA arg1=LITERAL_INTEGER )? PAREN_RIGHT )? # TypeArgDouble | datatype=(TIME|TIMESTAMP) ( PAREN_LEFT precision=LITERAL_INTEGER PAREN_RIGHT )? (WITH TIME ZONE)? # TypeTimeZone + | datatype=(STRUCT|TUPLE) (ANGLE_LEFT structField ( COMMA structField )* ANGLE_RIGHT) # TypeStruct + | datatype=(LIST|ARRAY) ANGLE_LEFT type ANGLE_RIGHT # TypeList | symbolPrimitive # TypeCustom ; + +structField + : columnName COLON type columnConstraint* + ; diff --git a/partiql-parser/src/main/antlr/PartiQLTokens.g4 b/partiql-parser/src/main/antlr/PartiQLTokens.g4 index e80269aff5..5ab8b50059 100644 --- a/partiql-parser/src/main/antlr/PartiQLTokens.g4 +++ b/partiql-parser/src/main/antlr/PartiQLTokens.g4 @@ -293,7 +293,7 @@ NOTHING: 'NOTHING'; * DATA TYPES * */ - +ARRAY: 'ARRAY'; TUPLE: 'TUPLE'; INTEGER2: 'INTEGER2'; INT2: 'INT2'; @@ -334,12 +334,9 @@ BANG: '!'; LT_EQ: '<='; GT_EQ: '>='; EQ: '='; -NEQ: '<>' | '!='; CONCAT: '||'; ANGLE_LEFT: '<'; ANGLE_RIGHT: '>'; -ANGLE_DOUBLE_LEFT: '<<'; -ANGLE_DOUBLE_RIGHT: '>>'; BRACKET_LEFT: '['; BRACKET_RIGHT: ']'; BRACE_LEFT: '{'; 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 82e3d395e9..412a78bfaa 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 @@ -177,6 +177,7 @@ import org.partiql.ast.statementQuery import org.partiql.ast.tableDefinition import org.partiql.ast.tableDefinitionAttribute import org.partiql.ast.typeAny +import org.partiql.ast.typeArray import org.partiql.ast.typeBag import org.partiql.ast.typeBlob import org.partiql.ast.typeBool @@ -191,7 +192,6 @@ import org.partiql.ast.typeInt import org.partiql.ast.typeInt2 import org.partiql.ast.typeInt4 import org.partiql.ast.typeInt8 -import org.partiql.ast.typeList import org.partiql.ast.typeMissing import org.partiql.ast.typeNullType import org.partiql.ast.typeNumeric @@ -199,12 +199,12 @@ import org.partiql.ast.typeReal import org.partiql.ast.typeSexp import org.partiql.ast.typeString import org.partiql.ast.typeStruct +import org.partiql.ast.typeStructField import org.partiql.ast.typeSymbol import org.partiql.ast.typeTime import org.partiql.ast.typeTimeWithTz import org.partiql.ast.typeTimestamp import org.partiql.ast.typeTimestampWithTz -import org.partiql.ast.typeTuple import org.partiql.ast.typeVarchar import org.partiql.parser.PartiQLLexerException import org.partiql.parser.PartiQLParser @@ -636,15 +636,43 @@ internal class PartiQLParserDefault : PartiQLParser { override fun visitColumnDeclaration(ctx: GeneratedParser.ColumnDeclarationContext) = translate(ctx) { val name = visitAs (ctx.columnName().symbolPrimitive()) - val type = visit(ctx.type()) as Type - val constraints = ctx.columnConstraint().map { constrCtx -> - val identifier = constrCtx.constraintName()?.let { symbolToString(it.symbolPrimitive()) } - val body = visit(constrCtx.columnConstraintDef()) as Constraint.Definition - constraint(identifier, body) + val type = (visit(ctx.type()) as Type).also { + isValidTypeDeclarationOrThrow(it, ctx.type()) } + val constraints = ctx.columnConstraint().map { visitColumnConstraint(it) } tableDefinitionAttribute(name, type, constraints) } + /** + * For Type Declaration used in DDL: + * We DO NOT support ANY Type, BAG Type, MISSING Type, Or NULL Type + */ + private fun isValidTypeDeclarationOrThrow(type: Type, ctx: GeneratedParser.TypeContext) = when (type) { + is Type.Any, + is Type.Bag, + is Type.Missing, + is Type.NullType -> throw error(ctx, "declaration attribute with $type is not supported") + else -> Unit + } + + private fun isValidTypeParameterOrThrow(type: Type, ctx: GeneratedParser.TypeContext) = when (type) { + is Type.Struct -> { + if (type.fields.isNotEmpty()) throw error(ctx, "using parameterized struct as type parameter is not supported") + else Unit + } + is Type.Array -> { + if (type.type != null) throw error(ctx, "using parameterized array as type parameter is not supported") + else Unit + } + else -> Unit + } + + override fun visitColumnConstraint(ctx: GeneratedParser.ColumnConstraintContext) = translate(ctx) { + val identifier = ctx.constraintName()?.let { symbolToString(it.symbolPrimitive()) } + val body = visit(ctx.columnConstraintDef()) as Constraint.Definition + constraint(identifier, body) + } + override fun visitColConstrNotNull(ctx: GeneratedParser.ColConstrNotNullContext) = translate(ctx) { constraintDefinitionNotNull() } @@ -1511,17 +1539,17 @@ internal class PartiQLParserDefault : PartiQLParser { override fun visitMathOp00(ctx: GeneratedParser.MathOp00Context) = translate(ctx) { if (ctx.parent != null) return@translate visit(ctx.parent) - convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryOp(ctx.op)) + convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryMathOp(ctx.op)) } override fun visitMathOp01(ctx: GeneratedParser.MathOp01Context) = translate(ctx) { if (ctx.parent != null) return@translate visit(ctx.parent) - convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryOp(ctx.op)) + convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryMathOp(ctx.op)) } override fun visitMathOp02(ctx: GeneratedParser.MathOp02Context) = translate(ctx) { if (ctx.parent != null) return@translate visit(ctx.parent) - convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryOp(ctx.op)) + convertBinaryExpr(ctx.lhs, ctx.rhs, convertBinaryMathOp(ctx.op)) } override fun visitValueExpr(ctx: GeneratedParser.ValueExprContext) = translate(ctx) { @@ -1536,7 +1564,7 @@ internal class PartiQLParserDefault : PartiQLParser { return exprBinary(op, l, r) } - private fun convertBinaryOp(token: Token) = when (token.type) { + private fun convertBinaryOp(ctx: GeneratedParser.ComparisonOpContext) = when (ctx.start.type) { GeneratedParser.AMPERSAND -> Expr.Binary.Op.BITWISE_AND GeneratedParser.AND -> Expr.Binary.Op.AND GeneratedParser.OR -> Expr.Binary.Op.OR @@ -1546,12 +1574,26 @@ internal class PartiQLParserDefault : PartiQLParser { GeneratedParser.MINUS -> Expr.Binary.Op.MINUS GeneratedParser.PERCENT -> Expr.Binary.Op.MODULO GeneratedParser.CONCAT -> Expr.Binary.Op.CONCAT - GeneratedParser.ANGLE_LEFT -> Expr.Binary.Op.LT + GeneratedParser.ANGLE_LEFT -> { + if (ctx.stop.type == GeneratedParser.ANGLE_RIGHT) Expr.Binary.Op.NE + else Expr.Binary.Op.LT + } GeneratedParser.LT_EQ -> Expr.Binary.Op.LTE GeneratedParser.ANGLE_RIGHT -> Expr.Binary.Op.GT GeneratedParser.GT_EQ -> Expr.Binary.Op.GTE - GeneratedParser.NEQ -> Expr.Binary.Op.NE + GeneratedParser.BANG -> Expr.Binary.Op.NE GeneratedParser.EQ -> Expr.Binary.Op.EQ + else -> throw error(ctx.start, "Invalid binary operator") + } + + private fun convertBinaryMathOp(token: Token) = when (token.type) { + GeneratedParser.AMPERSAND -> Expr.Binary.Op.BITWISE_AND + GeneratedParser.CONCAT -> Expr.Binary.Op.CONCAT + GeneratedParser.PLUS -> Expr.Binary.Op.PLUS + GeneratedParser.MINUS -> Expr.Binary.Op.MINUS + GeneratedParser.PERCENT -> Expr.Binary.Op.MODULO + GeneratedParser.ASTERISK -> Expr.Binary.Op.TIMES + GeneratedParser.SLASH_FORWARD -> Expr.Binary.Op.DIVIDE else -> throw error(token, "Invalid binary operator") } @@ -1595,7 +1637,7 @@ internal class PartiQLParserDefault : PartiQLParser { override fun visitPredicateIs(ctx: GeneratedParser.PredicateIsContext) = translate(ctx) { val value = visitAs(ctx.lhs) - val type = visitAs(ctx.type()) + val type = visitAs(ctx.type()).also { isValidTypeParameterOrThrow(it, ctx.type()) } val not = ctx.NOT() != null exprIsType(value, type, not) } @@ -1756,19 +1798,19 @@ internal class PartiQLParserDefault : PartiQLParser { override fun visitCast(ctx: GeneratedParser.CastContext) = translate(ctx) { val expr = visitExpr(ctx.expr()) - val type = visitAs(ctx.type()) + val type = visitAs(ctx.type()).also { isValidTypeParameterOrThrow(it, ctx.type()) } exprCast(expr, type) } override fun visitCanCast(ctx: GeneratedParser.CanCastContext) = translate(ctx) { val expr = visitExpr(ctx.expr()) - val type = visitAs(ctx.type()) + val type = visitAs(ctx.type()).also { isValidTypeParameterOrThrow(it, ctx.type()) } exprCanCast(expr, type) } override fun visitCanLosslessCast(ctx: GeneratedParser.CanLosslessCastContext) = translate(ctx) { val expr = visitExpr(ctx.expr()) - val type = visitAs(ctx.type()) + val type = visitAs(ctx.type()).also { isValidTypeParameterOrThrow(it, ctx.type()) } exprCanLosslessCast(expr, type) } @@ -2125,9 +2167,6 @@ internal class PartiQLParserDefault : PartiQLParser { GeneratedParser.BLOB -> typeBlob(null) GeneratedParser.CLOB -> typeClob(null) GeneratedParser.DATE -> typeDate() - GeneratedParser.STRUCT -> typeStruct() - GeneratedParser.TUPLE -> typeTuple() - GeneratedParser.LIST -> typeList() GeneratedParser.SEXP -> typeSexp() GeneratedParser.BAG -> typeBag() GeneratedParser.ANY -> typeAny() @@ -2189,6 +2228,39 @@ internal class PartiQLParserDefault : PartiQLParser { typeCustom(ctx.text.uppercase()) } + override fun visitTypeComplexUnparameterized(ctx: GeneratedParser.TypeComplexUnparameterizedContext) = translate(ctx) { + when (ctx.datatype.type) { + GeneratedParser.STRUCT, GeneratedParser.TUPLE -> typeStruct(emptyList()) + GeneratedParser.ARRAY, GeneratedParser.LIST -> typeArray(null) + else -> throw error(ctx.datatype, "Invalid datatype") + } + } + + override fun visitTypeList(ctx: GeneratedParser.TypeListContext) = translate(ctx) { + val type = visitOrNull(ctx.type()) + ?.also { isValidTypeDeclarationOrThrow(it, ctx.type()) } + typeArray(type) + } + + override fun visitTypeStruct(ctx: GeneratedParser.TypeStructContext) = translate(ctx) { + val fields = ctx.structField().map { structFieldCtx -> + val name = visitAs (structFieldCtx.columnName()) + val type = visitAs(structFieldCtx.type()) + .also { isValidTypeDeclarationOrThrow(it, structFieldCtx.type()) } + + val constraints = structFieldCtx.columnConstraint().map { + when (it.columnConstraintDef()) { + is GeneratedParser.ColConstrNullContext, + is GeneratedParser.ColConstrNotNullContext -> visitColumnConstraint(it) + else -> throw error(it, "Only NULL Constraint and NOT NULL Constraint are allowed in Struct field") + } + } + + typeStructField(name, type, constraints) + } + typeStruct(fields) + } + private inline fun visitOrEmpty(ctx: List?): List = when { ctx.isNullOrEmpty() -> emptyList() else -> ctx.map { visit(it) as T } diff --git a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserDDLTests.kt b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserDDLTests.kt index ee80ca2a2d..46a2cce13a 100644 --- a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserDDLTests.kt +++ b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserDDLTests.kt @@ -6,6 +6,7 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.ArgumentsProvider import org.junit.jupiter.params.provider.ArgumentsSource +import org.partiql.ast.Constraint import org.partiql.ast.DdlOp import org.partiql.ast.Expr import org.partiql.ast.Identifier @@ -312,6 +313,220 @@ class PartiQLParserDDLTests { ), ) ), + + SuccessTestCase( + "CREATE TABLE with STRUCT", + """ + CREATE TABLE tbl ( + a STRUCT< + b: INT2, + c: INT2 NOT NULL + > + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Struct( + listOf( + Type.Struct.Field( + identifierSymbol("b", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + emptyList() + ), + Type.Struct.Field( + identifierSymbol("c", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + listOf(Constraint(null, Constraint.Definition.NotNull())) + ) + ) + ), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + + SuccessTestCase( + "CREATE TABLE with STRUCT of complex", + """ + CREATE TABLE tbl ( + a STRUCT< + b: STRUCT , + d: ARRAY + > + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Struct( + listOf( + Type.Struct.Field( + identifierSymbol("b", Identifier.CaseSensitivity.INSENSITIVE), + Type.Struct( + listOf( + Type.Struct.Field( + identifierSymbol("c", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + emptyList() + ), + ) + ), + emptyList() + ), + Type.Struct.Field( + identifierSymbol("d", Identifier.CaseSensitivity.INSENSITIVE), + Type.Array(Type.Int2()), + emptyList() + ) + ) + ), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + + SuccessTestCase( + "CREATE TABLE with empty", + """ + CREATE TABLE tbl ( + a STRUCT + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Struct( + emptyList() + ), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + + SuccessTestCase( + "CREATE TABLE with ARRAY", + """ + CREATE TABLE tbl ( + a ARRAY + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Array(Type.Int2()), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + SuccessTestCase( + "CREATE TABLE with ARRAY of Struct", + """ + CREATE TABLE tbl ( + a ARRAY< STRUCT< b:INT2 > > + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Array( + Type.Struct( + listOf( + Type.Struct.Field( + identifierSymbol("b", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + emptyList() + ), + ) + ), + ), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + SuccessTestCase( + "CREATE TABLE no space between angle right", + """ + CREATE TABLE tbl( + a LIST> + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Array( + Type.Struct( + listOf( + Type.Struct.Field( + identifierSymbol("b", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + emptyList() + ), + ) + ), + ), + emptyList(), + ) + ), + emptyList() + ), + ) + ), + + SuccessTestCase( + "CREATE TABLE with ARRAY without element type", + """ + CREATE TABLE tbl ( + a ARRAY + ) + """.trimIndent(), + ddlOpCreateTable( + identifierSymbol("tbl", Identifier.CaseSensitivity.INSENSITIVE), + tableDefinition( + listOf( + tableDefinitionAttribute( + identifierSymbol("a", Identifier.CaseSensitivity.INSENSITIVE), + Type.Array(null), + emptyList(), + ) + ), + emptyList() + ), + ) + ), ) val dropTableTests = listOf( @@ -371,7 +586,57 @@ class PartiQLParserDDLTests { CHECK (SELECT a FROM foo) ) """.trimIndent() - ) + ), + ErrorTestCase( + "NULL not allowed as type in type declaration", + """ + CREATE TABLE TBL( + a NULL + ) + """.trimIndent() + ), + ErrorTestCase( + "MISSING not allowed as type in type declaration", + """ + CREATE TABLE TBL( + a MISSING + ) + """.trimIndent() + ), + ErrorTestCase( + "STRUCT<> NOT Supported", + """ + CREATE TABLE TBL( + a STRUCT<> + ) + """.trimIndent() + ), + ErrorTestCase( + "LIST<> NOT Supported", + """ + CREATE TABLE TBL( + a LIST<> + ) + """.trimIndent() + ), + + // TODO: Move this to another place as part of parser test porting process + ErrorTestCase( + "Struct Field declaration not allowed for is Operator", + "a IS STRUCT" + ), + ErrorTestCase( + "Struct Field declaration not allowed for CAST Operator", + "CAST(a AS STRUCT)" + ), + ErrorTestCase( + "ELEMENT declaration for LIST Type not allowed for is Operator", + "a IS LIST" + ), + ErrorTestCase( + "Struct Field declaration not allowed for CAST Operator", + "CAST(a AS LIST)" + ), ) override fun provideArguments(p0: ExtensionContext?): Stream = errorTestCases.map { Arguments.of(it) }.stream() diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt index 5edecc3e4f..0c4e1f068c 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt @@ -283,7 +283,7 @@ internal object NormalizeSelect { expr = null, branches = listOf( exprCaseBranch( - condition = exprIsType(expr, typeStruct(), null), + condition = exprIsType(expr, typeStruct(emptyList()), null), expr = expr ) ), 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 e4ab533d53..6b9471315d 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 @@ -597,12 +597,14 @@ internal object RexConverter { is Type.TimestampWithTz -> call("is_timestampWithTz", arg0) is Type.Interval -> call("is_interval", arg0) is Type.Bag -> call("is_bag", arg0) - is Type.List -> call("is_list", arg0) is Type.Sexp -> call("is_sexp", arg0) - is Type.Tuple -> call("is_tuple", arg0) - is Type.Struct -> call("is_struct", arg0) is Type.Any -> call("is_any", arg0) is Type.Custom -> call("is_custom", arg0) + is Type.List -> call("is_list", arg0) + is Type.Tuple -> call("is_tuple", arg0) + // Note that for is function, the parser will reject parameterized list/struct + is Type.Array -> call("is_list", arg0) + is Type.Struct -> call("is_struct", arg0) } if (node.not == true) { @@ -768,12 +770,13 @@ internal object RexConverter { is Type.TimestampWithTz -> PartiQLValueType.TIMESTAMP is Type.Interval -> PartiQLValueType.INTERVAL is Type.Bag -> PartiQLValueType.BAG - is Type.List -> PartiQLValueType.LIST is Type.Sexp -> PartiQLValueType.SEXP - is Type.Tuple -> PartiQLValueType.STRUCT - is Type.Struct -> PartiQLValueType.STRUCT is Type.Any -> PartiQLValueType.ANY is Type.Custom -> TODO("Custom type not supported ") + is Type.List -> PartiQLValueType.LIST + is Type.Tuple -> PartiQLValueType.STRUCT + is Type.Array -> PartiQLValueType.LIST + is Type.Struct -> PartiQLValueType.STRUCT } return rex(StaticType.ANY, rexOpCastUnresolved(target, arg)) }