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 df47641154..a01096ae4f 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 @@ -1674,7 +1674,7 @@ internal class PartiQLPigVisitor( customType_(SymbolPrimitive(customName, metas), metas) } - override fun visitTypeComplexLegacy(ctx: PartiQLParser.TypeComplexLegacyContext) = PartiqlAst.build { + override fun visitTypeComplexUnparameterized(ctx: PartiQLParser.TypeComplexUnparameterizedContext) = PartiqlAst.build { val metas = ctx.datatype.getSourceMetaContainer() when (ctx.datatype.type) { PartiQLParser.TUPLE -> tupleType(metas) diff --git a/partiql-parser/api/partiql-parser.api b/partiql-parser/api/partiql-parser.api index c4c579924b..19f713642e 100644 --- a/partiql-parser/api/partiql-parser.api +++ b/partiql-parser/api/partiql-parser.api @@ -327,7 +327,7 @@ 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 enterTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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 @@ -555,7 +555,7 @@ 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 exitTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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 @@ -788,7 +788,7 @@ 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 visitTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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; @@ -1018,7 +1018,7 @@ 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 enterTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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 @@ -1245,7 +1245,7 @@ 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 exitTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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 @@ -4625,9 +4625,10 @@ public class org/partiql/parser/antlr/PartiQLParser$TypeAtomicContext : org/part public fun exitRule (Lorg/antlr/v4/runtime/tree/ParseTreeListener;)V } -public class org/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext : org/partiql/parser/antlr/PartiQLParser$TypeContext { +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; @@ -5463,7 +5464,7 @@ 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 visitTypeComplexLegacy (Lorg/partiql/parser/antlr/PartiQLParser$TypeComplexLegacyContext;)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; diff --git a/partiql-parser/src/main/antlr/PartiQL.g4 b/partiql-parser/src/main/antlr/PartiQL.g4 index 79e4921b9f..8f5ef40fe8 100644 --- a/partiql-parser/src/main/antlr/PartiQL.g4 +++ b/partiql-parser/src/main/antlr/PartiQL.g4 @@ -814,7 +814,7 @@ type | INTEGER8 | INT8 | BIGINT | REAL | CHAR | CHARACTER | MISSING | STRING | SYMBOL | BLOB | CLOB | DATE | SEXP | BAG | ANY ) # TypeAtomic - | datatype=(STRUCT|TUPLE|LIST) # TypeComplexLegacy + | 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 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 f695db45a4..ee49561562 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 @@ -2214,7 +2214,7 @@ internal class PartiQLParserDefault : PartiQLParser { typeCustom(ctx.text.uppercase()) } - override fun visitTypeComplexLegacy(ctx: GeneratedParser.TypeComplexLegacyContext) = translate(ctx) { + override fun visitTypeComplexUnparameterized(ctx: GeneratedParser.TypeComplexUnparameterizedContext) = translate(ctx) { when (ctx.datatype.type) { GeneratedParser.STRUCT, GeneratedParser.TUPLE -> typeStruct(emptyList()) GeneratedParser.ARRAY, GeneratedParser.LIST -> typeArray(null) 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 2299b459f9..8231a73402 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 @@ -314,11 +315,12 @@ class PartiQLParserDDLTests { ), SuccessTestCase( - "CREATE TABLE with CASE SENSITIVE Identifier as column name", + "CREATE TABLE with STRUCT", """ CREATE TABLE tbl ( a STRUCT< - b: INT2 + b: INT2, + c: INT2 NOT NULL > ) """.trimIndent(), @@ -334,6 +336,11 @@ class PartiQLParserDDLTests { identifierSymbol("b", Identifier.CaseSensitivity.INSENSITIVE), Type.Int2(), emptyList() + ), + Type.Struct.Field( + identifierSymbol("c", Identifier.CaseSensitivity.INSENSITIVE), + Type.Int2(), + listOf(Constraint(null, Constraint.Definition.NotNull())) ) ) ), @@ -346,7 +353,77 @@ class PartiQLParserDDLTests { ), SuccessTestCase( - "CREATE TABLE with CASE SENSITIVE Identifier as column name", + "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 @@ -366,6 +443,59 @@ class PartiQLParserDDLTests { ), ) ), + 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 with LIST 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( @@ -442,6 +572,35 @@ class PartiQLParserDDLTests { ) """.trimIndent() ), + ErrorTestCase( + "STRUCT<> NOT Supported", + """ + CREATE TABLE TBL( + a STRUCT<> + ) + """.trimIndent() + ), + ErrorTestCase( + "LIST<> NOT Supported", + """ + CREATE TABLE TBL( + a LIST<> + ) + """.trimIndent() + ), + + // TODO: Fix Me + // Potentially modify the bag grammar to use + // ANGLE_LEFT ANGLE_LEFT ( expr ( COMMA expr )* )? ANGLE_RIGHT ANGLE_RIGHT + // We should look into the multi-character token in ANTLR grammar + ErrorTestCase( + "ANTLR PARSER ISSUE", + """ + CREATE TABLE TBL( + a LIST> -- the ANTLR LEXER tokenize the >> to ANGLE_DOUBLE_RIGHT + ) + """.trimIndent() + ), // TODO: Move this to another place as part of parser test porting process ErrorTestCase( "Struct Field declaration not allowed for is Operator",