Skip to content
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

Generalizes back-tick Ion to a variant pair in the AST #1591

Merged
merged 1 commit into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
81 changes: 43 additions & 38 deletions partiql-ast/api/partiql-ast.api

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions partiql-ast/src/main/kotlin/org/partiql/ast/helpers/ToLegacyAst.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import com.amazon.ionelement.api.DecimalElement
import com.amazon.ionelement.api.FloatElement
import com.amazon.ionelement.api.IntElement
import com.amazon.ionelement.api.IntElementSize
import com.amazon.ionelement.api.IonElementException
import com.amazon.ionelement.api.MetaContainer
import com.amazon.ionelement.api.emptyMetaContainer
import com.amazon.ionelement.api.ionDecimal
import com.amazon.ionelement.api.ionFloat
import com.amazon.ionelement.api.ionInt
import com.amazon.ionelement.api.ionString
import com.amazon.ionelement.api.ionSymbol
import com.amazon.ionelement.api.loadSingleElement
import com.amazon.ionelement.api.metaContainerOf
import org.partiql.ast.AstNode
import org.partiql.ast.DatetimeField
Expand Down Expand Up @@ -270,8 +272,16 @@ private class AstTranslator(val metas: Map<String, MetaContainer>) : AstBaseVisi
}
}

