Skip to content

struct subfield and list element type #1449

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 95 additions & 10 deletions partiql-ast/api/partiql-ast.api

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1346,11 +1346,22 @@ private class AstTranslator(val metas: Map<String, MetaContainer>) : 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) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,13 @@ internal abstract class InternalSqlDialect : AstBaseVisitor<InternalSqlBlock, In

override fun visitTypeList(node: Type.List, tail: InternalSqlBlock): InternalSqlBlock = tail concat "LIST"

// TODO: Support List Element
override fun visitTypeArray(node: Type.Array, tail: InternalSqlBlock): InternalSqlBlock = tail concat "ARRAY"
override fun visitTypeSexp(node: Type.Sexp, tail: InternalSqlBlock): InternalSqlBlock = tail concat "SEXP"

override fun visitTypeTuple(node: Type.Tuple, tail: InternalSqlBlock): InternalSqlBlock = tail concat "TUPLE"

// TODO: Support Struct Field
override fun visitTypeStruct(node: Type.Struct, tail: InternalSqlBlock): InternalSqlBlock = tail concat "STRUCT"

override fun visitTypeAny(node: Type.Any, tail: InternalSqlBlock): InternalSqlBlock = tail concat "ANY"
Expand Down
21 changes: 20 additions & 1 deletion partiql-ast/src/main/resources/partiql_ast.ion
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,29 @@ type::[
timestamp_with_tz::{ precision: optional::int }, // TIMESTAMP [(<int>)] WITH TIMEZONE
interval::{ precision: optional::int }, // INTERVAL
bag::{}, // BAG
// Keep the list type for backward compatible reason
// user should migrate to the array type
list::{}, // LIST
array::{ type: optional::type }, // ARRAY [<type>]
sexp::{}, // SEXP
// Keep the tuple type for backward compatible reason
// migration: in v0.15.0: struct modeling should NOT be Introduced,
// users of struct type should be migrate to tuple type.
// in v1.0.0: introduce the struct modeling change, all users from tuple type should migrate to struct type.
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 <fields>
any::{}, // ANY
custom::{ name: string }, // <symbol>
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<b : INT2>
)
""".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<INT2>
)
""".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<b : INT2>
""".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<b : INT2>)
""".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<INT2>
""".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<INT2>)
""".trimIndent(),
code = ErrorCode.PARSE_UNEXPECTED_TOKEN,
context = mapOf(),
),
)
}
}
Loading