Skip to content

Commit

Permalink
Fixes function invocation for missing arguments
Browse files Browse the repository at this point in the history
Fixes evaluation of Rex.Op.Missing
  • Loading branch information
johnedquinn committed Jul 25, 2024
1 parent 73db367 commit 923c8a0
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 28 deletions.
3 changes: 3 additions & 0 deletions partiql-eval/src/main/java/org/partiql/eval/value/Datum.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ default Datum getInsensitive(@NotNull String name) {
@Deprecated
default PartiQLValue toPartiQLValue() {
PType type = this.getType();
if (this.isMissing()) {
return PartiQL.missingValue();
}
switch (type.getKind()) {
case BOOL:
return this.isNull() ? PartiQL.boolValue(null) : PartiQL.boolValue(this.getBoolean());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import org.partiql.plan.Rel
import org.partiql.plan.Rex
import org.partiql.plan.Statement
import org.partiql.plan.debug.PlanPrinter
import org.partiql.plan.rexOpErr
import org.partiql.plan.visitor.PlanBaseVisitor
import org.partiql.spi.fn.Agg
import org.partiql.spi.fn.FnExperimental
Expand Down Expand Up @@ -267,16 +266,7 @@ internal class Compiler(
}

override fun visitRexOpMissing(node: Rex.Op.Missing, ctx: PType?): Operator {
return when (session.mode) {
PartiQLEngine.Mode.PERMISSIVE -> {
// Make a runtime TypeCheckException.
ExprMissing(node.message)
}
PartiQLEngine.Mode.STRICT -> {
// Promote to error.
visitRexOpErr(rexOpErr(node.message, node.causes), null)
}
}
return ExprMissing(ctx ?: PType.typeUnknown()) // TODO: Pass a type
}

// REL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal class ExprCallDynamic(
val actualTypes = actualArgs.map { it.type }
candidateIndex.get(actualTypes)?.let {
val transformedArgs = Array(actualArgs.size) {
actualArgs[it].toPartiQLValue()
actualArgs[it]
}
return it.eval(transformedArgs, env)
}
Expand Down Expand Up @@ -63,15 +63,19 @@ internal class ExprCallDynamic(
*/
private val nil = { Datum.nullValue(fn.signature.returns) }

fun eval(originalArgs: Array<PartiQLValue>, env: Environment): Datum {
/**
* Memoize creation of missing values
*/
private val missing = { Datum.missingValue(fn.signature.returns) }

fun eval(originalArgs: Array<Datum>, env: Environment): Datum {
val args = originalArgs.mapIndexed { i, arg ->
if (arg.isNull && fn.signature.isNullCall) {
return nil.invoke()
}
if (arg.isNull && fn.signature.isNullCall) return nil.invoke()
if (arg.isMissing && fn.signature.isMissingCall) return missing.invoke()
when (val c = coercions[i]) {
null -> arg
else -> ExprCast(ExprLiteral(Datum.of(arg)), c).eval(env).toPartiQLValue()
}
else -> ExprCast(ExprLiteral(arg), c).eval(env)
}.toPartiQLValue()
}.toTypedArray()
return Datum.of(fn.invoke(args))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.partiql.eval.internal.operator.rex

import org.partiql.errors.TypeCheckException
import org.partiql.eval.internal.Environment
import org.partiql.eval.internal.operator.Operator
import org.partiql.eval.value.Datum
Expand All @@ -19,12 +18,17 @@ internal class ExprCallStatic(
*/
private val nil = { Datum.nullValue(fn.signature.returns) }

/**
* Memoize creation of missing values
*/
private val missing = { Datum.missingValue(fn.signature.returns) }

override fun eval(env: Environment): Datum {
// Evaluate arguments
val args = inputs.map { input ->
val r = input.eval(env)
if (r.isNull && fn.signature.isNullCall) return nil.invoke()
if (r.isMissing && fn.signature.isMissingCall) throw TypeCheckException()
if (r.isMissing && fn.signature.isMissingCall) return missing.invoke()
r.toPartiQLValue()
}.toTypedArray()
return Datum.of(fn.invoke(args))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package org.partiql.eval.internal.operator.rex

import org.partiql.errors.TypeCheckException
import org.partiql.eval.internal.Environment
import org.partiql.eval.internal.operator.Operator
import org.partiql.eval.value.Datum
import org.partiql.types.PType

internal class ExprMissing(
private val message: String,
private val type: PType
) : Operator.Expr {

override fun eval(env: Environment): Datum {
throw TypeCheckException(message)
return Datum.missingValue(type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,20 @@ class PartiQLEngineDefaultTest {
structValue("a" to int32Value(1), "b" to int32Value(2))
)
),
// PartiQL Specification Section 7.1 -- Inputs with wrong types Example 28 (1)
// According to the Specification, in permissive mode, functions/operators return missing when one of
// the parameters is missing.
SuccessTestCase(
input = "SELECT VALUE 5 + v FROM <<1, MISSING>> AS v;",
expected = bagValue(int32Value(6), missingValue())
),
// PartiQL Specification Section 7.1 -- Inputs with wrong types Example 28 (1)
// See https://github.com/partiql/partiql-tests/pull/118 for more information.
SuccessTestCase(
input = "SELECT VALUE 5 + v FROM <<1, MISSING>> AS v;",
expected = bagValue(int32Value(6), missingValue()),
mode = PartiQLEngine.Mode.STRICT
),
)

@JvmStatic
Expand Down Expand Up @@ -1194,11 +1208,6 @@ class PartiQLEngineDefaultTest {
"amzn" to decimalValue(BigDecimal.valueOf(840.05))
)
),
TypingTestCase(
name = "PartiQL Specification Section 7.1 -- Inputs with wrong types Example 28 (1)",
input = "SELECT VALUE 5 + v FROM <<1, MISSING>> AS v;",
expectedPermissive = bagValue(int32Value(6), missingValue())
),
TypingTestCase(
name = "PartiQL Specification Section 7.1 -- Inputs with wrong types Example 28 (3)",
input = "SELECT VALUE NOT v FROM << false, {'a':1} >> AS v;",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class EvalExecutor(
if (actual is PartiQLResult.Value && expect is PartiQLResult.Value) {
return valueComparison(actual.value, expect.value)
}
if (actual is PartiQLResult.Error) {
throw actual.cause
}
val errorMessage = buildString {
appendLine("Cannot compare different types of PartiQLResult.")
appendLine(" - Expected : $expect")
Expand Down

0 comments on commit 923c8a0

Please sign in to comment.