From 4946ab2e0136c6b8e229aef887a30496134238ee Mon Sep 17 00:00:00 2001 From: Yingtao Liu Date: Wed, 1 Nov 2023 12:37:46 -0700 Subject: [PATCH] runtime type resolution --- partiql-lang/build.gradle.kts | 1 + .../main/kotlin/org/partiql/planner/Header.kt | 2 +- .../org/partiql/planner/PartiQLHeader.kt | 215 +++++++++++++++--- 3 files changed, 190 insertions(+), 28 deletions(-) diff --git a/partiql-lang/build.gradle.kts b/partiql-lang/build.gradle.kts index 7080fc3b70..0c3da19acb 100644 --- a/partiql-lang/build.gradle.kts +++ b/partiql-lang/build.gradle.kts @@ -85,5 +85,6 @@ tasks.processTestResources { tasks.shadowJar { archiveBaseName.set("shadow") + exclude("**/*.kotlin_metadata") archiveClassifier.set("") } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt index 257be92466..399e017a7b 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/Header.kt @@ -43,7 +43,7 @@ public abstract class Header { * For functions, output CREATE FUNCTION statements. */ override fun toString(): String = buildString { - functions.groupBy { it.name }.forEach { + (functions + operators + aggregations).groupBy { it.name }.forEach { appendLine("-- [${it.key}] ---------") appendLine() it.value.forEach { fn -> appendLine(fn) } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt index 5565077c3d..3434355447 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLHeader.kt @@ -105,15 +105,15 @@ object PartiQLHeader : Header() { // OPERATORS - private fun not(): List = listOf(unary("not", BOOL, BOOL)) + private fun not(): List = listOf(unary("not", BOOL, BOOL), unary("not", ANY, ANY)) private fun pos(): List = types.numeric.map { t -> unary("pos", t, t) - } + } + listOf(unary("pos", ANY, ANY)) private fun neg(): List = types.numeric.map { t -> unary("neg", t, t) - } + } + listOf(unary("pos", ANY, ANY)) private fun eq(): List = types.all.map { t -> FunctionSignature.Scalar( @@ -127,55 +127,55 @@ object PartiQLHeader : Header() { private fun ne(): List = types.all.map { t -> binary("ne", BOOL, t, t) - } + } + listOf(binary("ne", ANY, ANY, ANY)) - private fun and(): List = listOf(binary("and", BOOL, BOOL, BOOL)) + private fun and(): List = listOf(binary("and", BOOL, BOOL, BOOL), binary("and", ANY, ANY, ANY)) - private fun or(): List = listOf(binary("or", BOOL, BOOL, BOOL)) + private fun or(): List = listOf(binary("or", BOOL, BOOL, BOOL), binary("or", ANY, ANY, ANY)) private fun lt(): List = types.numeric.map { t -> binary("lt", BOOL, t, t) - } + } + listOf(binary("lt", ANY, ANY, ANY)) private fun lte(): List = types.numeric.map { t -> binary("lte", BOOL, t, t) - } + } + listOf(binary("lte", ANY, ANY, ANY)) private fun gt(): List = types.numeric.map { t -> binary("gt", BOOL, t, t) - } + } + listOf(binary("gt", ANY, ANY, ANY)) private fun gte(): List = types.numeric.map { t -> binary("gte", BOOL, t, t) - } + } + listOf(binary("gte", ANY, ANY, ANY)) private fun plus(): List = types.numeric.map { t -> binary("plus", t, t, t) - } + } + listOf(binary("plus", ANY, ANY, ANY)) private fun minus(): List = types.numeric.map { t -> binary("minus", t, t, t) - } + } + listOf(binary("minus", ANY, ANY, ANY)) private fun times(): List = types.numeric.map { t -> binary("times", t, t, t) - } + } + listOf(binary("times", ANY, ANY, ANY)) private fun div(): List = types.numeric.map { t -> binary("divide", t, t, t) - } + } + listOf(binary("divide", ANY, ANY, ANY)) private fun mod(): List = types.numeric.map { t -> binary("modulo", t, t, t) - } + } + listOf(binary("modulo", ANY, ANY, ANY)) private fun concat(): List = types.text.map { t -> binary("concat", t, t, t) - } + } + listOf(binary("concat", ANY, ANY, ANY)) private fun bitwiseAnd(): List = types.integer.map { t -> binary("bitwise_and", t, t, t) - } + } + listOf(binary("bitwise_and", ANY, ANY, ANY)) // BUILT INTS @@ -223,6 +223,27 @@ object PartiQLHeader : Header() { isNullCall = true, isNullable = false, ), + FunctionSignature.Scalar( + name = "like", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("pattern", ANY), + ), + isNullCall = true, + isNullable = false, + ), + FunctionSignature.Scalar( + name = "like_escape", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("pattern", ANY), + FunctionParameter("escape", ANY), + ), + isNullCall = true, + isNullable = false, + ), ) private fun between(): List = types.numeric.map { t -> @@ -328,7 +349,16 @@ object PartiQLHeader : Header() { ), isNullCall = false, isNullable = true, - ) + ), + FunctionSignature.Scalar( + name = "coalesce", + returns = ANY, + parameters = listOf( + FunctionParameter("values", ANY) + ), + isNullCall = false, + isNullable = true, + ), ) // NULLIF(x, y) @@ -343,7 +373,18 @@ object PartiQLHeader : Header() { isNullCall = true, isNullable = true, ) - } + } + listOf( + FunctionSignature.Scalar( + name = "null_if", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("nullifier", ANY), + ), + isNullCall = true, + isNullable = true, + ) + ) // SUBSTRING (expression, start[, length]?) // SUBSTRINGG(expression from start [FOR length]? ) @@ -371,7 +412,29 @@ object PartiQLHeader : Header() { isNullable = false, ) ) - }.flatten() + }.flatten() + listOf( + FunctionSignature.Scalar( + name = "substring", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("start", ANY), + ), + isNullCall = true, + isNullable = false, + ), + FunctionSignature.Scalar( + name = "substring", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("start", ANY), + FunctionParameter("end", ANY), + ), + isNullCall = true, + isNullable = false, + ) + ) // position (str1, str2) // position (str1 in str2) @@ -386,7 +449,18 @@ object PartiQLHeader : Header() { isNullCall = true, isNullable = false, ) - } + } + listOf( + FunctionSignature.Scalar( + name = "position", + returns = ANY, + parameters = listOf( + FunctionParameter("probe", ANY), + FunctionParameter("value", ANY), + ), + isNullCall = true, + isNullable = false, + ) + ) // trim(str) private fun trim(): List = types.text.map { t -> @@ -399,7 +473,17 @@ object PartiQLHeader : Header() { isNullCall = true, isNullable = false, ) - } + } + listOf( + FunctionSignature.Scalar( + name = "trim", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + ), + isNullCall = true, + isNullable = false, + ) + ) // TODO: We need to add a special form function for TRIM(BOTH FROM value) private fun trimSpecial(): List = types.text.map { t -> @@ -459,7 +543,62 @@ object PartiQLHeader : Header() { isNullable = false, ), ) - }.flatten() + }.flatten() + listOf( + // TRIM(chars FROM value) + // TRIM(both chars from value) + FunctionSignature.Scalar( + name = "trim_chars", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("chars", ANY), + ), + isNullCall = true, + isNullable = false, + ), + // TRIM(LEADING FROM value) + FunctionSignature.Scalar( + name = "trim_leading", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + ), + isNullCall = true, + isNullable = false, + ), + // TRIM(LEADING chars FROM value) + FunctionSignature.Scalar( + name = "trim_leading_chars", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("chars", ANY), + ), + isNullCall = true, + isNullable = false, + ), + // TRIM(TRAILING FROM value) + FunctionSignature.Scalar( + name = "trim_trailing", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + ), + isNullCall = true, + isNullable = false, + ), + // TRIM(TRAILING chars FROM value) + FunctionSignature.Scalar( + name = "trim_trailing_chars", + returns = ANY, + parameters = listOf( + FunctionParameter("value", ANY), + FunctionParameter("chars", ANY), + ), + isNullCall = true, + isNullable = false, + ), + ) // TODO private fun overlay(): List = emptyList() @@ -469,8 +608,8 @@ object PartiQLHeader : Header() { private fun dateAdd(): List { val operators = mutableListOf() - for (type in types.datetime) { - for (field in DatetimeField.values()) { + for (field in DatetimeField.values()) { + for (type in types.datetime) { if (field == DatetimeField.TIMEZONE_HOUR || field == DatetimeField.TIMEZONE_MINUTE) { continue } @@ -486,14 +625,25 @@ object PartiQLHeader : Header() { ) operators.add(signature) } + val anySignature = FunctionSignature.Scalar( + name = "date_diff_${field.name.lowercase()}", + returns = ANY, + parameters = listOf( + FunctionParameter("datetime1", ANY), + FunctionParameter("datetime2", ANY), + ), + isNullCall = true, + isNullable = false, + ) + operators.add(anySignature) } return operators } private fun dateDiff(): List { val operators = mutableListOf() - for (type in types.datetime) { - for (field in DatetimeField.values()) { + for (field in DatetimeField.values()) { + for (type in types.datetime) { if (field == DatetimeField.TIMEZONE_HOUR || field == DatetimeField.TIMEZONE_MINUTE) { continue } @@ -509,6 +659,17 @@ object PartiQLHeader : Header() { ) operators.add(signature) } + val anySignature = FunctionSignature.Scalar( + name = "date_diff_${field.name.lowercase()}", + returns = ANY, + parameters = listOf( + FunctionParameter("datetime1", ANY), + FunctionParameter("datetime2", ANY), + ), + isNullCall = true, + isNullable = false, + ) + operators.add(anySignature) } return operators }