override fun visitExprIon(node: Expr.Ion, ctx: Ctx) = translate(node) { metas ->
lit(node.value, metas)
override fun visitExprVariant(node: Expr.Variant, ctx: Ctx) = translate(node) { metas ->
if (node.encoding != "ion") {
error("Only `ion` variant encoding is supported in legacy AST")
}
val value = try {
loadSingleElement(node.value)
} catch (e: IonElementException) {
error("Unable to parse Ion value.")
}
lit(value, metas)
}

override fun visitExprVar(node: Expr.Var, ctx: Ctx) = translate(node) { metas ->
Expand Down
8 changes: 5 additions & 3 deletions partiql-ast/src/main/kotlin/org/partiql/ast/sql/SqlDialect.kt
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,11 @@ public abstract class SqlDialect : AstBaseVisitor<SqlBlock, SqlBlock>() {
return head concat r(value)
}

override fun visitExprIon(node: Expr.Ion, head: SqlBlock): SqlBlock {
// simplified Ion value writing, as this intentionally omits formatting
val value = node.value.toString()
override fun visitExprVariant(node: Expr.Variant, head: SqlBlock): SqlBlock {
if (node.encoding != "ion") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe having the encoding as an enum is a better option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, however I'm not sure the best way to make it extensible/extendable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of it like the "content-type" header

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see thinking of it same as "content-type" make sense if we are directly working on the serialized payload. But if the node is an in-memory (which can be deserialized from the payload), we may benefit from Enum.

error("Unsupported encoding ${node.encoding}")
}
val value = node.value
return head concat r("`$value`")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,11 @@ internal abstract class InternalSqlDialect : AstBaseVisitor<InternalSqlBlock, In
return tail concat value
}

override fun visitExprIon(node: Expr.Ion, tail: InternalSqlBlock): InternalSqlBlock {
// simplified Ion value writing, as this intentionally omits formatting
val value = node.value.toString()
override fun visitExprVariant(node: Expr.Variant, tail: InternalSqlBlock): InternalSqlBlock {
if (node.encoding != "ion") {
error("Unsupported encoding ${node.encoding}")
}
val value = node.value
return tail concat "`$value`"
}

Expand Down
9 changes: 5 additions & 4 deletions partiql-ast/src/main/resources/partiql_ast.ion
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
imports::{ kotlin: [
ion::'com.amazon.ionelement.api.IonElement',
value::'org.partiql.value.PartiQLValue',
],
}
Expand Down Expand Up @@ -157,13 +156,15 @@ set_quantifier::[
expr::[

// PartiQL Literal Value
// TODO https://github.com/partiql/partiql-lang-kotlin/issues/1589
lit::{
value: '.value',
},

// Ion Literal Value, ie `<ion>`
ion::{
value: '.ion',
// Variant literals such as `<ion>`
variant::{
value: string,
encoding: string,
},

// Variable Reference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package org.partiql.ast.helpers

import com.amazon.ion.Decimal
import com.amazon.ionelement.api.IonElement
import com.amazon.ionelement.api.MetaContainer
import com.amazon.ionelement.api.ionBool
import com.amazon.ionelement.api.ionDecimal
Expand All @@ -27,6 +28,7 @@ import org.partiql.ast.Sort
import org.partiql.ast.builder.AstBuilder
import org.partiql.ast.builder.ast
import org.partiql.ast.exprLit
import org.partiql.ast.exprVariant
import org.partiql.ast.identifierSymbol
import org.partiql.lang.domains.PartiqlAst
import org.partiql.value.PartiQLValueExperimental
Expand Down Expand Up @@ -205,6 +207,8 @@ class ToLegacyAstTest {
// TODO detailed tests just for _DateTime_ types
)

private fun exprIon(value: IonElement): Expr = exprVariant(value.toString(), "ion")

@JvmStatic
fun identifiers() = listOf(
expect("(id 'a' (case_sensitive) (unqualified))") {
Expand Down
25 changes: 25 additions & 0 deletions partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.partiql.ast.sql

import com.amazon.ion.Decimal
import com.amazon.ionelement.api.IonElement
import com.amazon.ionelement.api.ionBool
import com.amazon.ionelement.api.ionDecimal
import com.amazon.ionelement.api.ionFloat
Expand All @@ -25,6 +26,7 @@ import org.partiql.ast.Sort
import org.partiql.ast.builder.AstBuilder
import org.partiql.ast.builder.ast
import org.partiql.ast.exprLit
import org.partiql.ast.exprVariant
import org.partiql.value.PartiQLValueExperimental
import org.partiql.value.boolValue
import org.partiql.value.dateValue
Expand Down Expand Up @@ -449,8 +451,31 @@ class SqlDialectTest {
expect("""`hello`""") {
exprIon(ionSymbol("hello"))
},
expect("`a::b::null`") {
exprIon(ionNull().withAnnotations("a", "b"))
},
expect("`a::b::true`") {
exprIon(ionBool(true).withAnnotations("a", "b"))
},
expect("`a::b::1`") {
exprIon(ionInt(1).withAnnotations("a", "b"))
},
expect("`a::b::1.2e0`") {
exprIon(ionFloat(1.2).withAnnotations("a", "b"))
},
expect("`a::b::1.3`") {
exprIon(ionDecimal(Decimal.valueOf(1.3)).withAnnotations("a", "b"))
},
expect("""`a::b::"hello"`""") {
exprIon(ionString("hello").withAnnotations("a", "b"))
},
expect("""`a::b::hello`""") {
exprIon(ionSymbol("hello").withAnnotations("a", "b"))
},
)

private fun exprIon(value: IonElement): Expr = exprVariant(value.toString(), "ion")

@JvmStatic
fun exprVarCases() = listOf(
// DEFAULT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ package org.partiql.parser.internal
import com.amazon.ionelement.api.IntElement
import com.amazon.ionelement.api.IntElementSize
import com.amazon.ionelement.api.IonElement
import com.amazon.ionelement.api.IonElementException
import com.amazon.ionelement.api.loadSingleElement
import org.antlr.v4.runtime.BailErrorStrategy
import org.antlr.v4.runtime.BaseErrorListener
import org.antlr.v4.runtime.CharStreams
Expand Down Expand Up @@ -67,7 +65,6 @@ import org.partiql.ast.exprDateAdd
import org.partiql.ast.exprDateDiff
import org.partiql.ast.exprExtract
import org.partiql.ast.exprInCollection
import org.partiql.ast.exprIon
import org.partiql.ast.exprIsType
import org.partiql.ast.exprLike
import org.partiql.ast.exprLit
Expand All @@ -91,6 +88,7 @@ import org.partiql.ast.exprStructField
import org.partiql.ast.exprSubstring
import org.partiql.ast.exprTrim
import org.partiql.ast.exprVar
import org.partiql.ast.exprVariant
import org.partiql.ast.exprWindow
import org.partiql.ast.exprWindowOver
import org.partiql.ast.fromJoin
Expand Down Expand Up @@ -1820,12 +1818,9 @@ internal class PartiQLParserDefault : PartiQLParser {
}

override fun visitLiteralIon(ctx: GeneratedParser.LiteralIonContext) = translate(ctx) {
val value = try {
loadSingleElement(ctx.ION_CLOSURE().getStringValue())
} catch (e: IonElementException) {
throw error(ctx, "Unable to parse Ion value.", e)
}
exprIon(value)
val value = ctx.ION_CLOSURE().getStringValue()
val encoding = "ion"
exprVariant(value, encoding)
}

override fun visitLiteralString(ctx: GeneratedParser.LiteralStringContext) = translate(ctx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.partiql.planner.internal.transforms

import com.amazon.ionelement.api.loadSingleElement
import org.partiql.ast.AstNode
import org.partiql.ast.DatetimeField
import org.partiql.ast.Expr
Expand Down Expand Up @@ -103,10 +104,15 @@ internal object RexConverter {
return rex(type, op)
}

override fun visitExprIon(node: Expr.Ion, ctx: Env): Rex {
val value =
PartiQLValueIonReaderBuilder
.standard().build(node.value).read()
/**
* TODO PartiQLValue will be replaced by Datum (i.e. IonDatum) is a subsequent PR.
*/
override fun visitExprVariant(node: Expr.Variant, ctx: Env): Rex {
if (node.encoding != "ion") {
throw IllegalArgumentException("unsupported encoding ${node.encoding}")
}
val ion = loadSingleElement(node.value)
val value = PartiQLValueIonReaderBuilder.standard().build(ion).read()
val type = CompilerType(value.type.toPType())
return rex(type, rexOpLit(value))
}
Expand Down
Loading