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

[2/2] Parameter match on SqlTypeFamily #1603

Merged
merged 2 commits into from
Oct 2, 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
25 changes: 11 additions & 14 deletions partiql-planner/src/main/kotlin/org/partiql/planner/internal/Env.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.partiql.planner.internal

import org.partiql.planner.internal.casts.CastTable
import org.partiql.planner.internal.casts.Coercions
import org.partiql.planner.internal.ir.Ref
import org.partiql.planner.internal.ir.Rel
import org.partiql.planner.internal.ir.Rex
Expand All @@ -15,6 +14,7 @@ import org.partiql.planner.internal.ir.rexOpCallDynamicCandidate
import org.partiql.planner.internal.ir.rexOpCastResolved
import org.partiql.planner.internal.ir.rexOpVarGlobal
import org.partiql.planner.internal.typer.CompilerType
import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType
import org.partiql.planner.internal.typer.Scope.Companion.toPath
import org.partiql.spi.catalog.Catalog
import org.partiql.spi.catalog.Catalogs
Expand All @@ -23,7 +23,6 @@ import org.partiql.spi.catalog.Name
import org.partiql.spi.catalog.Session
import org.partiql.spi.function.Aggregation
import org.partiql.types.PType
import org.partiql.types.PType.Kind

/**
* [Env] is similar to the database type environment from the PartiQL Specification. This includes resolution of
Expand Down Expand Up @@ -265,13 +264,12 @@ internal class Env(private val session: Session) {
/**
* Check if this function accepts the exact input argument types. Assume same arity.
*/

private fun Aggregation.matches(args: List<PType>): Boolean {
val parameters = getParameters()
for (i in args.indices) {
val a = args[i]
val p = parameters[i]
if (p.getType().kind != Kind.DYNAMIC && a != p.getType()) return false
if (p.getMatch(a) != a) return false
}
return true
}
Expand All @@ -286,20 +284,19 @@ internal class Env(private val session: Session) {
val parameters = getParameters()
val mapping = arrayOfNulls<Ref.Cast?>(args.size)
for (i in args.indices) {
val arg = args[i]
val a = args[i]
val p = parameters[i]
val m = p.getMatch(a)
when {
// 1. Exact match
arg == p.getType() -> continue
// 2. Match ANY, no coercion needed
p.getType().kind == Kind.DYNAMIC -> continue
// 3. Check for a coercion
else -> when (val coercion = Coercions.get(arg, p.getType())) {
null -> return null // short-circuit
else -> mapping[i] = coercion
}
m == null -> return null
m == a -> continue
else -> mapping[i] = coercion(a, m)
}
}
return this to mapping
}

private fun coercion(arg: PType, target: PType): Ref.Cast {
return Ref.Cast(arg.toCType(), target.toCType(), Ref.Cast.Safety.COERCION, true)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.partiql.planner.internal

import org.partiql.planner.internal.casts.Coercions
import org.partiql.planner.internal.ir.Ref
import org.partiql.planner.internal.typer.CompilerType
import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType
import org.partiql.spi.function.Function
import org.partiql.types.PType
import org.partiql.types.PType.Kind

/**
Expand Down Expand Up @@ -121,42 +121,33 @@ internal object FnResolver {
for (i in args.indices) {
val a = args[i]
val p = parameters[i]
if (a != p.getType()) return false
if (p.getMatch(a) != a) return false
}
return true
}

/**
* Attempt to match arguments to the parameters; return the implicit casts if necessary.
* Attempt to match arguments to the parameters; return the coercions if necessary.
*
* @param args
* @return
*/
private fun Function.match(args: List<CompilerType>): MatchResult? {
val parameters = getParameters()
val mapping = arrayOfNulls<Ref.Cast?>(args.size)
var exactInputTypes: Int = 0
var exactInputTypes = 0
for (i in args.indices) {
val arg = args[i]
val a = args[i]
if (a.kind == Kind.UNKNOWN) {
continue // skip unknown arguments
}
// check match
val p = parameters[i]
val m = p.getMatch(a)
when {
// 1. Exact match
arg == p.getType() -> {
exactInputTypes++
continue
}
// 2. Match ANY parameter, no coercion needed
p.getType().kind == Kind.DYNAMIC -> continue
arg.kind == Kind.UNKNOWN -> continue
// 3. Allow for ANY arguments
arg.kind == Kind.DYNAMIC -> {
mapping[i] = Ref.Cast(arg, p.getType().toCType(), Ref.Cast.Safety.UNSAFE, true)
}
// 4. Check for a coercion
else -> when (val coercion = Coercions.get(arg, p.getType())) {
null -> return null // short-circuit
else -> mapping[i] = coercion
}
m == null -> return null // short-circuit
m == a -> exactInputTypes++
else -> mapping[i] = coercion(a, m)
}
}
return MatchResult(
Expand All @@ -165,6 +156,10 @@ internal object FnResolver {
)
}

private fun coercion(arg: PType, target: PType): Ref.Cast {
return Ref.Cast(arg.toCType(), target.toCType(), Ref.Cast.Safety.COERCION, true)
}

private class MatchResult(
val match: FnMatch.Static,
val numberOfExactInputTypes: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@ import org.partiql.planner.internal.ir.Ref.Cast
import org.partiql.planner.internal.typer.CompilerType
import org.partiql.types.PType
import org.partiql.types.PType.Kind
import org.partiql.value.PartiQLValueExperimental
import org.partiql.value.PartiQLValueType

/**
* A place to model type relationships (for now this is to answer CAST inquiries).
*
* @property types
* @property graph Going with a matrix here (using enum ordinals) as it's simple and avoids walking.
*/
@OptIn(PartiQLValueExperimental::class)
internal class CastTable private constructor(
private val types: Array<Kind>,
private val graph: Array<Array<Status>>,
Expand All @@ -29,8 +26,6 @@ internal class CastTable private constructor(
}
}

private operator fun <T> Array<T>.get(t: PartiQLValueType): T = get(t.ordinal)

/**
* This represents the Y, M, and N in the table listed in SQL:1999 Section 6.22.
*/
Expand All @@ -42,9 +37,7 @@ internal class CastTable private constructor(

companion object {

private val N = Kind.values().size

private operator fun <T> Array<T>.set(t: PartiQLValueType, value: T): Unit = this.set(t.ordinal, value)
private val N = Kind.entries.size

private fun relationships(block: RelationshipBuilder.() -> Unit): Array<Status> {
return with(RelationshipBuilder()) {
Expand All @@ -60,15 +53,15 @@ internal class CastTable private constructor(
*/
@JvmStatic
val partiql: CastTable = run {
val types = Kind.values()
val types = Kind.entries.toTypedArray()
val graph = arrayOfNulls<Array<Status>>(N)
for (type in types) {
// initialize all with empty relationships
graph[type.ordinal] = Array(N) { Status.NO }
}
graph[Kind.DYNAMIC.ordinal] = relationships {
cast(Kind.DYNAMIC)
Kind.values().filterNot { it == Kind.DYNAMIC }.forEach {
Kind.entries.filterNot { it == Kind.DYNAMIC }.forEach {
cast(it)
}
}
Expand Down
Loading
Loading