Skip to content

v0.4 to v0.5 upgrade

yliuuuu edited this page Nov 2, 2022 · 4 revisions

v0.5.* (latest v0.5.0)

New features

  • Adds support for OFFSET
  • Adds a static type inferencer for static query checks and query type inference
  • Adds multiple exception logging and severity level API
  • Adds the dataguide API which can be used to infer Ion schema from Ion data
    • Also adds mappers to and from PartiQL’s static type and ISL
  • Adds evaluator option for PERMISSIVE mode
  • Adds support for CAN_CAST and CAN_LOSSLESS_CAST ExprFunctions
  • Adds evaluation-time function call (i.e. ExprFunction) argument type checks
  • Adds integer8, int8, bigint, int2, and integer2 as type names
  • Adds additional types to StaticType and additional methods on those types

Deprecated items

  • ExprNode in parser

Misc/bug fixes

  • [fix] evaluator behavior to error for structs with non-text keys
  • [fix] the parser error for unexpected reserved keywords in a select list
  • [fix] static initializing cycle with lazy initialization of SqlDataType
  • [fix] unknown propagation for IN operator
  • [fix] bug in precision check for NUMERIC
  • Makes unknown simple CASE WHEN predicate the same as false
  • Make unknown branch predicates the same as false for searched CASE WHEN
  • Disallows duplicate projected fields in select list query
  • [fix] EXTRACT ExprFunction to return a decimal instead of float
  • [fix] EXISTS and DATE_DIFF function signatures
  • [fix] GROUP BY for more than 2 nested path expressions (#461)

Breaking changes

Breaking API changes

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.

  1. Removes outer sealed class of DateTimeType for ExprNode
// ----- v0.4.* -----
// In v0.4.0 and before, date value constructor required the outer `DateTimeType` sealed class
val date = DateTimeType.Date(year = 2022, month = 1, day = 1, metas = emptyMetaContainer)

// Similarly, for the time value constructor
val time = DateTimeType.Time(
    hour = 12,
    minute = 34,
    second = 56,
    nano = 78,
    precision = 2,
    with_time_zone = false,
    metas = emptyMetaContainer
)
// ----- v0.5.* -----
// In v0.5.0 and before, date value constructor uses `DateLiteral` without an outer sealed class
val date = DateLiteral(year = 2022, month = 1, day = 1, metas = emptyMetaContainer)

// Similarly, for the time value constructor uses `TimeLiteral` without an outer sealed class
val time = TimeLiteral(
    hour = 12,
    minute = 34,
    second = 56,
    nano = 78,
    precision = 2,
    with_time_zone = false,
    metas = emptyMetaContainer
)
  1. Refactor of ExprFunction interface
// ----- v0.4.* -----
val exprValueFactory = ExprValueFactory.standard(IonSystemBuilder.standard().build())

// `ExprFunction`s defined in v0.4.0 and before implemented the `NullPropagatingExprFunction`
// abstract class, which implements the `ArityCheckingTrait` and `ExprFunction` interfaces
// Below is an example `ExprFunction` definition that requires one argument and makes another
// argument optional. The implementation will need to override `eval` to specify the behavior.
class SomeExprFunction():  NullPropagatingExprFunction(
    name = "some_expr_function",
    arity = 1..2,
    exprValueFactory
) {
    override fun eval(env: Environment, args: List<ExprValue>): ExprValue {
        TODO("Implementation details with and without the optional argument")
    }
}
// ----- v0.5.* -----
// Starting in v0.5.0, the `ExprFunction` interface has been refactored and `ExprFunction` implementations will
// need to define the `FunctionSignature` of the function which specifies the name, return type, and any
// required, optional, and variadic arguments. The implementation will need to override `callWith*` depending
// on the permitted arguments (in this example, overriding `callWithRequired` and `callWithOptional`).
// Note: in v0.6.0, the first argument to the `callWith*` function was changed from `Environment` to
// `EvaluationSession`
class SomeExprFunction(): ExprFunction {
    override val signature = FunctionSignature(
        name = "some_expr_function",
        requiredParameters = listOf(StaticType.ANY),
        optionalParameter = StaticType.ANY,
        returnType = StaticType.ANY
    )

    override fun callWithRequired(env: Environment, required: List<ExprValue>): ExprValue {
        TODO("Implementation details without optional argument")
    }

    override fun callWithOptional(env: Environment, required: List<ExprValue>, opt: ExprValue): ExprValue {
        TODO("Implementation details with optional argument")
    }
}
  1. UntypedFunctionSignature data class removed
// ----- v0.4.* -----
// v0.4.0 and before had a convenience data class to create an untyped `FunctionSignature` that used a variadic
// number of [StaticType.ANY] parameters and returned [StaticType.ANY]
val funName = "untyped_fun"
// initialization of the untyped `FunctionSignature`
val signature = UntypedFunctionSignature(name = funName)
assertEquals(funName, signature.name)
assertEquals(listOf(VarargFormalParameter(StaticType.ANY)), signature.formalParameters)
assertEquals(StaticType.ANY, signature.returnType)
// ----- v0.5.* -----
// In v0.5.0, due to the refactor of `FunctionSignature`, `UntypedFunctionSignature` was removed. The equivalent
// can be created using the `FunctionSignature` constructor that includes the `variadicParameter` argument.
// Initialization of an untyped `FunctionSignature` with the refactored APIs
val signature = FunctionSignature(
    name = funName,
    requiredParameters = emptyList(),
    variadicParameter = VarargFormalParameter(StaticType.ANY, minCount = 0),
    returnType = StaticType.ANY
)
assertEquals(funName, signature.name)
assertEquals(VarargFormalParameter(StaticType.ANY, minCount = 0), signature.variadicParameter)
assertEquals(StaticType.ANY, signature.returnType)
  1. Models NULLIF and COALESCE as PartiqlAst nodes rather than ExprFunctions
// ----- v0.4.* -----
val ion = IonSystemBuilder.standard().build()
val parser = SqlParser(ion)

// In v0.4.0 and before, NULLIF was modeled as an `ExprFunction` call
val nullIfQuery = "NULLIF(1, 2)"
val nullIfParsedAst = parser.parseAstStatement(nullIfQuery)
val nullIfExpectedAst = PartiqlAst.build {
    query(
        call(
            funcName = "nullif",
            args = listOf(lit(ionInt(1)), lit(ionInt(2))),
        )
    )
}
assertEquals(nullIfExpectedAst, nullIfParsedAst)

// In v0.4.0 and before, COALESCE was modeled as an `ExprFunction` call
val coalesceQuery = "COALESCE(1, 2)"
val coalesceParsedAst = parser.parseAstStatement(coalesceQuery)
val coalesceExpectedAst = PartiqlAst.build {
    query(
        call(
            funcName = "coalesce",
            args = listOf(lit(ionInt(1)), lit(ionInt(2))),
        )
    )
}
assertEquals(coalesceExpectedAst, coalesceParsedAst)
// ----- v0.5.* -----
// In v0.5.0 onwards, NULLIF is modeled as a separate AST node
val nullIfQuery = "NULLIF(1, 2)"
val nullIfParsedAst = parser.parseAstStatement(nullIfQuery)
val nullIfExpectedAst = PartiqlAst.build {
    query(
        nullIf(
            lit(ionInt(1)),
            lit(ionInt(2))
        )
    )
}
assertEquals(nullIfExpectedAst, nullIfParsedAst)

// In v0.5.0 onwards, COALESCE is modeled as a separate AST node
val coalesceQuery = "COALESCE(1, 2)"
val coalesceParsedAst = parser.parseAstStatement(coalesceQuery)
val coalesceExpectedAst = PartiqlAst.build {
    query(
        coalesce(
            args = listOf(lit(ionInt(1)), lit(ionInt(2))),
        )
    )
}
assertEquals(coalesceExpectedAst, coalesceParsedAst)
  1. Upgrades to Kotlin 1.4 -- see https://kotlinlang.org/docs/compatibility-guide-14.html#language-and-stdlib for interop between Kotlin 1.3 and Kotlin 1.4
  2. SqlDataType class changed from an enum class to a sealed class. Note: this class relates to ExprNode which is deprecated in v0.6.0. Recommend upgrade path is to use the PartiqlAst.
  3. Meta deserialize (IonSexp) removed from MetaDeserializer interface (was deprecated in a prior major version)
  4. PARSE_EXPECTED_DATE_PART ErrorCode changed to PARSE_EXPECTED_DATE_TIME_PART
Clone this wiki locally