-
Notifications
You must be signed in to change notification settings - Fork 67
v0.1 to v0.2 upgrade
yliuuuu edited this page Nov 2, 2022
·
4 revisions
- Adds support for
DISTINCT,LET(fromFROMclause), system stored procedure calls (EXEC) - Adds parser support for DML statements (
INSERT,UPDATE,DELETE),Parameter,BYvariable - Improvements to
LIKEpattern compilation performance - Adds function to convert from UNIX epoch to TIMESTAMP and TIMESTAMP to UNIX epoch
-
AstRewriter,AstRewriterBase,MetaStrippingRewriter,RewriterTestBase- Existing AST rewriters upgraded to use PIG’s
VisitorTransforms -
AstRewriterBasetoVisitorTransformguide provided here
- Existing AST rewriters upgraded to use PIG’s
-
V0AstSerializer,AstSerializer,AstDeserializer, and classes & functions relating to the V0Ast- Users are encouraged to use
PartiqlAst. Do not useExprNodewhich was deprecated in v0.6.* and will be removed in an upcoming major version (see partiql-lang-kotlin#682 for tracking).
- Users are encouraged to use
- New error codes for division by
0and modulo0 - [fix] float negative zero equality
- Removes invalid syntax check on case expressions w/ type parameters e.g.,
CAST(a AS DECIMAL(1, 2))now does not throw - [fix]
LIMITwith value over 2^31 returning no values - [fix]
LIMITclause execution order - [fix] stop treating date parts as if they are string literals
- [fix] parsing of
TRIMspecification keywords (BOTH,LEADING, andTRAILING) - Adds some AST rewriters —
SelectStarRewriterandStaticTypeRewriter
-
JOINrequires anONclause. In v0.1.*, theONclause was optional, which caused ambiguous parsing of multipleJOIN
// ----- v0.1.* -----
// Initialization of components related to evaluating a query end-to-end
val ion = IonSystemBuilder.standard().build()
val parser = SqlParser(ion)
val pipeline = CompilerPipeline.standard(ion)
val evaluationSession = EvaluationSession.standard()
// Query with a JOIN without an ON clause. In v0.1.*, the ON condition is optional.
val query = "SELECT * FROM <<{'a': 1}>> INNER JOIN <<{'a': 2}>>"
val parsedQuery = parser.parseExprNode(query)
val compiledQuery = pipeline.compile(parsedQuery)
val result = compiledQuery.eval(evaluationSession)
// Query successfully evaluates. Here we compare the result to its string representation.
assertEquals("<<{'a': 1, 'a': 2}>>", result.toString())
// Query with an ON clause successfully parses and can be evaluated
val resultWithOn = pipeline.compile("SELECT * FROM <<{'a': 1}>> INNER JOIN <<{'a': 2}>> ON true").eval(evaluationSession)
assertEquals(result.toString(), resultWithOn.toString())// ----- v0.2.* -----
// Query with a JOIN without an ON clause. Starting in v0.2.0, the ON condition is REQUIRED except for cross
// joins. When not provided, a parser error is thrown.
val query = "SELECT * FROM <<{'a': 1}>> INNER JOIN <<{'a': 2}>>"
assertFailsWith<ParserException> {
parser.parseExprNode(query)
}
// Query with an ON clause still successfully parses and can be evaluated in v0.2.* onwards
val resultWithOn = pipeline.compile("SELECT * FROM <<{'a': 1}>> INNER JOIN <<{'a': 2}>> ON true").eval(evaluationSession)
assertEquals("<<{'a': 1, 'a': 2}>>", resultWithOn.toString())
NOTE: ExprNode is deprecated and replaced with PartiqlAst. Users can look at ExprNodeToStatement.kt and RewriterToVisitorTransformGuide.md to see how to upgrade from ExprNode to PartiqlAst.
- Refactoring of
ExprNodeAST (see 16fefe0)FromSourceExprvariables (changed to useLetVariables).
// ----- v0.1.* -----
// FROM source and FROM source UNPIVOT are modeled differently between v0.1.* and v0.2.*
// The following is an AstNode/ExprNode representation of '... FROM foo AS f AT g' in v0.1.*
val fromExpr = VariableReference(id = "foo", case = CaseSensitivity.INSENSITIVE, metas = metaContainerOf())
FromSourceExpr(
expr = fromExpr,
asName = SymbolicName(name = "f", metas = metaContainerOf()),
atName = SymbolicName(name = "g", metas = metaContainerOf())
)
// The following models '... FROM UNPIVOT foo AS f AT g'
FromSourceUnpivot(
expr = fromExpr,
asName = SymbolicName(name = "f", metas = metaContainerOf()),
atName = SymbolicName(name = "g", metas = metaContainerOf()),
metas = metaContainerOf()
)// ----- v0.2.* -----
// The following is an AstNode/ExprNode representation of '... FROM foo AS f AT g' in v0.2.*
val fromExpr = VariableReference(id = "foo", case = CaseSensitivity.INSENSITIVE, metas = metaContainerOf())
FromSourceExpr(
expr = fromExpr,
variables = LetVariables(
asName = SymbolicName(name = "f", metas = metaContainerOf()),
atName = SymbolicName(name = "g", metas = metaContainerOf())
// v0.2.0 onwards also allows specifying a `BY` variable in FROM sources
)
)
// The following models '... FROM UNPIVOT foo AS f AT g'
FromSourceUnpivot(
expr = fromExpr,
variables = LetVariables(
asName = SymbolicName(name = "f", metas = metaContainerOf()),
atName = SymbolicName(name = "g", metas = metaContainerOf())
),
metas = metaContainerOf()
)- Refactoring of
ExprNodeAST (see 16fefe0)ListandBagExprNodes defined under aSeqclass
// ----- v0.1.* -----
val ion = IonSystemBuilder.standard().build()
val elem1 = Literal(ionValue = ion.singleValue("1"), metas = metaContainerOf())
val elem2 = Literal(ionValue = ion.singleValue("2"), metas = metaContainerOf())
val elem3 = Literal(ionValue = ion.singleValue("3"), metas = metaContainerOf())
// LIST and BAG are modeled differently between v0.1.* and v0.2.*
// The following is an AstNode/ExprNode representation of [1, 2, 3]
ListExprNode(
values = listOf(
elem1,
elem2,
elem3
),
metas = metaContainerOf()
)
// The following is an AstNode/ExprNode representation of <<1, 2, 3>>
Bag(
bag = listOf(
elem1,
elem2,
elem3
),
metas = metaContainerOf()
)// ----- v0.2.* -----
// The following is an AstNode/ExprNode representation of [1, 2, 3]
Seq(
type = SeqType.LIST,
values = listOf(
elem1,
elem2,
elem3
),
metas = metaContainerOf()
)
// The following is an AstNode/ExprNode representation of <<1, 2, 3>>
Seq(
type = SeqType.BAG,
values = listOf(
elem1,
elem2,
elem3
),
metas = metaContainerOf()
)
// v0.2.0 onwards also allows for specifying s-expressions. E.g. (1 2 3)
Seq(
type = SeqType.SEXP,
values = listOf(
elem1,
elem2,
elem3
),
metas = metaContainerOf()
)- Starting in v0.2.*, the classes and functions related to
V0AstSerializer,AstSerializer,AstDeserializerhave been deprecated and will be removed in a future PartiQL release. Below is an example demonstrating how to update V0AstIonSexprewriting code to usePartiqlAst.
// ----- v0.1.* -----
// v0.1.* parsed the PartiQL statement to an `ExprNode` that could be serialized to the V0Ast. `ExprNode` and `V0Ast`
// have been deprecated in favor of PartiqlAst.
val node: ExprNode = SqlParser(ion).parseExprNode("SELECT * FROM <<{'a': 1, 'b': {'c': 23}}>>")
val ionSexp: IonSexp = V0AstSerializer.serialize(node, ion)
// below is a way to recursively rewrite a V0Ast/IonSexp statement. This particular example function rewrites
// any encountered int literal to 42.
fun rewriteIntsTo42(sexp: IonSexp): IonSexp {
val rewritten = sexp.map { child ->
when (child) {
is IonSexp -> rewriteIntsTo42(child)
is IonInt -> ion.newInt(42)
else -> child.clone()
}
}
return ion.newSexp(*rewritten.toTypedArray())
}
val rewrittenIonSexp = rewriteIntsTo42(ionSexp)
// the rewritten statement will be equivalent to the following statement (excluding source location metas)
val expectedIonSexp = SqlParser(ion).parse("SELECT * FROM <<{'a': 42, 'b': {'c': 42}}>>")
assertEquals(expectedIonSexp.filterMetaNodes(), rewrittenIonSexp.filterMetaNodes())// v0.2.* onwards recommend using the `PartiqlAst` over any other AST versions
val partiqlAst = SqlParser(ion).parseAstStatement("SELECT * FROM <<{'a': 1, 'b': {'c': 23}}>>")
// below shows a way to create the same recursive rewriting function on `PartiqlAst` statements using the
// `VisitorTransform` class
class RewriteIntsTo42: PartiqlAst.VisitorTransform() {
override fun transformExprLit(node: PartiqlAst.Expr.Lit): PartiqlAst.Expr {
val newValue = when (node.value) {
is IntElement -> ionInt(42)
else -> node.value
}
val newNode = PartiqlAst.build {
lit(newValue)
}
return super.transformExprLit(newNode)
}
}
val rewrittenStatement = RewriteIntsTo42().transformStatement(partiqlAst)
val expectedPartiqlAst = SqlParser(ion).parseAstStatement("SELECT * FROM <<{'a': 42, 'b': {'c': 42}}>>")
assertEquals(expectedPartiqlAst, rewrittenStatement)- General
- Tutorials
- Documentation
- Clauses
- Testing
- Serde
- Upgrade Guides
- Design & Development Documents
- V1 Documentation
- Basics
- PartiQL CLI
- Developer Usage Guides