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

Func resolver #1378

Merged
merged 1 commit into from
Feb 26, 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ Thank you to all who have contributed!
## [Unreleased]

### Added
- Added constrained decimal as valid parameter type to functions that take in numeric parameters.

### Changed
- Function resolution logic: Now the function resolver would match all possible candidate(based on if the argument can be coerced to the Signature parameter type). If there are multiple match it will first attempt to pick the one requires the least cast, then pick the function with the highest precedence.

### Deprecated

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.partiql.planner.internal.ir.Agg
import org.partiql.planner.internal.ir.Fn
import org.partiql.planner.internal.ir.Identifier
import org.partiql.planner.internal.ir.Rex
import org.partiql.planner.internal.typer.FnResolver.Companion.compareTo
import org.partiql.types.AnyOfType
import org.partiql.types.NullType
import org.partiql.types.StaticType
Expand Down Expand Up @@ -247,15 +248,28 @@ internal class FnResolver(private val header: Header) {

/**
* Functions are sorted by precedence (which is not rigorously defined/specified at the moment).
*
* This function first attempts to find all possible match for given args
* If there are multiple matches, then
* - return the matches that requires the lowest number of coercion
* - This is to match edges like concat(symbol, symbol) which should return symbol
* but because string has higher precedence,
* we also would have concat(cast(symbol as string), cast(symbol as string))
* added to the map first.
* - return the matches which has the highest argument precedence.
*/
private fun <T : FunctionSignature> match(signatures: List<T>, args: Args): Match<T>? {
val candidates = mutableListOf<Match<T>>()
for (signature in signatures) {
val mapping = match(signature, args)
if (mapping != null) {
return Match(signature, mapping)
candidates.add(Match(signature, mapping))
}
}
return null

// Sorted By is stable, we don't have to resort based on parameter type precedence
candidates.sortBy { it.mapping.filterNotNull().size }
return candidates.firstOrNull()
}

/**
Expand Down Expand Up @@ -288,14 +302,7 @@ internal class FnResolver(private val header: Header) {
}
}
}
// if all elements requires casting, then no match
// because there must be another function definition that requires no casting
return if (mapping.isEmpty() || mapping.contains(null)) {
// we made a match
mapping
} else {
null
}
return mapping
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ internal class TypeLattice private constructor(
INT32,
INT64,
INT,
DECIMAL,
DECIMAL_ARBITRARY,
FLOAT32,
FLOAT64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,15 @@ private fun StaticType.asRuntimeType(): PartiQLValueType = when (this) {
is ListType -> PartiQLValueType.LIST
is SexpType -> PartiQLValueType.SEXP
is DateType -> PartiQLValueType.DATE
is DecimalType -> when (this.precisionScaleConstraint) {
is DecimalType.PrecisionScaleConstraint.Constrained -> PartiQLValueType.DECIMAL
DecimalType.PrecisionScaleConstraint.Unconstrained -> PartiQLValueType.DECIMAL_ARBITRARY
// TODO: Run time decimal type does not model precision scale constraint yet
// despite that we match to Decimal vs Decimal_ARBITRARY (PVT) here
// but when mapping it back to Static Type, (i.e, mapping function return type to Value Type)
// we can only map to Unconstrained decimal (Static Type)
is DecimalType -> {
when (this.precisionScaleConstraint) {
is DecimalType.PrecisionScaleConstraint.Constrained -> PartiQLValueType.DECIMAL
DecimalType.PrecisionScaleConstraint.Unconstrained -> PartiQLValueType.DECIMAL_ARBITRARY
}
}
is FloatType -> PartiQLValueType.FLOAT64
is GraphType -> error("Graph type missing from runtime types")
Expand Down
Loading