diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt index c12e3a3f7..b7e8f70f6 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/compiler/StandardCompiler.kt @@ -369,7 +369,7 @@ internal class StandardCompiler(strategies: List) : PartiQLCompiler { override fun visitCall(rex: RexCall, ctx: Unit): ExprValue { val func = rex.getFunction() val args = rex.getArgs() - val catch = func.parameters.any { it.kind == PType.Kind.DYNAMIC } + val catch = func.parameters.any { it.code() == PType.DYNAMIC } return when (catch) { true -> ExprCall(func, Array(args.size) { i -> compile(args[i], Unit).catch() }) else -> ExprCall(func, Array(args.size) { i -> compile(args[i], Unit) }) diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/helpers/ValueUtility.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/helpers/ValueUtility.kt index de9344cef..08d5ea4cf 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/helpers/ValueUtility.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/helpers/ValueUtility.kt @@ -18,7 +18,7 @@ internal object ValueUtility { */ @JvmStatic fun Datum.isTrue(): Boolean { - return this.type.kind == PType.Kind.BOOL && !this.isNull && !this.isMissing && this.boolean + return this.type.code() == PType.BOOL && !this.isNull && !this.isMissing && this.boolean } @OptIn(PartiQLValueExperimental::class) @@ -50,8 +50,8 @@ internal object ValueUtility { * @throws TypeCheckException if the value's type is not a text type (string, symbol, char) */ fun Datum.getText(): String { - return when (this.type.kind) { - PType.Kind.STRING, PType.Kind.CHAR -> this.string + return when (this.type.code()) { + PType.STRING, PType.CHAR -> this.string else -> throw TypeCheckException("Expected text, but received ${this.type}.") } } @@ -67,12 +67,12 @@ internal object ValueUtility { * @throws TypeCheckException if type is not an integer type */ fun Datum.getBigIntCoerced(): BigInteger { - return when (this.type.kind) { - PType.Kind.TINYINT -> this.byte.toInt().toBigInteger() - PType.Kind.SMALLINT -> this.short.toInt().toBigInteger() - PType.Kind.INTEGER -> this.int.toBigInteger() - PType.Kind.BIGINT -> this.long.toBigInteger() - PType.Kind.NUMERIC -> this.bigInteger + return when (this.type.code()) { + PType.TINYINT -> this.byte.toInt().toBigInteger() + PType.SMALLINT -> this.short.toInt().toBigInteger() + PType.INTEGER -> this.int.toBigInteger() + PType.BIGINT -> this.long.toBigInteger() + PType.NUMERIC -> this.bigInteger else -> throw TypeCheckException() } } @@ -89,12 +89,12 @@ internal object ValueUtility { * @throws TypeCheckException if type is not an integer type */ fun Datum.getInt32Coerced(): Int { - return when (this.type.kind) { - PType.Kind.TINYINT -> this.byte.toInt() - PType.Kind.SMALLINT -> this.short.toInt() - PType.Kind.INTEGER -> this.int - PType.Kind.BIGINT -> this.long.toInt() - PType.Kind.NUMERIC -> this.bigInteger.toInt() + return when (this.type.code()) { + PType.TINYINT -> this.byte.toInt() + PType.SMALLINT -> this.short.toInt() + PType.INTEGER -> this.int + PType.BIGINT -> this.long.toInt() + PType.NUMERIC -> this.bigInteger.toInt() else -> throw TypeCheckException() } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpExclude.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpExclude.kt index 5a1cf8b71..2d48ce430 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpExclude.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpExclude.kt @@ -79,9 +79,9 @@ internal class RelOpExclude( /** * Entry-point to apply exclusions to an arbitrary [Datum]. */ - private fun Datum.exclude(exclusions: List): Datum = when (this.type.kind) { - PType.Kind.ROW, PType.Kind.STRUCT -> this.structExclude(exclusions) - PType.Kind.BAG, PType.Kind.ARRAY -> this.collExclude(exclusions) + private fun Datum.exclude(exclusions: List): Datum = when (this.type.code()) { + PType.ROW, PType.STRUCT -> this.structExclude(exclusions) + PType.BAG, PType.ARRAY -> this.collExclude(exclusions) else -> this } @@ -137,9 +137,9 @@ internal class RelOpExclude( * (i.e. [PartiQLValueType.LIST] or [PartiQLValueType.BAG].). */ private fun newCollValue(type: PType, coll: Iterable): Datum { - return when (type.kind) { - PType.Kind.ARRAY -> Datum.array(coll) - PType.Kind.BAG -> Datum.bag(coll) + return when (type.code()) { + PType.ARRAY -> Datum.array(coll) + PType.BAG -> Datum.bag(coll) else -> error("Collection type required") } } @@ -172,7 +172,7 @@ internal class RelOpExclude( // apply exclusions to subtree var value = element // apply collection index exclusions at deeper levels for lists - if (type.kind == PType.Kind.ARRAY) { + if (type.code() == PType.ARRAY) { branches.getCollIndex(i)?.let { value = value.exclude(it.getItems()) } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIterate.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIterate.kt index b2a1adc2f..d72e3fe87 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIterate.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIterate.kt @@ -18,12 +18,12 @@ internal class RelOpIterate( override fun open(env: Environment) { val r = expr.eval(env.push(Row())) index = 0 - iterator = when (r.type.kind) { - PType.Kind.BAG -> { + iterator = when (r.type.code()) { + PType.BAG -> { close() throw TypeCheckException() } - PType.Kind.ARRAY -> r.iterator() + PType.ARRAY -> r.iterator() else -> { close() throw TypeCheckException() diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIteratePermissive.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIteratePermissive.kt index 1af0b8aaf..ef4d7998f 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIteratePermissive.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpIteratePermissive.kt @@ -18,12 +18,12 @@ internal class RelOpIteratePermissive( override fun open(env: Environment) { val r = expr.eval(env.push(Row())) index = 0 - iterator = when (r.type.kind) { - PType.Kind.BAG -> { + iterator = when (r.type.code()) { + PType.BAG -> { isIndexable = false r.iterator() } - PType.Kind.ARRAY -> r.iterator() + PType.ARRAY -> r.iterator() else -> { isIndexable = false iterator { yield(r) } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScan.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScan.kt index a176fad46..1ac7e74b6 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScan.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScan.kt @@ -16,8 +16,8 @@ internal class RelOpScan( override fun open(env: Environment) { val r = expr.eval(env.push(Row())) - records = when (r.type.kind) { - PType.Kind.ARRAY, PType.Kind.BAG -> RecordValueIterator(r.iterator()) + records = when (r.type.code()) { + PType.ARRAY, PType.BAG -> RecordValueIterator(r.iterator()) else -> { close() throw TypeCheckException("Unexpected type for scan: ${r.type}") diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScanPermissive.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScanPermissive.kt index 85d6306d6..dfc9f7110 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScanPermissive.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpScanPermissive.kt @@ -15,8 +15,8 @@ internal class RelOpScanPermissive( override fun open(env: Environment) { val r = expr.eval(env.push(Row())) - records = when (r.type.kind) { - PType.Kind.BAG, PType.Kind.ARRAY -> RecordValueIterator(r.iterator()) + records = when (r.type.code()) { + PType.BAG, PType.ARRAY -> RecordValueIterator(r.iterator()) else -> iterator { yield(Row(arrayOf(r))) } } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpUnpivot.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpUnpivot.kt index 6f19bc8dd..6c9c5b657 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpUnpivot.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rel/RelOpUnpivot.kt @@ -59,7 +59,7 @@ internal sealed class RelOpUnpivot : ExprRelation { override fun struct(): Datum { val v = expr.eval(env.push(Row())) - if (v.type.kind != PType.Kind.STRUCT && v.type.kind != PType.Kind.ROW) { + if (v.type.code() != PType.STRUCT && v.type.code() != PType.ROW) { throw TypeCheckException() } return v @@ -82,8 +82,8 @@ internal sealed class RelOpUnpivot : ExprRelation { if (v.isMissing) { return Datum.struct(emptyList()) } - return when (v.type.kind) { - PType.Kind.STRUCT, PType.Kind.ROW -> v + return when (v.type.code()) { + PType.STRUCT, PType.ROW -> v else -> Datum.struct(listOf(Field.of("_1", v))) } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/CastTable.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/CastTable.kt index df371d16e..a173d7ad9 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/CastTable.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/CastTable.kt @@ -7,28 +7,28 @@ import org.partiql.errors.DataException import org.partiql.errors.TypeCheckException import org.partiql.spi.value.Datum import org.partiql.types.PType -import org.partiql.types.PType.Kind.ARRAY -import org.partiql.types.PType.Kind.BAG -import org.partiql.types.PType.Kind.BIGINT -import org.partiql.types.PType.Kind.BOOL -import org.partiql.types.PType.Kind.CHAR -import org.partiql.types.PType.Kind.CLOB -import org.partiql.types.PType.Kind.DATE -import org.partiql.types.PType.Kind.DECIMAL -import org.partiql.types.PType.Kind.DOUBLE -import org.partiql.types.PType.Kind.DYNAMIC -import org.partiql.types.PType.Kind.INTEGER -import org.partiql.types.PType.Kind.NUMERIC -import org.partiql.types.PType.Kind.REAL -import org.partiql.types.PType.Kind.SMALLINT -import org.partiql.types.PType.Kind.STRING -import org.partiql.types.PType.Kind.STRUCT -import org.partiql.types.PType.Kind.TIME -import org.partiql.types.PType.Kind.TIMESTAMP -import org.partiql.types.PType.Kind.TIMESTAMPZ -import org.partiql.types.PType.Kind.TIMEZ -import org.partiql.types.PType.Kind.TINYINT -import org.partiql.types.PType.Kind.VARCHAR +import org.partiql.types.PType.ARRAY +import org.partiql.types.PType.BAG +import org.partiql.types.PType.BIGINT +import org.partiql.types.PType.BOOL +import org.partiql.types.PType.CHAR +import org.partiql.types.PType.CLOB +import org.partiql.types.PType.DATE +import org.partiql.types.PType.DECIMAL +import org.partiql.types.PType.DOUBLE +import org.partiql.types.PType.DYNAMIC +import org.partiql.types.PType.INTEGER +import org.partiql.types.PType.NUMERIC +import org.partiql.types.PType.REAL +import org.partiql.types.PType.SMALLINT +import org.partiql.types.PType.STRING +import org.partiql.types.PType.STRUCT +import org.partiql.types.PType.TIME +import org.partiql.types.PType.TIMESTAMP +import org.partiql.types.PType.TIMESTAMPZ +import org.partiql.types.PType.TIMEZ +import org.partiql.types.PType.TINYINT +import org.partiql.types.PType.VARCHAR import org.partiql.value.datetime.DateTimeValue import java.math.BigDecimal import java.math.BigInteger @@ -40,15 +40,15 @@ import java.math.RoundingMode private typealias Cast = (Datum, PType) -> Datum /** - * A two-dimensional array to look up casts by an input [PType.Kind] and target [PType.Kind]. If a [Cast] is found + * A two-dimensional array to look up casts by an input [PType.code] and target [PType.code]. If a [Cast] is found * (aka not null), then the cast is valid and may proceed. If the cast is null, then the cast is not supported between the * two types. * - * The cast table is made fast by using the [ordinal] for indexing. It is up to the [Cast] to provide + * The cast table is made fast by using the [PType.code] for indexing. It is up to the [Cast] to provide * additional logic regarding a type's parameters (aka [PType]). * * @see PType - * @see PType.Kind + * @see PType.code */ private typealias CastLookupTable = Array> @@ -67,10 +67,10 @@ internal object CastTable { if (source.isMissing) { return Datum.missing(target) } - if (target.kind == DYNAMIC) { + if (target.code() == DYNAMIC) { return source } - val cast = _table[source.type.kind.ordinal][target.kind.ordinal] + val cast = _table[source.type.code()][target.code()] ?: throw TypeCheckException("CAST(${source.type} AS $target) is not supported.") return try { cast.invoke(source, target) @@ -79,11 +79,11 @@ internal object CastTable { } } - private val TYPES = PType.Kind.entries.toTypedArray() + private val TYPES = PType.codes() private val SIZE = TYPES.size - private val TYPE_NAME_MAX_LENGTH = TYPES.maxOf { it.name.length } - private val _table: CastLookupTable = Array(PType.Kind.entries.size) { - Array(PType.Kind.entries.size) { + private val TYPE_NAME_MAX_LENGTH = TYPES.maxOf { it.toString().length } + private val _table: CastLookupTable = Array(PType.codes().size) { + Array(PType.codes().size) { null } } @@ -107,10 +107,6 @@ internal object CastTable { registerTime() } - private fun PType.Kind.pad(): String { - return this.name.pad() - } - private fun String.pad(): String { return this.padEnd(TYPE_NAME_MAX_LENGTH, ' ').plus("|") } @@ -124,7 +120,7 @@ internal object CastTable { else -> append("".pad()) } for (targetTypeIndex in 0 until SIZE) { - val typeName = TYPES[targetTypeIndex].name + val typeName = TYPES[targetTypeIndex].toString() val charIndex = typeStringIndex - (TYPE_NAME_MAX_LENGTH - typeName.length) val char = typeName.getOrElse(charIndex) { ' ' } append(' ') @@ -138,7 +134,7 @@ internal object CastTable { appendLine("_".repeat(numberOfSpaces)) // Print content with source type on left side for (sourceTypeIndex in 0 until SIZE) { - append(TYPES[sourceTypeIndex].pad()) + append(TYPES[sourceTypeIndex].toString().pad()) val row = _table[sourceTypeIndex] row.forEach { cell -> if (cell != null) { @@ -497,8 +493,8 @@ internal object CastTable { register(TIMEZ, TIMESTAMPZ) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(DateTimeValue.date(1970, 1, 1), x.time)) } } - private fun register(source: PType.Kind, target: PType.Kind, cast: (Datum, PType) -> Datum) { - _table[source.ordinal][target.ordinal] = cast + private fun register(source: Int, target: Int, cast: (Datum, PType) -> Datum) { + _table[source][target] = cast } /** diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCallDynamic.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCallDynamic.kt index caf6522a7..d75b283c3 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCallDynamic.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCallDynamic.kt @@ -66,16 +66,16 @@ internal class ExprCallDynamic( private fun match(args: List): Candidate? { var exactMatches: Int = -1 var currentMatch: Int? = null - val argFamilies = args.map { family(it.kind) } + val argFamilies = args.map { family(it.code()) } functions.indices.forEach { candidateIndex -> var currentExactMatches = 0 val params = functions[candidateIndex].getInstance(args.toTypedArray())?.parameters ?: return@forEach for (paramIndex in paramIndices) { val argType = args[paramIndex] val paramType = params[paramIndex] - if (paramType.kind == argType.kind) { currentExactMatches++ } // TODO: Convert all functions to use the new modelling, or else we need to only check kinds + if (paramType.code() == argType.code()) { currentExactMatches++ } // TODO: Convert all functions to use the new modelling, or else we need to only check kinds val argFamily = argFamilies[paramIndex] - val paramFamily = family(paramType.kind) + val paramFamily = family(paramType.code()) if (paramFamily != argFamily && argFamily != UNKNOWN && paramFamily != DYNAMIC) { return@forEach } } if (currentExactMatches > exactMatches) { @@ -119,34 +119,35 @@ internal class ExprCallDynamic( * @see family */ @JvmStatic - fun family(type: PType.Kind): CoercionFamily { + fun family(type: Int): CoercionFamily { return when (type) { - PType.Kind.TINYINT -> CoercionFamily.NUMBER - PType.Kind.SMALLINT -> CoercionFamily.NUMBER - PType.Kind.INTEGER -> CoercionFamily.NUMBER - PType.Kind.NUMERIC -> CoercionFamily.NUMBER - PType.Kind.BIGINT -> CoercionFamily.NUMBER - PType.Kind.REAL -> CoercionFamily.NUMBER - PType.Kind.DOUBLE -> CoercionFamily.NUMBER - PType.Kind.DECIMAL -> CoercionFamily.NUMBER - PType.Kind.STRING -> CoercionFamily.STRING - PType.Kind.BOOL -> CoercionFamily.BOOLEAN - PType.Kind.TIMEZ -> CoercionFamily.TIME - PType.Kind.TIME -> CoercionFamily.TIME - PType.Kind.TIMESTAMPZ -> CoercionFamily.TIMESTAMP - PType.Kind.TIMESTAMP -> CoercionFamily.TIMESTAMP - PType.Kind.DATE -> CoercionFamily.DATE - PType.Kind.STRUCT -> CoercionFamily.STRUCTURE - PType.Kind.ARRAY -> CoercionFamily.COLLECTION - PType.Kind.BAG -> CoercionFamily.COLLECTION - PType.Kind.ROW -> CoercionFamily.STRUCTURE - PType.Kind.CHAR -> CoercionFamily.STRING - PType.Kind.VARCHAR -> CoercionFamily.STRING - PType.Kind.DYNAMIC -> DYNAMIC // TODO: REMOVE - PType.Kind.BLOB -> CoercionFamily.BINARY - PType.Kind.CLOB -> CoercionFamily.STRING - PType.Kind.UNKNOWN -> UNKNOWN // TODO: REMOVE - PType.Kind.VARIANT -> UNKNOWN // TODO: HANDLE VARIANT + PType.TINYINT -> CoercionFamily.NUMBER + PType.SMALLINT -> CoercionFamily.NUMBER + PType.INTEGER -> CoercionFamily.NUMBER + PType.NUMERIC -> CoercionFamily.NUMBER + PType.BIGINT -> CoercionFamily.NUMBER + PType.REAL -> CoercionFamily.NUMBER + PType.DOUBLE -> CoercionFamily.NUMBER + PType.DECIMAL -> CoercionFamily.NUMBER + PType.STRING -> CoercionFamily.STRING + PType.BOOL -> CoercionFamily.BOOLEAN + PType.TIMEZ -> CoercionFamily.TIME + PType.TIME -> CoercionFamily.TIME + PType.TIMESTAMPZ -> CoercionFamily.TIMESTAMP + PType.TIMESTAMP -> CoercionFamily.TIMESTAMP + PType.DATE -> CoercionFamily.DATE + PType.STRUCT -> CoercionFamily.STRUCTURE + PType.ARRAY -> CoercionFamily.COLLECTION + PType.BAG -> CoercionFamily.COLLECTION + PType.ROW -> CoercionFamily.STRUCTURE + PType.CHAR -> CoercionFamily.STRING + PType.VARCHAR -> CoercionFamily.STRING + PType.DYNAMIC -> DYNAMIC // TODO: REMOVE + PType.BLOB -> CoercionFamily.BINARY + PType.CLOB -> CoercionFamily.STRING + PType.UNKNOWN -> UNKNOWN // TODO: REMOVE + PType.VARIANT -> UNKNOWN // TODO: HANDLE VARIANT + else -> error("Unknown type: $type") } } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCase.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCase.kt index fd8ec5bae..474f3c4b8 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCase.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCase.kt @@ -21,6 +21,6 @@ internal class ExprCase( } private fun Datum.isTrue(): Boolean { - return this.type.kind == PType.Kind.BOOL && !this.isNull && !this.isMissing && this.boolean + return this.type.code() == PType.BOOL && !this.isNull && !this.isMissing && this.boolean } } diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCaseBranch.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCaseBranch.kt index 478106b10..7ac7f3dc6 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCaseBranch.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprCaseBranch.kt @@ -22,7 +22,7 @@ internal class ExprCaseBranch(value: ExprValue, result: ExprValue) { */ fun eval(env: Environment): Datum? { val v = _value.eval(env) - if (v.type.kind == PType.Kind.BOOL && !v.isNull && !v.isMissing && v.boolean) { + if (v.type.code() == PType.BOOL && !v.isNull && !v.isMissing && v.boolean) { return _result.eval(env) } return null diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprPathIndex.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprPathIndex.kt index 792f0dedb..ff2059734 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprPathIndex.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprPathIndex.kt @@ -14,10 +14,10 @@ internal class ExprPathIndex( override fun eval(env: Environment): Datum { val input = root.eval(env) - val iterator = when (input.type.kind) { - PType.Kind.BAG, - PType.Kind.ARRAY -> input.iterator() - else -> throw TypeCheckException("expected collection, found ${input.type.kind}") + val iterator = when (input.type.code()) { + PType.BAG, + PType.ARRAY -> input.iterator() + else -> throw TypeCheckException("expected collection, found ${input.type.code()}") } // Calculate index diff --git a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprStructPermissive.kt b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprStructPermissive.kt index 3b9c32da9..8d5326863 100644 --- a/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprStructPermissive.kt +++ b/partiql-eval/src/main/kotlin/org/partiql/eval/internal/operator/rex/ExprStructPermissive.kt @@ -31,8 +31,8 @@ internal class ExprStructPermissive(private val fields: List) : if (this.isNull || this.isMissing) { return null } - return when (this.type.kind) { - PType.Kind.STRING, PType.Kind.CHAR -> this.string + return when (this.type.code()) { + PType.STRING, PType.CHAR -> this.string else -> null } } diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/DatumMaterialize.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/DatumMaterialize.kt new file mode 100644 index 000000000..2ca43a060 --- /dev/null +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/DatumMaterialize.kt @@ -0,0 +1,39 @@ +package org.partiql.eval.internal + +import org.partiql.spi.value.Datum +import org.partiql.spi.value.Field +import org.partiql.types.PType + +object DatumMaterialize { + @JvmStatic + fun materialize(datum: Datum): Datum { + val type = datum.type + val kind = type.code() + if (datum.isNull) { + return Datum.nullValue(type) + } + if (datum.isMissing) { + return Datum.missing(type) + } + return when (kind) { + PType.BAG -> { + val elements = datum.map { materialize(it) } + Datum.bag(elements) + } + PType.ARRAY -> { + val elements = datum.map { materialize(it) } + Datum.array(elements) + } + // TODO: Need to create a Datum.row() + PType.STRUCT, PType.ROW -> { + val fieldIter = datum.fields.iterator() + val newFields = mutableListOf() + fieldIter.forEach { + newFields.add(Field.of(it.name, materialize(it.value))) + } + Datum.struct(newFields) + } + else -> datum + } + } +} diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEvaluatorTest.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEvaluatorTest.kt index b8f1960ee..c2535b420 100644 --- a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEvaluatorTest.kt +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PartiQLEvaluatorTest.kt @@ -1276,28 +1276,19 @@ class PartiQLEvaluatorTest { } @Test - @Disabled + // @Disabled fun developmentTest() { - val tc = SuccessTestCase( - input = """ - SELECT VALUE - CASE x + 1 - WHEN NULL THEN 'shouldnt be null' - WHEN MISSING THEN 'shouldnt be missing' - WHEN i THEN 'ONE' - WHEN f THEN 'TWO' - WHEN d THEN 'THREE' - ELSE '?' - END - FROM << i, f, d, null, missing >> AS x - """, - expected = boolValue(true), - globals = listOf( - SuccessTestCase.Global("i", "1"), - SuccessTestCase.Global("f", "2e0"), - SuccessTestCase.Global("d", "3.") + val tc = + SuccessTestCase( + input = "SELECT DISTINCT VALUE t * 100 FROM <<0, 1, 2.0, 3.0>> AS t;", + expected = bagValue( + int32Value(0), + int32Value(100), + decimalValue(BigDecimal.valueOf(2000, 1)), + decimalValue(BigDecimal.valueOf(3000, 1)), + ), + mode = Mode.STRICT() ) - ) tc.run() } diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PlusTest.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PlusTest.kt index d41117887..d020c7749 100644 --- a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PlusTest.kt +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/PlusTest.kt @@ -23,13 +23,13 @@ class PlusTest { fun plusTestCases() = listOf( SuccessTestCase( input = """ - -- DEC(1, 0) + DEC(6, 5) - -- P = 5 + MAX(1, 1) + 1 = 7 + -- DEC(10, 0) + DEC(6, 5) + -- P = 5 + MAX(10, 1) + 1 = 16 -- S = MAX(0, 5) = 5 1 + 2.00000; """.trimIndent(), mode = Mode.STRICT(), - expected = Datum.decimal(BigDecimal.valueOf(300000, 5), 7, 5), + expected = Datum.decimal(BigDecimal.valueOf(300000, 5), 16, 5), jvmEquality = true ), SuccessTestCase( diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/SuccessTestCase.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/SuccessTestCase.kt index 8da22b4d1..32bd8d72b 100644 --- a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/SuccessTestCase.kt +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/SuccessTestCase.kt @@ -69,7 +69,7 @@ public class SuccessTestCase( .catalogs(catalog) .build() val plan = planner.plan(statement, session).plan - val result = compiler.prepare(plan, mode).execute() + val result = DatumMaterialize.materialize(compiler.prepare(plan, mode).execute()) val comparison = when (jvmEquality) { true -> expected == result false -> Datum.comparator().compare(expected, result) == 0 diff --git a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/TypingTestCase.kt b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/TypingTestCase.kt index 1e9d5a646..dda974399 100644 --- a/partiql-eval/src/test/kotlin/org/partiql/eval/internal/TypingTestCase.kt +++ b/partiql-eval/src/test/kotlin/org/partiql/eval/internal/TypingTestCase.kt @@ -47,8 +47,8 @@ public class TypingTestCase @OptIn(PartiQLValueExperimental::class) constructor( var error: Throwable? = null try { val (strictResult, _) = run(mode = Mode.STRICT()) - when (strictResult.type.kind) { - PType.Kind.BAG, PType.Kind.ARRAY -> strictResult.toList() + when (strictResult.type.code()) { + PType.BAG, PType.ARRAY -> strictResult.toList() else -> strictResult } } catch (e: Throwable) { diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/CoercionFamily.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/CoercionFamily.kt index 3fb8ee34e..97806abc3 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/CoercionFamily.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/CoercionFamily.kt @@ -32,34 +32,35 @@ internal enum class CoercionFamily { * @see family */ @JvmStatic - fun family(type: PType.Kind): CoercionFamily { + fun family(type: Int): CoercionFamily { return when (type) { - PType.Kind.TINYINT -> NUMBER - PType.Kind.SMALLINT -> NUMBER - PType.Kind.INTEGER -> NUMBER - PType.Kind.NUMERIC -> NUMBER - PType.Kind.BIGINT -> NUMBER - PType.Kind.REAL -> NUMBER - PType.Kind.DOUBLE -> NUMBER - PType.Kind.DECIMAL -> NUMBER - PType.Kind.STRING -> STRING - PType.Kind.BOOL -> BOOLEAN - PType.Kind.TIMEZ -> TIME - PType.Kind.TIME -> TIME - PType.Kind.TIMESTAMPZ -> TIMESTAMP - PType.Kind.TIMESTAMP -> TIMESTAMP - PType.Kind.DATE -> DATE - PType.Kind.STRUCT -> STRUCTURE - PType.Kind.ARRAY -> COLLECTION - PType.Kind.BAG -> COLLECTION - PType.Kind.ROW -> STRUCTURE - PType.Kind.CHAR -> STRING - PType.Kind.VARCHAR -> STRING - PType.Kind.DYNAMIC -> DYNAMIC // TODO: REMOVE - PType.Kind.BLOB -> BINARY - PType.Kind.CLOB -> STRING - PType.Kind.UNKNOWN -> UNKNOWN // TODO: REMOVE - PType.Kind.VARIANT -> UNKNOWN // TODO: HANDLE VARIANT + PType.TINYINT -> NUMBER + PType.SMALLINT -> NUMBER + PType.INTEGER -> NUMBER + PType.NUMERIC -> NUMBER + PType.BIGINT -> NUMBER + PType.REAL -> NUMBER + PType.DOUBLE -> NUMBER + PType.DECIMAL -> NUMBER + PType.STRING -> STRING + PType.BOOL -> BOOLEAN + PType.TIMEZ -> TIME + PType.TIME -> TIME + PType.TIMESTAMPZ -> TIMESTAMP + PType.TIMESTAMP -> TIMESTAMP + PType.DATE -> DATE + PType.STRUCT -> STRUCTURE + PType.ARRAY -> COLLECTION + PType.BAG -> COLLECTION + PType.ROW -> STRUCTURE + PType.CHAR -> STRING + PType.VARCHAR -> STRING + PType.DYNAMIC -> DYNAMIC // TODO: REMOVE + PType.BLOB -> BINARY + PType.CLOB -> STRING + PType.UNKNOWN -> UNKNOWN // TODO: REMOVE + PType.VARIANT -> UNKNOWN // TODO: HANDLE VARIANT + else -> error("Unknown type: $type") } } @@ -72,13 +73,13 @@ internal enum class CoercionFamily { */ @JvmStatic fun canCoerce(from: PType, to: PType): Boolean { - if (from.kind == PType.Kind.UNKNOWN) { + if (from.code() == PType.UNKNOWN) { return true } - if (to.kind == PType.Kind.DYNAMIC) { + if (to.code() == PType.DYNAMIC) { return true } - return family(from.kind) == family(to.kind) + return family(from.code()) == family(to.code()) } } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnComparator.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnComparator.kt index d33ca80f2..a1ba54183 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnComparator.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnComparator.kt @@ -3,7 +3,6 @@ package org.partiql.planner.internal import org.partiql.spi.function.Function import org.partiql.spi.function.Parameter import org.partiql.types.PType -import org.partiql.types.PType.Kind /** * Function precedence comparator; this is not formally specified. @@ -36,8 +35,8 @@ internal object FnComparator : Comparator { private fun comparePrecedence(t1: PType, t2: PType): Int { if (t1 == t2) return 0 - val p1 = precedence[t1.kind]!! - val p2 = precedence[t2.kind]!! + val p1 = precedence[t1.code()]!! + val p2 = precedence[t2.code()]!! return p1 - p2 } @@ -45,32 +44,32 @@ internal object FnComparator : Comparator { * This simply describes some precedence for ordering functions. * This is not explicitly defined in the PartiQL Specification!! * This does not imply the ability to CAST; this defines function resolution behavior. - * This excludes [Kind.ROW] and [Kind.UNKNOWN]. + * This excludes [PType.ROW] and [PType.UNKNOWN]. */ - private val precedence: Map = listOf( - Kind.BOOL, - Kind.TINYINT, - Kind.SMALLINT, - Kind.INTEGER, - Kind.BIGINT, - Kind.NUMERIC, - Kind.DECIMAL, - Kind.REAL, - Kind.DOUBLE, - Kind.CHAR, - Kind.VARCHAR, - Kind.STRING, - Kind.CLOB, - Kind.BLOB, - Kind.DATE, - Kind.TIME, - Kind.TIMEZ, - Kind.TIMESTAMP, - Kind.TIMESTAMPZ, - Kind.ARRAY, - Kind.BAG, - Kind.ROW, - Kind.STRUCT, - Kind.DYNAMIC, + private val precedence: Map = listOf( + PType.BOOL, + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, + PType.NUMERIC, + PType.DECIMAL, + PType.REAL, + PType.DOUBLE, + PType.CHAR, + PType.VARCHAR, + PType.STRING, + PType.CLOB, + PType.BLOB, + PType.DATE, + PType.TIME, + PType.TIMEZ, + PType.TIMESTAMP, + PType.TIMESTAMPZ, + PType.ARRAY, + PType.BAG, + PType.ROW, + PType.STRUCT, + PType.DYNAMIC, ).mapIndexed { precedence, type -> type to precedence }.toMap() } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnResolver.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnResolver.kt index dc4b5779a..c881a8dd7 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnResolver.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/FnResolver.kt @@ -5,7 +5,6 @@ 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 /** * @@ -48,7 +47,7 @@ internal object FnResolver { } // 2. If there are DYNAMIC arguments, return all candidates - val isDynamic = args.any { it.kind == Kind.DYNAMIC } + val isDynamic = args.any { it.code() == PType.DYNAMIC } if (isDynamic) { val orderedMatches = candidates.sortedWith(FnComparator) return FnMatch.Dynamic(orderedMatches) @@ -130,7 +129,7 @@ internal object FnResolver { val a = args[i] val p = parameters[i] // TODO: Don't use kind! Once all functions use the new modelling, we can just make it p != a. - if (p.kind != a.kind) return false + if (p.code() != a.code()) return false } return true } @@ -148,13 +147,13 @@ internal object FnResolver { var exactInputTypes = 0 for (i in args.indices) { val a = args[i] - if (a.kind == Kind.UNKNOWN) { + if (a.code() == PType.UNKNOWN) { continue // skip unknown arguments } // check match val p = parameters[i] when { - p.kind == a.kind -> exactInputTypes++ // TODO: Don't use kind! Once all functions use the new modelling, we can just make it p == a. + p.code() == a.code() -> exactInputTypes++ // TODO: Don't use kind! Once all functions use the new modelling, we can just make it p == a. else -> mapping[i] = coercion(a, p) ?: return null } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/casts/CastTable.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/casts/CastTable.kt index 5db70c6de..b72500060 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/casts/CastTable.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/casts/CastTable.kt @@ -4,7 +4,6 @@ import org.partiql.planner.internal.ir.Ref 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 /** * A place to model type relationships (for now this is to answer CAST inquiries). @@ -13,13 +12,13 @@ import org.partiql.types.PType.Kind * @property graph Going with a matrix here (using enum ordinals) as it's simple and avoids walking. */ internal class CastTable private constructor( - private val types: Array, + private val types: Array, private val graph: Array>, ) { fun get(operand: PType, target: PType): Cast? { - val i = operand.kind.ordinal - val j = target.kind.ordinal + val i = operand.code() + val j = target.code() return when (graph[i][j]) { Status.YES, Status.MODIFIED -> Cast(CompilerType(operand), CompilerType(target), Ref.Cast.Safety.COERCION, isNullable = true) Status.NO -> null @@ -37,7 +36,7 @@ internal class CastTable private constructor( companion object { - private val N = Kind.entries.size + private val N = PType.codes().size private fun relationships(block: RelationshipBuilder.() -> Unit): Array { return with(RelationshipBuilder()) { @@ -53,240 +52,240 @@ internal class CastTable private constructor( */ @JvmStatic val partiql: CastTable = run { - val types = Kind.entries.toTypedArray() + val types = PType.codes().toTypedArray() val graph = arrayOfNulls>(N) for (type in types) { // initialize all with empty relationships - graph[type.ordinal] = Array(N) { Status.NO } + graph[type] = Array(N) { Status.NO } } - graph[Kind.UNKNOWN.ordinal] = relationships { - PType.Kind.values().map { + graph[PType.UNKNOWN] = relationships { + PType.codes().map { cast(it) } } - graph[Kind.DYNAMIC.ordinal] = relationships { - cast(Kind.DYNAMIC) - Kind.entries.filterNot { it == Kind.DYNAMIC }.forEach { + graph[PType.DYNAMIC] = relationships { + cast(PType.DYNAMIC) + PType.codes().filterNot { it == PType.DYNAMIC }.forEach { cast(it) } } - graph[Kind.BOOL.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.CHAR) - cast(Kind.STRING) - cast(Kind.VARCHAR) + graph[PType.BOOL] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.CHAR) + cast(PType.STRING) + cast(PType.VARCHAR) } - graph[Kind.TINYINT.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) + graph[PType.TINYINT] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) } - graph[Kind.SMALLINT.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.SMALLINT] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.INTEGER.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.INTEGER] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.BIGINT.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.BIGINT] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.NUMERIC.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.NUMERIC] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.DECIMAL.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.DECIMAL] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.REAL.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.REAL] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.DOUBLE.ordinal] = relationships { - cast(Kind.BOOL) - cast(Kind.TINYINT) - cast(Kind.SMALLINT) - cast(Kind.INTEGER) - cast(Kind.BIGINT) - cast(Kind.NUMERIC) - cast(Kind.DECIMAL) - cast(Kind.REAL) - cast(Kind.DOUBLE) - cast(Kind.STRING) - cast(Kind.CHAR) - cast(Kind.VARCHAR) + graph[PType.DOUBLE] = relationships { + cast(PType.BOOL) + cast(PType.TINYINT) + cast(PType.SMALLINT) + cast(PType.INTEGER) + cast(PType.BIGINT) + cast(PType.NUMERIC) + cast(PType.DECIMAL) + cast(PType.REAL) + cast(PType.DOUBLE) + cast(PType.STRING) + cast(PType.CHAR) + cast(PType.VARCHAR) } - graph[Kind.CHAR.ordinal] = relationships { - Kind.values().filterNot { - it in setOf(Kind.BLOB, Kind.UNKNOWN, Kind.DYNAMIC, Kind.ARRAY, Kind.BAG, Kind.ROW) + graph[PType.CHAR] = relationships { + PType.codes().filterNot { + it in setOf(PType.BLOB, PType.UNKNOWN, PType.DYNAMIC, PType.ARRAY, PType.BAG, PType.ROW) }.forEach { cast(it) } } - graph[Kind.STRING.ordinal] = relationships { - Kind.values().filterNot { - it in setOf(Kind.BLOB, Kind.UNKNOWN, Kind.DYNAMIC, Kind.ARRAY, Kind.BAG, Kind.ROW) + graph[PType.STRING] = relationships { + PType.codes().filterNot { + it in setOf(PType.BLOB, PType.UNKNOWN, PType.DYNAMIC, PType.ARRAY, PType.BAG, PType.ROW) }.forEach { cast(it) } } - graph[Kind.VARCHAR.ordinal] = relationships { - Kind.values().filterNot { - it in setOf(Kind.BLOB, Kind.UNKNOWN, Kind.DYNAMIC, Kind.ARRAY, Kind.BAG, Kind.ROW) + graph[PType.VARCHAR] = relationships { + PType.codes().filterNot { + it in setOf(PType.BLOB, PType.UNKNOWN, PType.DYNAMIC, PType.ARRAY, PType.BAG, PType.ROW) }.forEach { cast(it) } } - graph[Kind.CLOB.ordinal] = relationships { - Kind.values().filterNot { - it in setOf(Kind.BLOB, Kind.UNKNOWN, Kind.DYNAMIC, Kind.ARRAY, Kind.BAG, Kind.ROW) + graph[PType.CLOB] = relationships { + PType.codes().filterNot { + it in setOf(PType.BLOB, PType.UNKNOWN, PType.DYNAMIC, PType.ARRAY, PType.BAG, PType.ROW) }.forEach { cast(it) } } - graph[Kind.BLOB.ordinal] = Array(N) { Status.NO } - graph[Kind.DATE.ordinal] = relationships { - cast(Kind.TIMESTAMPZ) - cast(Kind.TIMESTAMP) - cast(Kind.TIMEZ) - cast(Kind.DATE) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) - cast(Kind.CLOB) + graph[PType.BLOB] = Array(N) { Status.NO } + graph[PType.DATE] = relationships { + cast(PType.TIMESTAMPZ) + cast(PType.TIMESTAMP) + cast(PType.TIMEZ) + cast(PType.DATE) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) + cast(PType.CLOB) } - graph[Kind.TIMEZ.ordinal] = relationships { - cast(Kind.TIMESTAMPZ) - cast(Kind.TIMESTAMP) - cast(Kind.TIMEZ) - cast(Kind.TIME) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) - cast(Kind.CLOB) + graph[PType.TIMEZ] = relationships { + cast(PType.TIMESTAMPZ) + cast(PType.TIMESTAMP) + cast(PType.TIMEZ) + cast(PType.TIME) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) + cast(PType.CLOB) } - graph[Kind.TIME.ordinal] = relationships { - cast(Kind.TIMESTAMPZ) - cast(Kind.TIMESTAMP) - cast(Kind.TIMEZ) - cast(Kind.TIME) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) - cast(Kind.CLOB) + graph[PType.TIME] = relationships { + cast(PType.TIMESTAMPZ) + cast(PType.TIMESTAMP) + cast(PType.TIMEZ) + cast(PType.TIME) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) + cast(PType.CLOB) } - graph[Kind.TIMESTAMPZ.ordinal] = relationships { - cast(Kind.TIMESTAMPZ) - cast(Kind.TIMESTAMP) - cast(Kind.DATE) - cast(Kind.TIMEZ) - cast(Kind.TIME) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) - cast(Kind.CLOB) + graph[PType.TIMESTAMPZ] = relationships { + cast(PType.TIMESTAMPZ) + cast(PType.TIMESTAMP) + cast(PType.DATE) + cast(PType.TIMEZ) + cast(PType.TIME) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) + cast(PType.CLOB) } - graph[Kind.TIMESTAMP.ordinal] = relationships { - cast(Kind.TIMESTAMPZ) - cast(Kind.TIMESTAMP) - cast(Kind.DATE) - cast(Kind.TIMEZ) - cast(Kind.TIME) - cast(Kind.STRING) - cast(Kind.VARCHAR) - cast(Kind.CHAR) - cast(Kind.CLOB) + graph[PType.TIMESTAMP] = relationships { + cast(PType.TIMESTAMPZ) + cast(PType.TIMESTAMP) + cast(PType.DATE) + cast(PType.TIMEZ) + cast(PType.TIME) + cast(PType.STRING) + cast(PType.VARCHAR) + cast(PType.CHAR) + cast(PType.CLOB) } - graph[Kind.BAG.ordinal] = relationships { - cast(Kind.BAG) - cast(Kind.ARRAY) + graph[PType.BAG] = relationships { + cast(PType.BAG) + cast(PType.ARRAY) } - graph[Kind.ARRAY.ordinal] = relationships { - cast(Kind.BAG) - cast(Kind.ARRAY) + graph[PType.ARRAY] = relationships { + cast(PType.BAG) + cast(PType.ARRAY) } - graph[Kind.STRUCT.ordinal] = relationships { - cast(Kind.STRUCT) + graph[PType.STRUCT] = relationships { + cast(PType.STRUCT) } CastTable(types, graph.requireNoNulls()) } @@ -301,8 +300,8 @@ internal class CastTable private constructor( fun build() = relationships - fun cast(target: Kind) { - relationships[target.ordinal] = Status.YES + fun cast(target: Int) { + relationships[target] = Status.YES } } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt index 658899c36..e52aea3c9 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/PlanTransform.kt @@ -136,10 +136,10 @@ internal class PlanTransform(private val flags: Set) { override fun visitRexOpCollection(node: IRex.Op.Collection, ctx: PType): Any { val values = node.values.map { visitRex(it, ctx) } val type = RexType(ctx) - return when (ctx.kind) { - PType.Kind.ARRAY -> factory.rexArray(values, type) - PType.Kind.BAG -> factory.rexBag(values, type) - else -> error("Expected bag or array, found ${ctx.kind.name.lowercase()}") + return when (ctx.code()) { + PType.ARRAY -> factory.rexArray(values, type) + PType.BAG -> factory.rexBag(values, type) + else -> error("Expected bag or array, found ${ctx.name().lowercase()}") } } @@ -232,7 +232,7 @@ internal class PlanTransform(private val flags: Set) { val value = node.value // TODO: PartiQLValue doesn't have a finite decimal type, so we need to specially handle this until we remove // PartiQLValue. - if (value is DecimalValue && ctx.kind == PType.Kind.DECIMAL) { + if (value is DecimalValue && ctx.code() == PType.DECIMAL) { return when (val dec = value.value) { null -> factory.rexLit(Datum.nullValue(ctx)) else -> factory.rexLit(Datum.decimal(dec, ctx.precision, ctx.scale)) diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt index f3c054637..fe68632bf 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RelConverter.kt @@ -751,5 +751,5 @@ internal object RelConverter { private val STRUCT: CompilerType = CompilerType(PType.struct()) private val BAG: CompilerType = CompilerType(PType.bag()) private val LIST: CompilerType = CompilerType(PType.array()) - private val INT: CompilerType = CompilerType(PType.numeric()) + private val INT: CompilerType = CompilerType(PType.numeric(38, 0)) } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt index 1bccfab9e..a8dbb5bd9 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/RexConverter.kt @@ -132,7 +132,7 @@ internal object RexConverter { // TODO: PartiQLValue won't be in AST soon is DecimalValue -> { when (val decimal = value.value) { - null -> PType.decimal() + null -> PType.decimal(38, 19) else -> PType.decimal(decimal.precision(), decimal.scale()) } } @@ -942,17 +942,17 @@ internal object RexConverter { // TODO CHAR_VARYING, CHARACTER_LARGE_OBJECT, CHAR_LARGE_OBJECT DataType.CHARACTER, DataType.CHAR -> { val length = type.length ?: 1 - assertGtZeroAndCreate(PType.Kind.CHAR, "length", length, PType::character) + assertGtZeroAndCreate(PType.CHAR, "length", length, PType::character) } DataType.CHARACTER_VARYING, DataType.VARCHAR -> { val length = type.length ?: 1 - assertGtZeroAndCreate(PType.Kind.VARCHAR, "length", length, PType::varchar) + assertGtZeroAndCreate(PType.VARCHAR, "length", length, PType::varchar) } - DataType.CLOB -> assertGtZeroAndCreate(PType.Kind.CLOB, "length", type.length ?: Int.MAX_VALUE, PType::clob) + DataType.CLOB -> assertGtZeroAndCreate(PType.CLOB, "length", type.length ?: Int.MAX_VALUE, PType::clob) DataType.STRING -> PType.string() // // TODO BINARY_LARGE_OBJECT - DataType.BLOB -> assertGtZeroAndCreate(PType.Kind.BLOB, "length", type.length ?: Int.MAX_VALUE, PType::blob) + DataType.BLOB -> assertGtZeroAndCreate(PType.BLOB, "length", type.length ?: Int.MAX_VALUE, PType::blob) // DataType.BIT -> error("BIT is not supported yet.") DataType.BIT_VARYING -> error("BIT VARYING is not supported yet.") @@ -961,17 +961,17 @@ internal object RexConverter { val p = type.precision val s = type.scale when { - p == null && s == null -> PType.decimal() + p == null && s == null -> PType.decimal(38, 0) p != null && s != null -> { - assertParamCompToZero(PType.Kind.NUMERIC, "precision", p, false) - assertParamCompToZero(PType.Kind.NUMERIC, "scale", s, true) + assertParamCompToZero(PType.NUMERIC, "precision", p, false) + assertParamCompToZero(PType.NUMERIC, "scale", s, true) if (s > p) { throw TypeCheckException("Numeric scale cannot be greater than precision.") } PType.decimal(type.precision!!, type.scale!!) } p != null && s == null -> { - assertParamCompToZero(PType.Kind.NUMERIC, "precision", p, false) + assertParamCompToZero(PType.NUMERIC, "precision", p, false) PType.decimal(p, 0) } else -> error("Precision can never be null while scale is specified.") @@ -981,17 +981,17 @@ internal object RexConverter { val p = type.precision val s = type.scale when { - p == null && s == null -> PType.decimal() + p == null && s == null -> PType.decimal(38, 0) p != null && s != null -> { - assertParamCompToZero(PType.Kind.DECIMAL, "precision", p, false) - assertParamCompToZero(PType.Kind.DECIMAL, "scale", s, true) + assertParamCompToZero(PType.DECIMAL, "precision", p, false) + assertParamCompToZero(PType.DECIMAL, "scale", s, true) if (s > p) { throw TypeCheckException("Decimal scale cannot be greater than precision.") } PType.decimal(p, s) } p != null && s == null -> { - assertParamCompToZero(PType.Kind.DECIMAL, "precision", p, false) + assertParamCompToZero(PType.DECIMAL, "precision", p, false) PType.decimal(p, 0) } else -> error("Precision can never be null while scale is specified.") @@ -1009,10 +1009,10 @@ internal object RexConverter { DataType.BOOL -> PType.bool() // DataType.DATE -> PType.date() - DataType.TIME -> assertGtEqZeroAndCreate(PType.Kind.TIME, "precision", type.precision ?: 0, PType::time) - DataType.TIME_WITH_TIME_ZONE -> assertGtEqZeroAndCreate(PType.Kind.TIMEZ, "precision", type.precision ?: 0, PType::timez) - DataType.TIMESTAMP -> assertGtEqZeroAndCreate(PType.Kind.TIMESTAMP, "precision", type.precision ?: 6, PType::timestamp) - DataType.TIMESTAMP_WITH_TIME_ZONE -> assertGtEqZeroAndCreate(PType.Kind.TIMESTAMPZ, "precision", type.precision ?: 6, PType::timestampz) + DataType.TIME -> assertGtEqZeroAndCreate(PType.TIME, "precision", type.precision ?: 0, PType::time) + DataType.TIME_WITH_TIME_ZONE -> assertGtEqZeroAndCreate(PType.TIMEZ, "precision", type.precision ?: 0, PType::timez) + DataType.TIMESTAMP -> assertGtEqZeroAndCreate(PType.TIMESTAMP, "precision", type.precision ?: 6, PType::timestamp) + DataType.TIMESTAMP_WITH_TIME_ZONE -> assertGtEqZeroAndCreate(PType.TIMESTAMPZ, "precision", type.precision ?: 6, PType::timestampz) // DataType.INTERVAL -> error("INTERVAL is not supported yet.") // @@ -1027,12 +1027,12 @@ internal object RexConverter { }.toCType() } - private fun assertGtZeroAndCreate(type: PType.Kind, param: String, value: Int, create: (Int) -> PType): PType { + private fun assertGtZeroAndCreate(type: Int, param: String, value: Int, create: (Int) -> PType): PType { assertParamCompToZero(type, param, value, false) return create.invoke(value) } - private fun assertGtEqZeroAndCreate(type: PType.Kind, param: String, value: Int, create: (Int) -> PType): PType { + private fun assertGtEqZeroAndCreate(type: Int, param: String, value: Int, create: (Int) -> PType): PType { assertParamCompToZero(type, param, value, true) return create.invoke(value) } @@ -1040,7 +1040,7 @@ internal object RexConverter { /** * @param allowZero when FALSE, this asserts that [value] > 0. If TRUE, this asserts that [value] >= 0. */ - private fun assertParamCompToZero(type: PType.Kind, param: String, value: Int, allowZero: Boolean) { + private fun assertParamCompToZero(type: Int, param: String, value: Int, allowZero: Boolean) { val (result, compString) = when (allowZero) { true -> (value >= 0) to "greater than" false -> (value > 0) to "greater than or equal to" @@ -1084,7 +1084,7 @@ internal object RexConverter { private val STRUCT: CompilerType = CompilerType(PType.struct()) private val BAG: CompilerType = CompilerType(PType.bag()) private val LIST: CompilerType = CompilerType(PType.array()) - private val INT: CompilerType = CompilerType(PType.numeric()) + private val INT: CompilerType = CompilerType(PType.numeric(38, 0)) private val INT4: CompilerType = CompilerType(PType.integer()) private val TIMESTAMP: CompilerType = CompilerType(PType.timestamp(6)) } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/CompilerType.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/CompilerType.kt index 0bace18bc..73fbaf223 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/CompilerType.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/CompilerType.kt @@ -2,7 +2,6 @@ package org.partiql.planner.internal.typer import org.partiql.spi.catalog.Identifier import org.partiql.types.PType -import org.partiql.types.PType.Kind /** * This is largely just to show that the planner does not need to use [_delegate] ([PType]) directly. Using an @@ -18,9 +17,8 @@ internal class CompilerType( internal val isNullValue: Boolean = false, // Note: This is an experimental property. internal val isMissingValue: Boolean = false -) : PType { +) : PType(_delegate.code()) { fun getDelegate(): PType = _delegate - override fun getKind(): Kind = _delegate.kind override fun getFields(): MutableCollection { return _delegate.fields.map { field -> when (field) { @@ -78,15 +76,15 @@ internal class CompilerType( } internal fun isNumeric(): Boolean { - return this.kind in setOf( - Kind.INTEGER, - Kind.NUMERIC, - Kind.BIGINT, - Kind.TINYINT, - Kind.SMALLINT, - Kind.REAL, - Kind.DOUBLE, - Kind.DECIMAL, + return this.code() in setOf( + PType.INTEGER, + PType.NUMERIC, + PType.BIGINT, + PType.TINYINT, + PType.SMALLINT, + PType.REAL, + PType.DOUBLE, + PType.DECIMAL, ) } @@ -96,7 +94,7 @@ internal class CompilerType( * @return null when the field definitely does not exist; dynamic when the type cannot be determined */ internal fun getSymbol(field: String): Pair? { - if (this.kind == Kind.STRUCT) { + if (this.code() == PType.STRUCT) { return Identifier.Part.regular(field) to CompilerType(PType.dynamic()) } val fields = this.fields.mapNotNull { diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/DynamicTyper.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/DynamicTyper.kt index c17da6315..3475090f0 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/DynamicTyper.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/DynamicTyper.kt @@ -4,7 +4,6 @@ import org.partiql.planner.internal.ir.Rex import org.partiql.planner.internal.typer.PlanTyper.Companion.anyOf import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType import org.partiql.types.PType -import org.partiql.types.PType.Kind import org.partiql.value.MissingValue import org.partiql.value.PartiQLValue import org.partiql.value.PartiQLValueExperimental @@ -33,7 +32,7 @@ import org.partiql.value.timestampValue /** * Graph of super types for quick lookup because we don't have a tree. */ -internal typealias SuperGraph = Array> +internal typealias SuperGraph = Array> /** * For lack of a better name, this is the "dynamic typer" which implements the typing rules of SQL-99 9.3. @@ -108,24 +107,24 @@ internal class DynamicTyper { @OptIn(PartiQLValueExperimental::class) fun mapping(): Pair?> { var s = supertype ?: return CompilerType(PType.dynamic()) to null - val superTypeBase = s.kind + val superTypeBase = s.code() // If at top supertype, then return union of all accumulated types - if (superTypeBase == Kind.DYNAMIC) { + if (superTypeBase == PType.DYNAMIC) { return anyOf(types)!!.toCType() to null } // If a collection, then return union of all accumulated types as these coercion rules are not defined by SQL. - if (superTypeBase in setOf(Kind.ROW, Kind.STRUCT, Kind.BAG, Kind.ARRAY)) { + if (superTypeBase in setOf(PType.ROW, PType.STRUCT, PType.BAG, PType.ARRAY)) { return anyOf(types)!!.toCType() to null } // Decimal - if (superTypeBase == Kind.DECIMAL) { + if (superTypeBase == PType.DECIMAL) { val type = computeDecimal() if (type != null) { s = type } } // Text - if (superTypeBase in setOf(Kind.CHAR, Kind.VARCHAR, Kind.STRING)) { + if (superTypeBase in setOf(PType.CHAR, PType.VARCHAR, PType.STRING)) { val type = computeText() if (type != null) { s = type @@ -135,7 +134,7 @@ internal class DynamicTyper { // Otherwise, return the supertype along with the coercion mapping val mapping = args.map { when { - it.isLiteralNull() -> Mapping.Replacement(Rex(s, Rex.Op.Lit(nullValue(s.kind)))) + it.isLiteralNull() -> Mapping.Replacement(Rex(s, Rex.Op.Lit(nullValue(s.code())))) it.isLiteralMissing() -> Mapping.Replacement(Rex(s, Rex.Op.Lit(missingValue()))) it.type == s -> Mapping.Coercion(s) else -> null @@ -147,7 +146,7 @@ internal class DynamicTyper { // TODO: Fix the computation of the supertype: https://github.com/partiql/partiql-lang-kotlin/issues/1566 private fun computeDecimal(): CompilerType? { val (precision, scale) = types.fold((0 to 0)) { acc, type -> - if (type.kind != Kind.DECIMAL) { + if (type.code() != PType.DECIMAL) { return null } val precision = Math.max(type.precision, acc.first) @@ -161,19 +160,19 @@ internal class DynamicTyper { var containsString = false var containsVarChar = false val length = types.fold(0) { acc, type -> - if (type.kind !in setOf(Kind.VARCHAR, Kind.CHAR, Kind.STRING)) { + if (type.code() !in setOf(PType.VARCHAR, PType.CHAR, PType.STRING)) { return null } - when (type.kind) { - Kind.STRING -> { + when (type.code()) { + PType.STRING -> { containsString = true Int.MAX_VALUE } - Kind.VARCHAR -> { + PType.VARCHAR -> { containsVarChar = true Math.max(acc, type.length) } - Kind.CHAR -> { + PType.CHAR -> { Math.max(acc, type.length) } else -> error("Received type: $type") @@ -199,12 +198,12 @@ internal class DynamicTyper { return } // Don't bother calculating the new supertype, we've already hit `dynamic`. - if (s.kind == Kind.DYNAMIC) return + if (s.code() == PType.DYNAMIC) return // Lookup and set the new minimum common supertype supertype = when { - type.kind == Kind.DYNAMIC -> type + type.code() == PType.DYNAMIC -> type s == type -> return // skip - else -> graph[s.kind.ordinal][type.kind.ordinal]?.toPType() ?: CompilerType(PType.dynamic()) // lookup, if missing then go to top. + else -> graph[s.code()][type.code()]?.toPType() ?: CompilerType(PType.dynamic()) // lookup, if missing then go to top. } } @@ -217,13 +216,13 @@ internal class DynamicTyper { companion object { @JvmStatic - private val N = Kind.values().size + private val N = PType.codes().size @JvmStatic - private fun edges(vararg edges: Pair): Array { - val arr = arrayOfNulls(N) + private fun edges(vararg edges: Pair): Array { + val arr = arrayOfNulls(N) for (type in edges) { - arr[type.first.ordinal] = type.second + arr[type.first] = type.second } return arr } @@ -236,150 +235,150 @@ internal class DynamicTyper { */ @JvmStatic internal val graph: SuperGraph = run { - val graph = arrayOfNulls>(N) - for (type in Kind.values()) { + val graph = arrayOfNulls>(N) + for (type in PType.codes()) { // initialize all with empty edges - graph[type.ordinal] = arrayOfNulls(N) + graph[type] = arrayOfNulls(N) } - graph[Kind.DYNAMIC.ordinal] = edges() - graph[Kind.BOOL.ordinal] = edges( - Kind.BOOL to Kind.BOOL + graph[PType.DYNAMIC] = edges() + graph[PType.BOOL] = edges( + PType.BOOL to PType.BOOL ) - graph[Kind.TINYINT.ordinal] = edges( - Kind.TINYINT to Kind.TINYINT, - Kind.SMALLINT to Kind.SMALLINT, - Kind.INTEGER to Kind.INTEGER, - Kind.BIGINT to Kind.BIGINT, - Kind.NUMERIC to Kind.NUMERIC, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.TINYINT] = edges( + PType.TINYINT to PType.TINYINT, + PType.SMALLINT to PType.SMALLINT, + PType.INTEGER to PType.INTEGER, + PType.BIGINT to PType.BIGINT, + PType.NUMERIC to PType.NUMERIC, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.SMALLINT.ordinal] = edges( - Kind.TINYINT to Kind.SMALLINT, - Kind.SMALLINT to Kind.SMALLINT, - Kind.INTEGER to Kind.INTEGER, - Kind.BIGINT to Kind.BIGINT, - Kind.NUMERIC to Kind.NUMERIC, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.SMALLINT] = edges( + PType.TINYINT to PType.SMALLINT, + PType.SMALLINT to PType.SMALLINT, + PType.INTEGER to PType.INTEGER, + PType.BIGINT to PType.BIGINT, + PType.NUMERIC to PType.NUMERIC, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.INTEGER.ordinal] = edges( - Kind.TINYINT to Kind.INTEGER, - Kind.SMALLINT to Kind.INTEGER, - Kind.INTEGER to Kind.INTEGER, - Kind.BIGINT to Kind.BIGINT, - Kind.NUMERIC to Kind.NUMERIC, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.INTEGER] = edges( + PType.TINYINT to PType.INTEGER, + PType.SMALLINT to PType.INTEGER, + PType.INTEGER to PType.INTEGER, + PType.BIGINT to PType.BIGINT, + PType.NUMERIC to PType.NUMERIC, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.BIGINT.ordinal] = edges( - Kind.TINYINT to Kind.BIGINT, - Kind.SMALLINT to Kind.BIGINT, - Kind.INTEGER to Kind.BIGINT, - Kind.BIGINT to Kind.BIGINT, - Kind.NUMERIC to Kind.NUMERIC, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.BIGINT] = edges( + PType.TINYINT to PType.BIGINT, + PType.SMALLINT to PType.BIGINT, + PType.INTEGER to PType.BIGINT, + PType.BIGINT to PType.BIGINT, + PType.NUMERIC to PType.NUMERIC, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.NUMERIC.ordinal] = edges( - Kind.TINYINT to Kind.NUMERIC, - Kind.SMALLINT to Kind.NUMERIC, - Kind.INTEGER to Kind.NUMERIC, - Kind.BIGINT to Kind.NUMERIC, - Kind.NUMERIC to Kind.NUMERIC, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.NUMERIC] = edges( + PType.TINYINT to PType.NUMERIC, + PType.SMALLINT to PType.NUMERIC, + PType.INTEGER to PType.NUMERIC, + PType.BIGINT to PType.NUMERIC, + PType.NUMERIC to PType.NUMERIC, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.DECIMAL.ordinal] = edges( - Kind.TINYINT to Kind.DECIMAL, - Kind.SMALLINT to Kind.DECIMAL, - Kind.INTEGER to Kind.DECIMAL, - Kind.BIGINT to Kind.DECIMAL, - Kind.NUMERIC to Kind.DECIMAL, - Kind.DECIMAL to Kind.DECIMAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.DECIMAL] = edges( + PType.TINYINT to PType.DECIMAL, + PType.SMALLINT to PType.DECIMAL, + PType.INTEGER to PType.DECIMAL, + PType.BIGINT to PType.DECIMAL, + PType.NUMERIC to PType.DECIMAL, + PType.DECIMAL to PType.DECIMAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.REAL.ordinal] = edges( - Kind.TINYINT to Kind.REAL, - Kind.SMALLINT to Kind.REAL, - Kind.INTEGER to Kind.REAL, - Kind.BIGINT to Kind.REAL, - Kind.NUMERIC to Kind.REAL, - Kind.DECIMAL to Kind.REAL, - Kind.REAL to Kind.REAL, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.REAL] = edges( + PType.TINYINT to PType.REAL, + PType.SMALLINT to PType.REAL, + PType.INTEGER to PType.REAL, + PType.BIGINT to PType.REAL, + PType.NUMERIC to PType.REAL, + PType.DECIMAL to PType.REAL, + PType.REAL to PType.REAL, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.DOUBLE.ordinal] = edges( - Kind.TINYINT to Kind.DOUBLE, - Kind.SMALLINT to Kind.DOUBLE, - Kind.INTEGER to Kind.DOUBLE, - Kind.BIGINT to Kind.DOUBLE, - Kind.NUMERIC to Kind.DOUBLE, - Kind.DECIMAL to Kind.DOUBLE, - Kind.REAL to Kind.DOUBLE, - Kind.DOUBLE to Kind.DOUBLE, + graph[PType.DOUBLE] = edges( + PType.TINYINT to PType.DOUBLE, + PType.SMALLINT to PType.DOUBLE, + PType.INTEGER to PType.DOUBLE, + PType.BIGINT to PType.DOUBLE, + PType.NUMERIC to PType.DOUBLE, + PType.DECIMAL to PType.DOUBLE, + PType.REAL to PType.DOUBLE, + PType.DOUBLE to PType.DOUBLE, ) - graph[Kind.CHAR.ordinal] = edges( - Kind.CHAR to Kind.CHAR, - Kind.STRING to Kind.STRING, - Kind.VARCHAR to Kind.STRING, - Kind.CLOB to Kind.CLOB, + graph[PType.CHAR] = edges( + PType.CHAR to PType.CHAR, + PType.STRING to PType.STRING, + PType.VARCHAR to PType.STRING, + PType.CLOB to PType.CLOB, ) - graph[Kind.STRING.ordinal] = edges( - Kind.CHAR to Kind.STRING, - Kind.STRING to Kind.STRING, - Kind.VARCHAR to Kind.STRING, - Kind.CLOB to Kind.CLOB, + graph[PType.STRING] = edges( + PType.CHAR to PType.STRING, + PType.STRING to PType.STRING, + PType.VARCHAR to PType.STRING, + PType.CLOB to PType.CLOB, ) - graph[Kind.VARCHAR.ordinal] = edges( - Kind.CHAR to Kind.VARCHAR, - Kind.STRING to Kind.STRING, - Kind.VARCHAR to Kind.VARCHAR, - Kind.CLOB to Kind.CLOB, + graph[PType.VARCHAR] = edges( + PType.CHAR to PType.VARCHAR, + PType.STRING to PType.STRING, + PType.VARCHAR to PType.VARCHAR, + PType.CLOB to PType.CLOB, ) - graph[Kind.BLOB.ordinal] = edges( - Kind.BLOB to Kind.BLOB, + graph[PType.BLOB] = edges( + PType.BLOB to PType.BLOB, ) - graph[Kind.DATE.ordinal] = edges( - Kind.DATE to Kind.DATE, + graph[PType.DATE] = edges( + PType.DATE to PType.DATE, ) - graph[Kind.CLOB.ordinal] = edges( - Kind.CHAR to Kind.CLOB, - Kind.STRING to Kind.CLOB, - Kind.VARCHAR to Kind.CLOB, - Kind.CLOB to Kind.CLOB, + graph[PType.CLOB] = edges( + PType.CHAR to PType.CLOB, + PType.STRING to PType.CLOB, + PType.VARCHAR to PType.CLOB, + PType.CLOB to PType.CLOB, ) - graph[Kind.TIME.ordinal] = edges( - Kind.TIME to Kind.TIME, + graph[PType.TIME] = edges( + PType.TIME to PType.TIME, ) - graph[Kind.TIMEZ.ordinal] = edges( - Kind.TIMEZ to Kind.TIMEZ, + graph[PType.TIMEZ] = edges( + PType.TIMEZ to PType.TIMEZ, ) - graph[Kind.TIMESTAMP.ordinal] = edges( - Kind.TIMESTAMP to Kind.TIMESTAMP, + graph[PType.TIMESTAMP] = edges( + PType.TIMESTAMP to PType.TIMESTAMP, ) - graph[Kind.TIMESTAMPZ.ordinal] = edges( - Kind.TIMESTAMPZ to Kind.TIMESTAMPZ, + graph[PType.TIMESTAMPZ] = edges( + PType.TIMESTAMPZ to PType.TIMESTAMPZ, ) - graph[Kind.ARRAY.ordinal] = edges( - Kind.ARRAY to Kind.ARRAY, - Kind.BAG to Kind.BAG, + graph[PType.ARRAY] = edges( + PType.ARRAY to PType.ARRAY, + PType.BAG to PType.BAG, ) - graph[Kind.BAG.ordinal] = edges( - Kind.ARRAY to Kind.BAG, - Kind.BAG to Kind.BAG, + graph[PType.BAG] = edges( + PType.ARRAY to PType.BAG, + PType.BAG to PType.BAG, ) - graph[Kind.STRUCT.ordinal] = edges( - Kind.STRUCT to Kind.STRUCT, + graph[PType.STRUCT] = edges( + PType.STRUCT to PType.STRUCT, ) - graph[Kind.ROW.ordinal] = edges( - Kind.ROW to Kind.ROW, + graph[PType.ROW] = edges( + PType.ROW to PType.ROW, ) graph.requireNoNulls() } @@ -388,64 +387,68 @@ internal class DynamicTyper { * TODO: We need to update the logic of this whole file. We are currently limited by not using parameters * of types. */ - private fun Kind.toPType(): CompilerType = when (this) { - Kind.BOOL -> PType.bool() - Kind.DYNAMIC -> PType.dynamic() - Kind.TINYINT -> PType.tinyint() - Kind.SMALLINT -> PType.smallint() - Kind.INTEGER -> PType.integer() - Kind.BIGINT -> PType.bigint() - Kind.NUMERIC -> PType.numeric() - Kind.DECIMAL -> PType.decimal() // TODO: To be updated. - Kind.REAL -> PType.real() - Kind.DOUBLE -> PType.doublePrecision() - Kind.CHAR -> PType.character(255) // TODO: To be updated - Kind.VARCHAR -> PType.varchar(255) // TODO: To be updated - Kind.STRING -> PType.string() - Kind.BLOB -> PType.blob(Int.MAX_VALUE) // TODO: To be updated - Kind.CLOB -> PType.clob(Int.MAX_VALUE) // TODO: To be updated - Kind.DATE -> PType.date() - Kind.TIMEZ -> PType.timez(6) // TODO: To be updated - Kind.TIME -> PType.time(6) // TODO: To be updated - Kind.TIMESTAMPZ -> PType.timestampz(6) // TODO: To be updated - Kind.TIMESTAMP -> PType.timestamp(6) // TODO: To be updated - Kind.BAG -> PType.bag() // TODO: To be updated - Kind.ARRAY -> PType.array() // TODO: To be updated - Kind.ROW -> PType.row(emptyList()) // TODO: To be updated - Kind.STRUCT -> PType.struct() // TODO: To be updated - Kind.UNKNOWN -> PType.unknown() // TODO: To be updated - Kind.VARIANT -> TODO("variant in dynamic typer") + private fun Int.toPType(): CompilerType = when (this) { + PType.BOOL -> PType.bool() + PType.DYNAMIC -> PType.dynamic() + PType.TINYINT -> PType.tinyint() + PType.SMALLINT -> PType.smallint() + PType.INTEGER -> PType.integer() + PType.BIGINT -> PType.bigint() + PType.NUMERIC -> PType.numeric(38, 0) // TODO: To be updated + PType.DECIMAL -> PType.decimal(38, 0) // TODO: To be updated. + PType.REAL -> PType.real() + PType.DOUBLE -> PType.doublePrecision() + PType.CHAR -> PType.character(255) // TODO: To be updated + PType.VARCHAR -> PType.varchar(255) // TODO: To be updated + PType.STRING -> PType.string() + PType.BLOB -> PType.blob(Int.MAX_VALUE) // TODO: To be updated + PType.CLOB -> PType.clob(Int.MAX_VALUE) // TODO: To be updated + PType.DATE -> PType.date() + PType.TIMEZ -> PType.timez(6) // TODO: To be updated + PType.TIME -> PType.time(6) // TODO: To be updated + PType.TIMESTAMPZ -> PType.timestampz(6) // TODO: To be updated + PType.TIMESTAMP -> PType.timestamp(6) // TODO: To be updated + PType.BAG -> PType.bag() // TODO: To be updated + PType.ARRAY -> PType.array() // TODO: To be updated + PType.ROW -> PType.row(emptyList()) // TODO: To be updated + PType.STRUCT -> PType.struct() // TODO: To be updated + PType.UNKNOWN -> PType.unknown() // TODO: To be updated + PType.VARIANT -> TODO("variant in dynamic typer") + else -> error("Unknown type: $this") }.toCType() @OptIn(PartiQLValueExperimental::class) - private fun nullValue(kind: Kind): PartiQLValue { + private fun nullValue(kind: Int): PartiQLValue { return when (kind) { - Kind.DYNAMIC -> nullValue() - Kind.BOOL -> boolValue(null) - Kind.TINYINT -> int8Value(null) - Kind.SMALLINT -> int16Value(null) - Kind.INTEGER -> int32Value(null) - Kind.BIGINT -> int64Value(null) - Kind.NUMERIC -> intValue(null) - Kind.DECIMAL -> decimalValue(null) - Kind.REAL -> float32Value(null) - Kind.DOUBLE -> float64Value(null) - Kind.CHAR -> charValue(null) - Kind.VARCHAR -> TODO("No implementation of VAR CHAR") - Kind.STRING -> stringValue(null) - Kind.BLOB -> blobValue(null) - Kind.CLOB -> clobValue(null) - Kind.DATE -> dateValue(null) - Kind.TIMEZ, - Kind.TIME -> timeValue(null) - Kind.TIMESTAMPZ, - Kind.TIMESTAMP -> timestampValue(null) - Kind.BAG -> bagValue(null) - Kind.ARRAY -> listValue(null) - Kind.ROW -> structValue(null) - Kind.STRUCT -> structValue() - Kind.UNKNOWN -> nullValue() - Kind.VARIANT -> TODO("variant in dynamic typer") + PType.DYNAMIC -> nullValue() + PType.BOOL -> boolValue(null) + PType.TINYINT -> int8Value(null) + PType.SMALLINT -> int16Value(null) + PType.INTEGER -> int32Value(null) + PType.BIGINT -> int64Value(null) + PType.NUMERIC -> intValue(null) + PType.DECIMAL -> decimalValue(null) + PType.REAL -> float32Value(null) + PType.DOUBLE -> float64Value(null) + PType.CHAR -> charValue(null) + PType.VARCHAR -> TODO("No implementation of VAR CHAR") + PType.STRING -> stringValue(null) + PType.BLOB -> blobValue(null) + PType.CLOB -> clobValue(null) + PType.DATE -> dateValue(null) + PType.TIMEZ, + PType.TIME -> timeValue(null) + + PType.TIMESTAMPZ, + PType.TIMESTAMP -> timestampValue(null) + + PType.BAG -> bagValue(null) + PType.ARRAY -> listValue(null) + PType.ROW -> structValue(null) + PType.STRUCT -> structValue() + PType.UNKNOWN -> nullValue() + PType.VARIANT -> TODO("variant in dynamic typer") + else -> error("Unknown type: $kind") } } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt index 364769c56..260876cd6 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt @@ -57,7 +57,6 @@ import org.partiql.spi.errors.PError import org.partiql.spi.errors.PErrorListener import org.partiql.types.Field import org.partiql.types.PType -import org.partiql.types.PType.Kind import org.partiql.value.BoolValue import org.partiql.value.MissingValue import org.partiql.value.PartiQLValueExperimental @@ -113,7 +112,7 @@ internal class PlanTyper(private val env: Env, config: Context) { } // Filter out UNKNOWN - unique = unique.filter { it.kind != Kind.UNKNOWN } + unique = unique.filter { it.code() != PType.UNKNOWN } if (unique.size == 0) { return PType.unknown() } else if (unique.size == 1) { @@ -121,23 +120,23 @@ internal class PlanTyper(private val env: Env, config: Context) { } // Collapse Collections - if (unique.all { it.kind == Kind.ARRAY } || - unique.all { it.kind == Kind.BAG } + if (unique.all { it.code() == PType.ARRAY } || + unique.all { it.code() == PType.BAG } ) { - return collapseCollection(unique, unique.first().kind) + return collapseCollection(unique, unique.first().code()) } // Collapse Structs - if (unique.all { it.kind == Kind.ROW }) { + if (unique.all { it.code() == PType.ROW }) { return collapseRows(unique) } return PType.dynamic() } - private fun collapseCollection(collections: Iterable, type: Kind): PType { + private fun collapseCollection(collections: Iterable, type: Int): PType { val typeParam = anyOfLiterals(collections.map { it.typeParameter.toCType() })!! return when (type) { - Kind.ARRAY -> PType.array(typeParam) - Kind.BAG -> PType.array(typeParam) + PType.ARRAY -> PType.array(typeParam) + PType.BAG -> PType.array(typeParam) else -> error("This shouldn't have happened.") } } @@ -230,15 +229,15 @@ internal class PlanTyper(private val env: Env, config: Context) { val kType = PType.string() // Check Root (Dynamic) - if (rex.type.kind == Kind.DYNAMIC) { + if (rex.type.code() == PType.DYNAMIC) { val type = ctx!!.copyWithSchema(listOf(kType, PType.dynamic()).toCType()) return rel(type, op) } // Check Root - val vType = when (rex.type.kind) { - Kind.ROW -> anyOf(rex.type.fields!!.map { it.type }) ?: PType.dynamic() - Kind.STRUCT -> PType.dynamic() + val vType = when (rex.type.code()) { + PType.ROW -> anyOf(rex.type.fields!!.map { it.type }) ?: PType.dynamic() + PType.STRUCT -> PType.dynamic() else -> rex.type } @@ -383,7 +382,7 @@ internal class PlanTyper(private val env: Env, config: Context) { val limit = node.limit.type(input.type.schema, outer, Strategy.GLOBAL) // check types if (limit.type.isNumeric().not()) { - val problem = PErrors.typeUnexpected(null, limit.type, listOf(PType.numeric())) + val problem = PErrors.typeUnexpected(null, limit.type, listOf(PType.numeric(38, 0))) val err = errorRexAndReport(_listener, problem) return rel(input.type, relOpLimit(input, err)) } @@ -401,7 +400,7 @@ internal class PlanTyper(private val env: Env, config: Context) { val offset = node.offset.type(input.type.schema, outer, Strategy.GLOBAL) // check types if (offset.type.isNumeric().not()) { - val problem = PErrors.typeUnexpected(null, offset.type, listOf(PType.numeric())) + val problem = PErrors.typeUnexpected(null, offset.type, listOf(PType.numeric(38, 0))) val err = errorRexAndReport(_listener, problem) return rel(input.type, relOpLimit(input, err)) } @@ -625,18 +624,18 @@ internal class PlanTyper(private val env: Env, config: Context) { val key = visitRex(node.key, node.key.type) // Check Key Type (INT or coercible to INT). TODO: Allow coercions to INT - if (key.type.kind !in setOf(Kind.TINYINT, Kind.SMALLINT, Kind.INTEGER, Kind.BIGINT, Kind.NUMERIC)) { + if (key.type.code() !in setOf(PType.TINYINT, PType.SMALLINT, PType.INTEGER, PType.BIGINT, PType.NUMERIC)) { val problem = PErrors.pathIndexNeverSucceeds(null) return errorRexAndReport(_listener, problem) } // Check if Root is DYNAMIC - if (root.type.kind == Kind.DYNAMIC) { + if (root.type.code() == PType.DYNAMIC) { return Rex(CompilerType(PType.dynamic()), Rex.Op.Path.Index(root, key)) } // Check Root Type LIST - if (root.type.kind != Kind.ARRAY) { + if (root.type.code() != PType.ARRAY) { return errorRexAndReport(_listener, PErrors.pathIndexNeverSucceeds(null)) } @@ -655,17 +654,17 @@ internal class PlanTyper(private val env: Env, config: Context) { val key = visitRex(node.key, node.key.type) // Check Key Type (STRING). TODO: Allow coercions to STRING - if (key.type.kind != Kind.STRING) { + if (key.type.code() != PType.STRING) { return errorRexAndReport(_listener, PErrors.pathKeyNeverSucceeds(null)) } // Check if Root is DYNAMIC - if (root.type.kind == Kind.DYNAMIC) { + if (root.type.code() == PType.DYNAMIC) { return Rex(CompilerType(PType.dynamic()), Rex.Op.Path.Key(root, key)) } // Check Root Type (STRUCT) - if (root.type.kind != Kind.STRUCT && root.type.kind != Kind.ROW) { + if (root.type.code() != PType.STRUCT && root.type.code() != PType.ROW) { return errorRexAndReport(_listener, PErrors.pathKeyNeverSucceeds(null)) } @@ -688,12 +687,12 @@ internal class PlanTyper(private val env: Env, config: Context) { val root = visitRex(node.root, node.root.type) // Check if Root is DYNAMIC - if (root.type.kind == Kind.DYNAMIC) { + if (root.type.code() == PType.DYNAMIC) { return Rex(CompilerType(PType.dynamic()), Rex.Op.Path.Symbol(root, node.key)) } // Check Root Type (STRUCT) - if (root.type.kind != Kind.STRUCT && root.type.kind != Kind.ROW) { + if (root.type.code() != PType.STRUCT && root.type.code() != PType.ROW) { return errorRexAndReport(_listener, PErrors.pathSymbolNeverSucceeds(null)) } @@ -719,7 +718,7 @@ internal class PlanTyper(private val env: Env, config: Context) { * @return null when the field definitely does not exist; dynamic when the type cannot be determined */ private fun CompilerType.getField(field: String, ignoreCase: Boolean): CompilerType? { - if (this.kind == Kind.STRUCT) { + if (this.code() == PType.STRUCT) { return CompilerType(PType.dynamic()) } val fields = this.fields!!.filter { it.name.equals(field, ignoreCase) }.map { it.type }.toSet() @@ -926,7 +925,7 @@ internal class PlanTyper(private val env: Env, config: Context) { * Hence, we permit Static Type BOOL, Static Type NULL, Static Type Missing here. */ private fun canBeBoolean(type: CompilerType): Boolean { - return type.kind == Kind.DYNAMIC || type.kind == Kind.BOOL + return type.code() == PType.DYNAMIC || type.code() == PType.BOOL } /** @@ -956,7 +955,7 @@ internal class PlanTyper(private val env: Env, config: Context) { } override fun visitRexOpCollection(node: Rex.Op.Collection, ctx: CompilerType?): Rex { - if (ctx!!.kind !in setOf(Kind.ARRAY, Kind.BAG)) { + if (ctx!!.code() !in setOf(PType.ARRAY, PType.BAG)) { val problem = PErrors.typeUnexpected(null, ctx, listOf(PType.array(), PType.bag())) return errorRexAndReport(_listener, problem) } @@ -965,9 +964,9 @@ internal class PlanTyper(private val env: Env, config: Context) { 0 -> PType.dynamic() else -> anyOfLiterals(values.map { it.type })!! } - val type = when (ctx.kind) { - Kind.BAG -> PType.bag(t) - Kind.ARRAY -> PType.array(t) + val type = when (ctx.code()) { + PType.BAG -> PType.bag(t) + PType.ARRAY -> PType.array(t) else -> error("This is impossible.") } return rex(CompilerType(type), rexOpCollection(values)) @@ -1026,7 +1025,7 @@ internal class PlanTyper(private val env: Env, config: Context) { * Calculate output type of a row-value subquery. */ private fun visitRexOpSubqueryRow(subquery: Rex.Op.Subquery, cons: CompilerType): Rex { - if (cons.kind != Kind.ROW) { + if (cons.code() != PType.ROW) { error("Subquery with non-SQL SELECT cannot be coerced to a row-value expression. Found constructor type: $cons") } // Do a simple cardinality check for the moment. @@ -1045,10 +1044,10 @@ internal class PlanTyper(private val env: Env, config: Context) { * Calculate output type of a scalar subquery. */ private fun visitRexOpSubqueryScalar(subquery: Rex.Op.Subquery, cons: CompilerType): Rex { - if (cons.kind == Kind.DYNAMIC) { + if (cons.code() == PType.DYNAMIC) { return Rex(PType.dynamic().toCType(), subquery) } - if (cons.kind != Kind.ROW) { + if (cons.code() != PType.ROW) { error("Subquery with non-SQL SELECT cannot be coerced to a scalar. Found constructor type: $cons") } val n = cons.fields!!.size @@ -1131,7 +1130,7 @@ internal class PlanTyper(private val env: Env, config: Context) { } private fun replaceGeneratedTupleUnionArg(node: Rex): Rex? { - if (node.op is Rex.Op.Struct && node.type.kind == Kind.ROW) { + if (node.op is Rex.Op.Struct && node.type.code() == PType.ROW) { return node } val case = node.op as? Rex.Op.Case ?: return null @@ -1147,7 +1146,7 @@ internal class PlanTyper(private val env: Env, config: Context) { return null } val firstBranchResultType = firstBranch.rex.type - if (firstBranchResultType.kind != Kind.ROW) { + if (firstBranchResultType.code() != PType.ROW) { return null } return Rex(firstBranchResultType, firstBranch.rex.op) @@ -1185,14 +1184,14 @@ internal class PlanTyper(private val env: Env, config: Context) { var containsDynamic = false var containsNonStruct = false args.forEach { arg -> - if (arg.kind == Kind.UNKNOWN) { + if (arg.code() == PType.UNKNOWN) { return@forEach } - when (arg.kind) { - Kind.ROW -> fields.addAll(arg.fields!!) - Kind.STRUCT -> structIsOpen = true - Kind.DYNAMIC -> containsDynamic = true - Kind.UNKNOWN -> structIsOpen = true + when (arg.code()) { + PType.ROW -> fields.addAll(arg.fields!!) + PType.STRUCT -> structIsOpen = true + PType.DYNAMIC -> containsDynamic = true + PType.UNKNOWN -> structIsOpen = true else -> containsNonStruct = true } } @@ -1271,9 +1270,9 @@ internal class PlanTyper(private val env: Env, config: Context) { private fun Rel.isOrdered(): Boolean = type.props.contains(Rel.Prop.ORDERED) - private fun getElementTypeForFromSource(fromSourceType: CompilerType): CompilerType = when (fromSourceType.kind) { - Kind.DYNAMIC -> CompilerType(PType.dynamic()) - Kind.BAG, Kind.ARRAY -> fromSourceType.typeParameter + private fun getElementTypeForFromSource(fromSourceType: CompilerType): CompilerType = when (fromSourceType.code()) { + PType.DYNAMIC -> CompilerType(PType.dynamic()) + PType.BAG, PType.ARRAY -> fromSourceType.typeParameter // TODO: Should we emit a warning? else -> fromSourceType } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/Scope.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/Scope.kt index 11d02959b..7c6752c35 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/Scope.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/Scope.kt @@ -10,7 +10,6 @@ import org.partiql.planner.internal.ir.rexOpVarLocal import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType import org.partiql.spi.catalog.Identifier import org.partiql.types.PType -import org.partiql.types.PType.Kind import org.partiql.value.PartiQLValueExperimental import org.partiql.value.stringValue @@ -142,10 +141,10 @@ internal data class Scope( * @return */ private fun CompilerType.containsKey(name: Identifier.Part): Boolean? { - return when (this.kind) { - Kind.ROW -> this.fields.any { name.matches(it.name) } - Kind.STRUCT -> null - Kind.DYNAMIC -> null + return when (this.code()) { + PType.ROW -> this.fields.any { name.matches(it.name) } + PType.STRUCT -> null + PType.DYNAMIC -> null else -> false } } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/TypeUtils.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/TypeUtils.kt index 53f789bf7..1fb9c1ab4 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/TypeUtils.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/TypeUtils.kt @@ -3,7 +3,6 @@ package org.partiql.planner.internal.typer import org.partiql.planner.internal.ir.Rel import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType import org.partiql.types.PType -import org.partiql.types.PType.Kind /** * Applies the given exclusion path to produce the reduced [CompilerType]. [lastStepOptional] indicates if a previous @@ -20,11 +19,11 @@ import org.partiql.types.PType.Kind internal fun CompilerType.exclude(steps: List, lastStepOptional: Boolean = false): CompilerType { val type = this return steps.fold(type) { acc, step -> - when (acc.kind) { - Kind.DYNAMIC -> CompilerType(PType.dynamic()) - Kind.ROW -> acc.excludeStruct(step, lastStepOptional) - Kind.STRUCT -> acc - Kind.ARRAY, Kind.BAG -> acc.excludeCollection(step, lastStepOptional) + when (acc.code()) { + PType.DYNAMIC -> CompilerType(PType.dynamic()) + PType.ROW -> acc.excludeStruct(step, lastStepOptional) + PType.STRUCT -> acc + PType.ARRAY, PType.BAG -> acc.excludeCollection(step, lastStepOptional) else -> acc } } @@ -105,9 +104,9 @@ internal fun CompilerType.excludeCollection(step: Rel.Op.Exclude.Step, lastStepO // the future } } - return when (this.kind) { - Kind.ARRAY -> PType.array(e).toCType() - Kind.BAG -> PType.bag(e).toCType() + return when (this.code()) { + PType.ARRAY -> PType.array(e).toCType() + PType.BAG -> PType.bag(e).toCType() else -> throw IllegalStateException() } } diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt index 0e0b4ad85..42d534ebd 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PartiQLTyperTestBase.kt @@ -17,7 +17,6 @@ import org.partiql.spi.catalog.Table import org.partiql.spi.errors.PError import org.partiql.spi.errors.PErrorListener import org.partiql.types.PType -import org.partiql.types.PType.Kind import org.partiql.types.StaticType import org.partiql.types.fromStaticType import java.util.stream.Stream @@ -114,7 +113,8 @@ abstract class PartiQLTyperTestBase { val result = testingPipeline(statement, testName, metadata, pc) val query = result.plan.getOperation() as Operation.Query val actualType = query.getType().getPType() - assert(actualType == key.expectedType) { + // TODO: The tests need parameter checks + assert(actualType.code() == key.expectedType.code()) { buildString { this.appendLine("expected Type is : ${key.expectedType}") this.appendLine("actual Type is : $actualType") @@ -144,7 +144,7 @@ abstract class PartiQLTyperTestBase { val result = testingPipeline(statement, testName, metadata, pc) val query = result.plan.getOperation() as Operation.Query val actualType = query.getType().getPType() - assert(actualType.kind == Kind.DYNAMIC) { + assert(actualType.code() == PType.DYNAMIC) { buildString { this.appendLine("expected Type is : DYNAMIC") this.appendLine("actual Type is : $actualType") diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt index 32ddd5806..6d6d12f03 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTest.kt @@ -39,7 +39,7 @@ class PlanTyperTest { private val STRING = PType.string().toCType() private val INT4 = PType.integer().toCType() private val DOUBLE_PRECISION = PType.doublePrecision().toCType() - private val DECIMAL = PType.decimal().toCType() + private val DECIMAL = PType.decimal(38, 0).toCType() @OptIn(PartiQLValueExperimental::class) private val LITERAL_STRUCT_1 = rex( diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt index 5116f8b32..13d06bd03 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/PlanTyperTestsPorted.kt @@ -216,7 +216,7 @@ internal class PlanTyperTestsPorted { // TODO: We don't assert on the properties right now. private fun errorsEqual(lhs: PError, rhs: PError): Boolean { - return lhs.code() == rhs.code() && lhs.kind == rhs.kind && lhs.severity == rhs.severity && lhs.location == rhs.location + return lhs.code() == rhs.code() && lhs.code() == rhs.code() && lhs.severity == rhs.severity && lhs.location == rhs.location } // private fun id(vararg parts: Identifier.Symbol): Identifier { @@ -787,7 +787,7 @@ internal class PlanTyperTestsPorted { name = "DECIMAL_ARBITRARY AS DECIMAL", key = key("cast-05"), catalog = "pql", - expected = PType.decimal(), + expected = PType.decimal(38, 0), ), ) @@ -2609,7 +2609,7 @@ internal class PlanTyperTestsPorted { SuccessTestCase( key = PartiQLTest.Key("basics", "case-when-10"), catalog = "pql", - expected = PType.decimal(), + expected = PType.decimal(38, 0), ), SuccessTestCase( key = PartiQLTest.Key("basics", "case-when-11"), @@ -2770,7 +2770,7 @@ internal class PlanTyperTestsPorted { SuccessTestCase( key = PartiQLTest.Key("basics", "case-when-44"), catalog = "pql", - expected = PType.decimal() + expected = PType.decimal(38, 0) ), SuccessTestCase( key = PartiQLTest.Key("basics", "case-when-45"), @@ -2893,22 +2893,22 @@ internal class PlanTyperTestsPorted { SuccessTestCase( key = PartiQLTest.Key("basics", "coalesce-02"), catalog = "pql", - expected = PType.decimal() + expected = PType.decimal(38, 0) ), SuccessTestCase( key = PartiQLTest.Key("basics", "coalesce-03"), catalog = "pql", - expected = PType.decimal() + expected = PType.decimal(38, 0) ), SuccessTestCase( key = PartiQLTest.Key("basics", "coalesce-04"), catalog = "pql", - expected = PType.decimal() + expected = PType.decimal(38, 0) ), SuccessTestCase( key = PartiQLTest.Key("basics", "coalesce-05"), catalog = "pql", - expected = PType.decimal() + expected = PType.decimal(38, 0) ), SuccessTestCase( key = PartiQLTest.Key("basics", "coalesce-06"), @@ -3291,8 +3291,8 @@ internal class PlanTyperTestsPorted { PType.row( Field.of("a", PType.decimal(2, 1)), Field.of("c", PType.bigint()), - Field.of("s", PType.decimal(38, 0)), // TODO: Check this - Field.of("m", PType.decimal(38, 0)), + Field.of("s", PType.decimal(38, 19)), // TODO: Check this + Field.of("m", PType.decimal(38, 19)), ) ), ), @@ -3630,18 +3630,18 @@ internal class PlanTyperTestsPorted { """.trimIndent(), expected = PType.bag( PType.row( - Field.of("a", PType.decimal()), + Field.of("a", PType.decimal(38, 0)), Field.of("count_star", PType.bigint()), Field.of("count_a", PType.bigint()), Field.of("count_b", PType.bigint()), - Field.of("sum_a", PType.decimal()), - Field.of("sum_b", PType.decimal()), - Field.of("min_a", PType.decimal()), - Field.of("min_b", PType.decimal()), - Field.of("max_a", PType.decimal()), - Field.of("max_b", PType.decimal()), - Field.of("avg_a", PType.decimal()), - Field.of("avg_b", PType.decimal()), + Field.of("sum_a", PType.decimal(38, 0)), + Field.of("sum_b", PType.decimal(38, 0)), + Field.of("min_a", PType.decimal(38, 0)), + Field.of("min_b", PType.decimal(38, 0)), + Field.of("max_a", PType.decimal(38, 0)), + Field.of("max_b", PType.decimal(38, 0)), + Field.of("avg_a", PType.decimal(38, 0)), + Field.of("avg_b", PType.decimal(38, 0)), ) ), ) @@ -4340,7 +4340,7 @@ internal class PlanTyperTestsPorted { query = "SELECT * FROM pets LIMIT '5'", expected = TABLE_AWS_DDB_PETS, problemHandler = assertProblemExists( - PErrors.typeUnexpected(null, PType.string(), listOf(PType.numeric())) + PErrors.typeUnexpected(null, PType.string(), listOf(PType.numeric(38, 0))) ) ), SuccessTestCase( @@ -4357,7 +4357,7 @@ internal class PlanTyperTestsPorted { query = "SELECT * FROM pets LIMIT 1 OFFSET '5'", expected = TABLE_AWS_DDB_PETS, problemHandler = assertProblemExists( - PErrors.typeUnexpected(null, PType.string(), listOf(PType.numeric())) + PErrors.typeUnexpected(null, PType.string(), listOf(PType.numeric(38, 0))) ) ), SuccessTestCase( diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/operator/OpBitwiseAndTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/operator/OpBitwiseAndTest.kt index 93ec9815e..8987afcad 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/operator/OpBitwiseAndTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/typer/operator/OpBitwiseAndTest.kt @@ -33,9 +33,9 @@ class OpBitwiseAndTest : PartiQLTyperTestBase() { val arg0 = args.first() val arg1 = args[1] val output = when { - arg0 !in allIntPType && arg1 !in allIntPType -> PType.numeric() - arg0 in allIntPType && arg1 !in allIntPType -> PType.numeric() - arg0 !in allIntPType && arg1 in allIntPType -> PType.numeric() + arg0 !in allIntPType && arg1 !in allIntPType -> PType.numeric(38, 0) + arg0 in allIntPType && arg1 !in allIntPType -> PType.numeric(38, 0) + arg0 !in allIntPType && arg1 in allIntPType -> PType.numeric(38, 0) arg0 == arg1 -> arg1 castTablePType(arg1, arg0) == CastType.COERCION -> arg0 castTablePType(arg0, arg1) == CastType.COERCION -> arg1 diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/util/Utils.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/util/Utils.kt index 070d36696..c52bacf40 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/util/Utils.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/util/Utils.kt @@ -72,10 +72,10 @@ val allBooleanPType = setOf( PType.bool() ) -val allIntPType = setOf(PType.tinyint(), PType.smallint(), PType.integer(), PType.bigint(), PType.numeric()) +val allIntPType = setOf(PType.tinyint(), PType.smallint(), PType.integer(), PType.bigint(), PType.numeric(38, 0)) val allNumberPType = allIntPType + setOf( - PType.decimal(), + PType.decimal(38, 19), PType.real(), PType.doublePrecision(), ) @@ -280,37 +280,37 @@ val castTablePType: ((PType, PType) -> CastType) = { from, to -> // Ref.Cast.Safety.EXPLICIT -> CastType.EXPLICIT // } // } - val fromKind = from.kind + val fromKind = from.code() when (fromKind) { - PType.Kind.DYNAMIC -> CastType.UNSAFE - PType.Kind.BLOB -> when (to.kind) { - PType.Kind.BLOB -> CastType.COERCION + PType.DYNAMIC -> CastType.UNSAFE + PType.BLOB -> when (to.code()) { + PType.BLOB -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.BOOL -> when (to.kind) { - PType.Kind.BOOL, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE, PType.Kind.INTEGER, PType.Kind.TINYINT, PType.Kind.SMALLINT, PType.Kind.BIGINT, PType.Kind.NUMERIC -> CastType.COERCION - PType.Kind.STRING -> CastType.COERCION + PType.BOOL -> when (to.code()) { + PType.BOOL, PType.DECIMAL, PType.REAL, PType.DOUBLE, PType.INTEGER, PType.TINYINT, PType.SMALLINT, PType.BIGINT, PType.NUMERIC -> CastType.COERCION + PType.STRING -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.CLOB -> when (to.kind) { - PType.Kind.CLOB -> CastType.COERCION + PType.CLOB -> when (to.code()) { + PType.CLOB -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.BAG -> when (to.kind) { - PType.Kind.BAG -> CastType.COERCION + PType.BAG -> when (to.code()) { + PType.BAG -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.ARRAY -> when (to.kind) { - PType.Kind.BAG -> CastType.COERCION + PType.ARRAY -> when (to.code()) { + PType.BAG -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.DATE -> when (to.kind) { - PType.Kind.DATE -> CastType.COERCION + PType.DATE -> when (to.code()) { + PType.DATE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.DECIMAL -> { - when (val toKind = to.kind) { - PType.Kind.DECIMAL -> { + PType.DECIMAL -> { + when (val toKind = to.code()) { + PType.DECIMAL -> { val toPrecision = to.precision val toScale = to.scale val fromPrecision = from.precision @@ -319,70 +319,73 @@ val castTablePType: ((PType, PType) -> CastType) = { from, to -> CastType.COERCION } else CastType.EXPLICIT } - PType.Kind.REAL -> CastType.COERCION - PType.Kind.DOUBLE -> CastType.COERCION - PType.Kind.INTEGER -> CastType.EXPLICIT + PType.REAL -> CastType.COERCION + PType.DOUBLE -> CastType.COERCION + PType.INTEGER -> CastType.EXPLICIT else -> CastType.UNSAFE } } - PType.Kind.REAL -> when (to.kind) { - PType.Kind.REAL -> CastType.COERCION - PType.Kind.DOUBLE -> CastType.COERCION + PType.REAL -> when (to.code()) { + PType.REAL -> CastType.COERCION + PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.TINYINT -> when (to.kind) { - PType.Kind.TINYINT, PType.Kind.SMALLINT, PType.Kind.INTEGER, PType.Kind.BIGINT, PType.Kind.NUMERIC, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE -> CastType.COERCION + PType.TINYINT -> when (to.code()) { + PType.TINYINT, PType.SMALLINT, PType.INTEGER, PType.BIGINT, PType.NUMERIC, PType.DECIMAL, PType.REAL, PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.SMALLINT -> when (to.kind) { - PType.Kind.SMALLINT, PType.Kind.INTEGER, PType.Kind.BIGINT, PType.Kind.NUMERIC, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE -> CastType.COERCION + PType.SMALLINT -> when (to.code()) { + PType.SMALLINT, PType.INTEGER, PType.BIGINT, PType.NUMERIC, PType.DECIMAL, PType.REAL, PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.INTEGER -> when (to.kind) { - PType.Kind.INTEGER, PType.Kind.BIGINT, PType.Kind.NUMERIC, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE -> CastType.COERCION + PType.INTEGER -> when (to.code()) { + PType.INTEGER, PType.BIGINT, PType.NUMERIC, PType.DECIMAL, PType.REAL, PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.BIGINT -> when (to.kind) { - PType.Kind.BIGINT, PType.Kind.NUMERIC, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE -> CastType.COERCION + PType.BIGINT -> when (to.code()) { + PType.BIGINT, PType.NUMERIC, PType.DECIMAL, PType.REAL, PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.STRING -> when (to.kind) { - PType.Kind.STRING, PType.Kind.CLOB -> CastType.COERCION + PType.STRING -> when (to.code()) { + PType.STRING, PType.CLOB -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.STRUCT -> when (to.kind) { - PType.Kind.STRUCT -> CastType.COERCION + PType.STRUCT -> when (to.code()) { + PType.STRUCT -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.TIME, PType.Kind.TIMEZ -> when (to.kind) { - PType.Kind.TIME, PType.Kind.TIMEZ -> CastType.COERCION + PType.TIME, PType.TIMEZ -> when (to.code()) { + PType.TIME, PType.TIMEZ -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.TIMESTAMP, PType.Kind.TIMESTAMPZ -> when (to.kind) { - PType.Kind.TIMESTAMP, PType.Kind.TIMESTAMPZ -> CastType.COERCION + PType.TIMESTAMP, PType.TIMESTAMPZ -> when (to.code()) { + PType.TIMESTAMP, PType.TIMESTAMPZ -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.NUMERIC -> when (to.kind) { - PType.Kind.NUMERIC, PType.Kind.DECIMAL, PType.Kind.REAL, PType.Kind.DOUBLE -> CastType.COERCION + PType.NUMERIC -> when (to.code()) { + PType.NUMERIC, PType.DECIMAL, PType.REAL, PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.DOUBLE -> when (to.kind) { - PType.Kind.DOUBLE -> CastType.COERCION + PType.DOUBLE -> when (to.code()) { + PType.DOUBLE -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.CHAR -> when (to.kind) { - PType.Kind.CHAR, PType.Kind.VARCHAR, PType.Kind.STRING, PType.Kind.CLOB -> CastType.COERCION + PType.CHAR -> when (to.code()) { + PType.CHAR, PType.VARCHAR, PType.STRING, PType.CLOB -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.VARCHAR -> when (to.kind) { - PType.Kind.VARCHAR, PType.Kind.STRING, PType.Kind.CLOB -> CastType.COERCION + PType.VARCHAR -> when (to.code()) { + PType.VARCHAR, PType.STRING, PType.CLOB -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.ROW -> when (to.kind) { - PType.Kind.ROW, PType.Kind.STRUCT -> CastType.COERCION + PType.ROW -> when (to.code()) { + PType.ROW, PType.STRUCT -> CastType.COERCION else -> CastType.UNSAFE } - PType.Kind.UNKNOWN -> CastType.UNSAFE - PType.Kind.VARIANT -> TODO() + PType.UNKNOWN -> CastType.UNSAFE + PType.VARIANT -> TODO() + else -> { + error("Unknown type: $fromKind") + } } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java b/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java index 538e30619..0f3647a8c 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable; import org.partiql.errors.DataException; import org.partiql.types.PType; -import org.partiql.value.DecimalValue; import org.partiql.value.PartiQL; import org.partiql.value.PartiQLValue; import org.partiql.value.PartiQLValueType; @@ -24,6 +23,31 @@ import java.util.Iterator; import java.util.Objects; +import static org.partiql.types.PType.DYNAMIC; +import static org.partiql.types.PType.BOOL; +import static org.partiql.types.PType.TINYINT; +import static org.partiql.types.PType.SMALLINT; +import static org.partiql.types.PType.INTEGER; +import static org.partiql.types.PType.BIGINT; +import static org.partiql.types.PType.NUMERIC; +import static org.partiql.types.PType.DECIMAL; +import static org.partiql.types.PType.REAL; +import static org.partiql.types.PType.DOUBLE; +import static org.partiql.types.PType.CHAR; +import static org.partiql.types.PType.STRING; +import static org.partiql.types.PType.BLOB; +import static org.partiql.types.PType.CLOB; +import static org.partiql.types.PType.DATE; +import static org.partiql.types.PType.TIME; +import static org.partiql.types.PType.TIMEZ; +import static org.partiql.types.PType.TIMESTAMP; +import static org.partiql.types.PType.TIMESTAMPZ; +import static org.partiql.types.PType.ARRAY; +import static org.partiql.types.PType.BAG; +import static org.partiql.types.PType.ROW; +import static org.partiql.types.PType.STRUCT; +import static org.partiql.types.PType.UNKNOWN; + /** * This is an EXPERIMENTAL representation of a value in PartiQL's type system. The intention of this modeling is to * provide a layer of indirection between PartiQL's type semantics and Java's type semantics. @@ -75,11 +99,10 @@ default boolean isMissing() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#STRING}, - * {@link PartiQLValueType#SYMBOL}, - * {@link PartiQLValueType#CHAR} + * {@link PType#STRING}, + * {@link PType#CHAR} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -91,9 +114,9 @@ default String getString() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#BOOL} + * {@link PType#BOOL} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -107,11 +130,10 @@ default boolean getBoolean() { * ! ! ! EXPERIMENTAL ! ! ! This is an experimental API under development by the PartiQL maintainers. *

* @return the underlying value applicable to the types: - * {@link PartiQLValueType#BINARY}, - * {@link PartiQLValueType#BLOB}, - * {@link PartiQLValueType#CLOB} + * {@link PType#BLOB}, + * {@link PType#CLOB} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -127,10 +149,9 @@ default byte[] getBytes() { /** * ! ! ! EXPERIMENTAL ! ! ! This is an experimental API under development by the PartiQL maintainers. * @return the underlying value applicable to the types: - * {@link PartiQLValueType#BYTE}, - * {@link PartiQLValueType#INT8} + * {@link PType#TINYINT} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -144,9 +165,9 @@ default byte getByte() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#DATE}. + * {@link PType#DATE}. * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -158,9 +179,9 @@ default org.partiql.value.datetime.Date getDate() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#TIME} + * {@link PType#TIME} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -172,9 +193,9 @@ default Time getTime() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#TIMESTAMP}. + * {@link PType#TIMESTAMP}. * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -187,9 +208,9 @@ default Timestamp getTimestamp() { /** * ! ! ! EXPERIMENTAL ! ! ! This is an experimental API under development by the PartiQL maintainers. * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INTERVAL}. + * TODO * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -203,9 +224,9 @@ default long getInterval() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INT16} + * {@link PType#SMALLINT} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -216,9 +237,9 @@ default short getShort() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INT32} + * {@link PType#INTEGER} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -229,9 +250,9 @@ default int getInt() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INT64} + * {@link PType#BIGINT} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -242,9 +263,9 @@ default long getLong() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INT} + * {@link PType#INTEGER} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -256,9 +277,9 @@ default BigInteger getBigInteger() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#FLOAT32} + * {@link PType#REAL} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -269,9 +290,9 @@ default float getFloat() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#FLOAT64} + * {@link PType#DOUBLE} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -282,10 +303,9 @@ default double getDouble() { /** * @return the underlying value applicable to the types: - * {@link PartiQLValueType#DECIMAL}, - * {@link PartiQLValueType#DECIMAL_ARBITRARY} + * {@link PType#DECIMAL} * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -298,8 +318,8 @@ default BigDecimal getBigDecimal() { /** * @return the elements of either bags/lists; returns the fields' values if the type is a struct. * @throws UnsupportedOperationException if this operation is invoked on a value that is not of the following - * types: {@link PartiQLValueType#BAG}, {@link PartiQLValueType#LIST}, and - * {@link PartiQLValueType#STRUCT}. + * types: {@link PType#BAG}, {@link PType#ARRAY}, and + * {@link PType#STRUCT}. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. */ @@ -310,9 +330,9 @@ default Iterator iterator() { } /** - * @return the underlying values applicable to the type {@link PartiQLValueType#STRUCT}. + * @return the underlying values applicable to the type {@link PType#STRUCT}. * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -323,10 +343,10 @@ default Iterator getFields() { } /** - * @return the underlying value applicable to the type {@link PartiQLValueType#STRUCT} and requested field name. This + * @return the underlying value applicable to the type {@link PType#STRUCT} and requested field name. This * is a case-sensitive lookup. * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -336,10 +356,10 @@ default Datum get(@NotNull String name) { } /** - * @return the underlying value applicable to the type {@link PartiQLValueType#STRUCT} and requested field name. This + * @return the underlying value applicable to the type {@link PType#STRUCT} and requested field name. This * is a case-insensitive lookup. * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method + * {@link #getType()}; for example, if {@link #getType()} returns a {@link PType#INTEGER}, then this method * will throw this exception upon invocation. * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that * {@link #isNull()} returns false before attempting to invoke this method. @@ -387,7 +407,7 @@ default PartiQLValue toPartiQLValue() { if (this.isMissing()) { return PartiQL.missingValue(); } - switch (type.getKind()) { + switch (type.code()) { case BOOL: return this.isNull() ? PartiQL.boolValue(null) : PartiQL.boolValue(this.getBoolean()); case TINYINT: @@ -607,8 +627,9 @@ static Datum doublePrecision(double value) { } @NotNull + @Deprecated static Datum decimal(@NotNull BigDecimal value) { - return new DatumDecimal(value, PType.decimal()); + return new DatumDecimal(value, PType.decimal(38, 0)); } @NotNull diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumBigInteger.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumBigInteger.java index 3d82aec16..a81449e2b 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumBigInteger.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumBigInteger.java @@ -13,7 +13,7 @@ class DatumBigInteger implements Datum { @NotNull private final BigInteger _value; - private final static PType _type = PType.numeric(); + private final static PType _type = PType.numeric(38, 0); DatumBigInteger(@NotNull BigInteger value) { _value = value; diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumCollection.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumCollection.java index fb2612c63..b225e91c9 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumCollection.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumCollection.java @@ -9,8 +9,8 @@ * This shall always be package-private (internal). *

* This is specifically for: - * {@link PType.Kind#ARRAY}, - * {@link PType.Kind#BAG} + * {@link PType#ARRAY}, + * {@link PType#BAG} */ class DatumCollection implements Datum { diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumComparator.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumComparator.java index e77953bed..29f781ec9 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumComparator.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumComparator.java @@ -13,10 +13,36 @@ import java.util.Map; import java.util.function.Supplier; +import static org.partiql.types.PType.ARRAY; +import static org.partiql.types.PType.BAG; +import static org.partiql.types.PType.BIGINT; +import static org.partiql.types.PType.BLOB; +import static org.partiql.types.PType.BOOL; +import static org.partiql.types.PType.CHAR; +import static org.partiql.types.PType.CLOB; +import static org.partiql.types.PType.DATE; +import static org.partiql.types.PType.DECIMAL; +import static org.partiql.types.PType.DOUBLE; +import static org.partiql.types.PType.DYNAMIC; +import static org.partiql.types.PType.INTEGER; +import static org.partiql.types.PType.NUMERIC; +import static org.partiql.types.PType.REAL; +import static org.partiql.types.PType.SMALLINT; +import static org.partiql.types.PType.STRING; +import static org.partiql.types.PType.STRUCT; +import static org.partiql.types.PType.TIME; +import static org.partiql.types.PType.TIMESTAMP; +import static org.partiql.types.PType.TIMESTAMPZ; +import static org.partiql.types.PType.TIMEZ; +import static org.partiql.types.PType.TINYINT; +import static org.partiql.types.PType.UNKNOWN; +import static org.partiql.types.PType.VARCHAR; +import static org.partiql.types.PType.ROW; + /** * This class allows for the comparison between two {@link Datum}s. This is internally implemented by constructing * a comparison table, where each cell contains a reference to a {@link DatumComparison} to compute the comparison. - * The table's rows and columns are indexed by the {@link PType.Kind#ordinal()}. The first dimension matches the + * The table's rows and columns are indexed by the {@link PType#code()}. The first dimension matches the * left-hand-side's type of {@link #compare(Datum lhs, Datum rhs)}. The second dimension matches the right-hand-side's * type of {@link #compare(Datum lhs, Datum rhs)}. As such, this implementation allows for O(1) comparison of scalars. */ @@ -29,7 +55,7 @@ abstract class DatumComparator implements Comparator { private static final int GREATER = 1; @NotNull - private static final PType.Kind[] TYPE_KINDS = PType.Kind.values(); + private static final int[] TYPE_KINDS = PType.codes(); private static final int TYPE_KINDS_LENGTH = TYPE_KINDS.length; @@ -43,7 +69,7 @@ abstract class DatumComparator implements Comparator { *

*/ @NotNull - private static final Map TYPE_PRECEDENCE = initializeTypePrecedence(); + private static final Map TYPE_PRECEDENCE = initializeTypePrecedence(); /** *

@@ -88,8 +114,8 @@ public int compare(Datum lhs, Datum rhs) { } // Invoke the Comparison Table - int lhsKind = lhs.getType().getKind().ordinal(); - int rhsKind = rhs.getType().getKind().ordinal(); + int lhsKind = lhs.getType().code(); + int rhsKind = rhs.getType().code(); return COMPARISON_TABLE[lhsKind][rhsKind].apply(lhs, rhs, this); } @@ -136,46 +162,45 @@ int rhsUnknown() { * @see #TYPE_PRECEDENCE */ @NotNull - @SuppressWarnings("deprecation") - private static Map initializeTypePrecedence() { - Map precedence = new HashMap<>(); + private static Map initializeTypePrecedence() { + Map precedence = new HashMap<>(); // Boolean Type - precedence.put(PType.Kind.BOOL, 0); + precedence.put(BOOL, 0); // Number Types - precedence.put(PType.Kind.TINYINT, 1); - precedence.put(PType.Kind.SMALLINT, 1); - precedence.put(PType.Kind.INTEGER, 1); - precedence.put(PType.Kind.BIGINT, 1); - precedence.put(PType.Kind.NUMERIC, 1); - precedence.put(PType.Kind.DECIMAL, 1); - precedence.put(PType.Kind.REAL, 1); - precedence.put(PType.Kind.DOUBLE, 1); + precedence.put(TINYINT, 1); + precedence.put(SMALLINT, 1); + precedence.put(INTEGER, 1); + precedence.put(BIGINT, 1); + precedence.put(NUMERIC, 1); + precedence.put(DECIMAL, 1); + precedence.put(REAL, 1); + precedence.put(DOUBLE, 1); // Date Type - precedence.put(PType.Kind.DATE, 2); + precedence.put(DATE, 2); // Time Type - precedence.put(PType.Kind.TIMEZ, 3); - precedence.put(PType.Kind.TIME, 3); + precedence.put(TIMEZ, 3); + precedence.put(TIME, 3); // Timestamp Types - precedence.put(PType.Kind.TIMESTAMPZ, 4); - precedence.put(PType.Kind.TIMESTAMP, 4); + precedence.put(TIMESTAMPZ, 4); + precedence.put(TIMESTAMP, 4); // Text Types - precedence.put(PType.Kind.CHAR, 5); - precedence.put(PType.Kind.VARCHAR, 5); - precedence.put(PType.Kind.STRING, 5); + precedence.put(CHAR, 5); + precedence.put(PType.VARCHAR, 5); + precedence.put(STRING, 5); // LOB Types - precedence.put(PType.Kind.CLOB, 6); - precedence.put(PType.Kind.BLOB, 6); + precedence.put(CLOB, 6); + precedence.put(BLOB, 6); // Array Type - precedence.put(PType.Kind.ARRAY, 7); + precedence.put(ARRAY, 7); // Tuple Type - precedence.put(PType.Kind.ROW, 9); - precedence.put(PType.Kind.STRUCT, 9); + precedence.put(PType.ROW, 9); + precedence.put(STRUCT, 9); // Bag Type - precedence.put(PType.Kind.BAG, 10); + precedence.put(BAG, 10); // OTHER - precedence.put(PType.Kind.DYNAMIC, 100); - precedence.put(PType.Kind.UNKNOWN, 100); - precedence.put(PType.Kind.VARIANT, 100); + precedence.put(DYNAMIC, 100); + precedence.put(UNKNOWN, 100); + precedence.put(PType.VARIANT, 100); return precedence; } @@ -188,16 +213,15 @@ private static Map initializeTypePrecedence() { * need to have their JVM primitives extracted before making comparison judgements. * * @return the 2D comparison table - * @see #initializeComparatorArray(PType.Kind) + * @see #initializeComparatorArray(int) * @see #fillIntComparator(DatumComparison[]) */ - @SuppressWarnings("deprecation") private static DatumComparison[][] initializeComparators() { // Initialize Table DatumComparison[][] table = new DatumComparison[TYPE_KINDS_LENGTH][TYPE_KINDS_LENGTH]; for (int i = 0; i < TYPE_KINDS_LENGTH; i++) { @SuppressWarnings("ConstantConditions") - PType.Kind kind = TYPE_KINDS[i]; + int kind = TYPE_KINDS[i]; DatumComparison[] row = initializeComparatorArray(kind); table[i] = row; switch (kind) { @@ -269,85 +293,85 @@ private static DatumComparison[][] initializeComparators() { return table; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillTinyIntComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> Byte.compare(self.getByte(), tinyInt.getByte()); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> Short.compare(self.getByte(), smallInt.getShort()); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> Integer.compare(self.getByte(), intNum.getInt()); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> Long.compare(self.getByte(), bigInt.getLong()); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getByte()).compareTo(intArbitrary.getBigInteger()); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getByte(), real.getFloat())); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getByte(), doublePrecision.getDouble())); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> BigDecimal.valueOf(self.getByte()).compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> Byte.compare(self.getByte(), tinyInt.getByte()); + comps[SMALLINT] = (self, smallInt, comp) -> Short.compare(self.getByte(), smallInt.getShort()); + comps[INTEGER] = (self, intNum, comp) -> Integer.compare(self.getByte(), intNum.getInt()); + comps[BIGINT] = (self, bigInt, comp) -> Long.compare(self.getByte(), bigInt.getLong()); + comps[NUMERIC] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getByte()).compareTo(intArbitrary.getBigInteger()); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getByte(), real.getFloat())); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getByte(), doublePrecision.getDouble())); + comps[DECIMAL] = (self, decimal, comp) -> BigDecimal.valueOf(self.getByte()).compareTo(decimal.getBigDecimal()); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillSmallIntComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> Short.compare(self.getShort(), tinyInt.getByte()); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> Short.compare(self.getShort(), smallInt.getShort()); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> Integer.compare(self.getShort(), intNum.getInt()); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> Long.compare(self.getShort(), bigInt.getLong()); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getShort()).compareTo(intArbitrary.getBigInteger()); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getShort(), real.getFloat())); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getShort(), doublePrecision.getDouble())); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> BigDecimal.valueOf(self.getShort()).compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> Short.compare(self.getShort(), tinyInt.getByte()); + comps[SMALLINT] = (self, smallInt, comp) -> Short.compare(self.getShort(), smallInt.getShort()); + comps[INTEGER] = (self, intNum, comp) -> Integer.compare(self.getShort(), intNum.getInt()); + comps[BIGINT] = (self, bigInt, comp) -> Long.compare(self.getShort(), bigInt.getLong()); + comps[NUMERIC] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getShort()).compareTo(intArbitrary.getBigInteger()); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getShort(), real.getFloat())); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getShort(), doublePrecision.getDouble())); + comps[DECIMAL] = (self, decimal, comp) -> BigDecimal.valueOf(self.getShort()).compareTo(decimal.getBigDecimal()); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillIntComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> Integer.compare(self.getInt(), tinyInt.getByte()); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> Integer.compare(self.getInt(), smallInt.getShort()); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> Integer.compare(self.getInt(), intNum.getInt()); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> Long.compare(self.getInt(), bigInt.getLong()); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getInt()).compareTo(intArbitrary.getBigInteger()); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getInt(), real.getFloat())); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getInt(), doublePrecision.getDouble())); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> BigDecimal.valueOf(self.getInt()).compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> Integer.compare(self.getInt(), tinyInt.getByte()); + comps[SMALLINT] = (self, smallInt, comp) -> Integer.compare(self.getInt(), smallInt.getShort()); + comps[INTEGER] = (self, intNum, comp) -> Integer.compare(self.getInt(), intNum.getInt()); + comps[BIGINT] = (self, bigInt, comp) -> Long.compare(self.getInt(), bigInt.getLong()); + comps[NUMERIC] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getInt()).compareTo(intArbitrary.getBigInteger()); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getInt(), real.getFloat())); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getInt(), doublePrecision.getDouble())); + comps[DECIMAL] = (self, decimal, comp) -> BigDecimal.valueOf(self.getInt()).compareTo(decimal.getBigDecimal()); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillBigIntComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> Long.compare(self.getLong(), tinyInt.getByte()); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> Long.compare(self.getLong(), smallInt.getShort()); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> Long.compare(self.getLong(), intNum.getInt()); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> Long.compare(self.getLong(), bigInt.getLong()); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getLong()).compareTo(intArbitrary.getBigInteger()); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getLong(), real.getFloat())); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getLong(), doublePrecision.getDouble())); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> BigDecimal.valueOf(self.getLong()).compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> Long.compare(self.getLong(), tinyInt.getByte()); + comps[SMALLINT] = (self, smallInt, comp) -> Long.compare(self.getLong(), smallInt.getShort()); + comps[INTEGER] = (self, intNum, comp) -> Long.compare(self.getLong(), intNum.getInt()); + comps[BIGINT] = (self, bigInt, comp) -> Long.compare(self.getLong(), bigInt.getLong()); + comps[NUMERIC] = (self, intArbitrary, comp) -> BigInteger.valueOf(self.getLong()).compareTo(intArbitrary.getBigInteger()); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> Float.compare(self.getLong(), real.getFloat())); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> Double.compare(self.getLong(), doublePrecision.getDouble())); + comps[DECIMAL] = (self, decimal, comp) -> BigDecimal.valueOf(self.getLong()).compareTo(decimal.getBigDecimal()); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillIntArbitraryComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(tinyInt.getByte())); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(smallInt.getShort())); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(intNum.getInt())); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(bigInt.getLong())); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> self.getBigInteger().compareTo(intArbitrary.getBigInteger()); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> new BigDecimal(self.getBigInteger()).compareTo(BigDecimal.valueOf(real.getFloat()))); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> new BigDecimal(self.getBigInteger()).compareTo(BigDecimal.valueOf(doublePrecision.getDouble()))); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> new BigDecimal(self.getBigInteger()).compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(tinyInt.getByte())); + comps[SMALLINT] = (self, smallInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(smallInt.getShort())); + comps[INTEGER] = (self, intNum, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(intNum.getInt())); + comps[BIGINT] = (self, bigInt, comp) -> self.getBigInteger().compareTo(BigInteger.valueOf(bigInt.getLong())); + comps[NUMERIC] = (self, intArbitrary, comp) -> self.getBigInteger().compareTo(intArbitrary.getBigInteger()); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> new BigDecimal(self.getBigInteger()).compareTo(BigDecimal.valueOf(real.getFloat()))); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> new BigDecimal(self.getBigInteger()).compareTo(BigDecimal.valueOf(doublePrecision.getDouble()))); + comps[DECIMAL] = (self, decimal, comp) -> new BigDecimal(self.getBigInteger()).compareTo(decimal.getBigDecimal()); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillRealComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), tinyInt.getByte())); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), smallInt.getShort())); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), intNum.getInt())); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), bigInt.getLong())); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), intArbitrary.getBigInteger().floatValue())); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubles(self.getFloat(), real.getFloat(), () -> Float.compare(self.getFloat(), real.getFloat())); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> { + comps[TINYINT] = (self, tinyInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), tinyInt.getByte())); + comps[SMALLINT] = (self, smallInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), smallInt.getShort())); + comps[INTEGER] = (self, intNum, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), intNum.getInt())); + comps[BIGINT] = (self, bigInt, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), bigInt.getLong())); + comps[NUMERIC] = (self, intArbitrary, comp) -> compareDoubleLhs(self.getFloat(), () -> Float.compare(self.getFloat(), intArbitrary.getBigInteger().floatValue())); + comps[REAL] = (self, real, comp) -> compareDoubles(self.getFloat(), real.getFloat(), () -> Float.compare(self.getFloat(), real.getFloat())); + comps[DOUBLE] = (self, doublePrecision, comp) -> { float selfFlt = self.getFloat(); double otherDbl = doublePrecision.getDouble(); return compareDoubles(selfFlt, otherDbl, () -> Double.compare(selfFlt, otherDbl)); }; - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> compareDoubleLhs(self.getFloat(), () -> BigDecimal.valueOf(self.getFloat()).compareTo(decimal.getBigDecimal())); + comps[DECIMAL] = (self, decimal, comp) -> compareDoubleLhs(self.getFloat(), () -> BigDecimal.valueOf(self.getFloat()).compareTo(decimal.getBigDecimal())); return comps; } @@ -445,106 +469,112 @@ private static int compareDoubleRhs(double rhs, Supplier comparison) { return comparison.get(); } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillDoubleComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), tinyInt.getByte())); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), smallInt.getShort())); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), intNum.getInt())); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), bigInt.getLong())); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), intArbitrary.getBigInteger().doubleValue())); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> { + comps[TINYINT] = (self, tinyInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), tinyInt.getByte())); + comps[SMALLINT] = (self, smallInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), smallInt.getShort())); + comps[INTEGER] = (self, intNum, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), intNum.getInt())); + comps[BIGINT] = (self, bigInt, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), bigInt.getLong())); + comps[NUMERIC] = (self, intArbitrary, comp) -> compareDoubleLhs(self.getDouble(), () -> Double.compare(self.getDouble(), intArbitrary.getBigInteger().doubleValue())); + comps[REAL] = (self, real, comp) -> { double selfDbl = self.getDouble(); float otherFlt = real.getFloat(); return compareDoubles(selfDbl, otherFlt, () -> Double.compare(selfDbl, otherFlt)); }; - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubles(self.getDouble(), doublePrecision.getDouble(), () -> Double.compare(self.getDouble(), doublePrecision.getDouble())); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> compareDoubleLhs(self.getDouble(), () -> BigDecimal.valueOf(self.getDouble()).compareTo(decimal.getBigDecimal())); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubles(self.getDouble(), doublePrecision.getDouble(), () -> Double.compare(self.getDouble(), doublePrecision.getDouble())); + comps[DECIMAL] = (self, decimal, comp) -> compareDoubleLhs(self.getDouble(), () -> BigDecimal.valueOf(self.getDouble()).compareTo(decimal.getBigDecimal())); return comps; } - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillDecimalComparator(DatumComparison[] comps) { - comps[PType.Kind.TINYINT.ordinal()] = (self, tinyInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(tinyInt.getByte())); - comps[PType.Kind.SMALLINT.ordinal()] = (self, smallInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(smallInt.getShort())); - comps[PType.Kind.INTEGER.ordinal()] = (self, intNum, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(intNum.getInt())); - comps[PType.Kind.BIGINT.ordinal()] = (self, bigInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(bigInt.getLong())); - comps[PType.Kind.NUMERIC.ordinal()] = (self, intArbitrary, comp) -> self.getBigDecimal().compareTo(new BigDecimal(intArbitrary.getBigInteger())); - comps[PType.Kind.REAL.ordinal()] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> self.getBigDecimal().compareTo(BigDecimal.valueOf(real.getFloat()))); - comps[PType.Kind.DOUBLE.ordinal()] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> self.getBigDecimal().compareTo(BigDecimal.valueOf(doublePrecision.getDouble()))); - comps[PType.Kind.DECIMAL.ordinal()] = (self, decimal, comp) -> self.getBigDecimal().compareTo(decimal.getBigDecimal()); + comps[TINYINT] = (self, tinyInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(tinyInt.getByte())); + comps[SMALLINT] = (self, smallInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(smallInt.getShort())); + comps[INTEGER] = (self, intNum, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(intNum.getInt())); + comps[BIGINT] = (self, bigInt, comp) -> self.getBigDecimal().compareTo(BigDecimal.valueOf(bigInt.getLong())); + comps[NUMERIC] = (self, intArbitrary, comp) -> self.getBigDecimal().compareTo(new BigDecimal(intArbitrary.getBigInteger())); + comps[REAL] = (self, real, comp) -> compareDoubleRhs(real.getFloat(), () -> self.getBigDecimal().compareTo(BigDecimal.valueOf(real.getFloat()))); + comps[DOUBLE] = (self, doublePrecision, comp) -> compareDoubleRhs(doublePrecision.getDouble(), () -> self.getBigDecimal().compareTo(BigDecimal.valueOf(doublePrecision.getDouble()))); + comps[DECIMAL] = (self, decimal, comp) -> self.getBigDecimal().compareTo(decimal.getBigDecimal()); return comps; } + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillDateComparator(DatumComparison[] comps) { - comps[PType.Kind.DATE.ordinal()] = (self, date, comp) -> self.getDate().compareTo(date.getDate()); + comps[DATE] = (self, date, comp) -> self.getDate().compareTo(date.getDate()); return comps; } /** - * Used for both {@link PType.Kind#TIME} and {@link PType.Kind#TIMEZ} + * Used for both {@link PType#TIME} and {@link PType#TIMEZ} * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillTimeComparator(DatumComparison[] comps) { - comps[PType.Kind.TIME.ordinal()] = (self, time, comp) -> self.getTime().compareTo(time.getTime()); - comps[PType.Kind.TIMEZ.ordinal()] = (self, time, comp) -> self.getTime().compareTo(time.getTime()); + comps[TIME] = (self, time, comp) -> self.getTime().compareTo(time.getTime()); + comps[TIMEZ] = (self, time, comp) -> self.getTime().compareTo(time.getTime()); return comps; } /** - * Used for both {@link PType.Kind#TIMESTAMP} and {@link PType.Kind#TIMESTAMPZ} + * Used for both {@link PType#TIMESTAMP} and {@link PType#TIMESTAMPZ} * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillTimestampComparator(DatumComparison[] comps) { - comps[PType.Kind.TIMESTAMPZ.ordinal()] = (self, timestamp, comp) -> self.getTimestamp().compareTo(timestamp.getTimestamp()); - comps[PType.Kind.TIMESTAMP.ordinal()] = (self, timestamp, comp) -> self.getTimestamp().compareTo(timestamp.getTimestamp()); + comps[TIMESTAMPZ] = (self, timestamp, comp) -> self.getTimestamp().compareTo(timestamp.getTimestamp()); + comps[TIMESTAMP] = (self, timestamp, comp) -> self.getTimestamp().compareTo(timestamp.getTimestamp()); return comps; } /** - * Used for {@link PType.Kind#STRING}, {@link PType.Kind#CHAR}, {@link PType.Kind#VARCHAR}. + * Used for {@link PType#STRING}, {@link PType#CHAR}, {@link PType#VARCHAR}. * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillStringComparator(DatumComparison[] comps) { - comps[PType.Kind.STRING.ordinal()] = (self, string, comp) -> self.getString().compareTo(string.getString()); - comps[PType.Kind.CHAR.ordinal()] = (self, string, comp) -> self.getString().compareTo(string.getString()); - comps[PType.Kind.VARCHAR.ordinal()] = (self, string, comp) -> self.getString().compareTo(string.getString()); + comps[STRING] = (self, string, comp) -> self.getString().compareTo(string.getString()); + comps[CHAR] = (self, string, comp) -> self.getString().compareTo(string.getString()); + comps[PType.VARCHAR] = (self, string, comp) -> self.getString().compareTo(string.getString()); return comps; } /** * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillListComparator(DatumComparison[] comps) { - comps[PType.Kind.ARRAY.ordinal()] = (self, list, comp) -> compareOrdered(self.iterator(), list.iterator(), comp); + comps[ARRAY] = (self, list, comp) -> compareOrdered(self.iterator(), list.iterator(), comp); return comps; } /** * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillBagComparator(DatumComparison[] comps) { - comps[PType.Kind.BAG.ordinal()] = DatumComparator::compareUnordered; + comps[BAG] = DatumComparator::compareUnordered; return comps; } /** * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillBooleanComparator(DatumComparison[] comps) { - comps[PType.Kind.BOOL.ordinal()] = (self, bool, comp) -> Boolean.compare(self.getBoolean(), bool.getBoolean()); + comps[BOOL] = (self, bool, comp) -> Boolean.compare(self.getBoolean(), bool.getBoolean()); return comps; } @@ -575,28 +605,28 @@ public Byte next() { } /** - * Used for both {@link PType.Kind#BLOB} and {@link PType.Kind#CLOB}. + * Used for both {@link PType#BLOB} and {@link PType#CLOB}. * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue", "deprecation"}) private static DatumComparison[] fillLobComparator(DatumComparison[] comps) { - comps[PType.Kind.BLOB.ordinal()] = (self, blob, comp) -> compareArray(self.getBytes(), blob.getBytes()); - comps[PType.Kind.CLOB.ordinal()] = (self, blob, comp) -> compareArray(self.getBytes(), blob.getBytes()); + comps[BLOB] = (self, blob, comp) -> compareArray(self.getBytes(), blob.getBytes()); + comps[CLOB] = (self, blob, comp) -> compareArray(self.getBytes(), blob.getBytes()); return comps; } /** - * Used for both {@link PType.Kind#STRUCT} and {@link PType.Kind#ROW}. + * Used for both {@link PType#STRUCT} and {@link PType#ROW}. * @param comps the array of {@link DatumComparison} to modify. Each {@link DatumComparison} is indexed by the other - * {@link Datum}'s {@link PType.Kind#ordinal()}. + * {@link Datum}'s {@link PType#code()}. * @return the modified array */ - @SuppressWarnings("deprecation") + @SuppressWarnings({"UnusedReturnValue"}) private static DatumComparison[] fillStructComparator(DatumComparison[] comps) { - comps[PType.Kind.STRUCT.ordinal()] = (self, struct, comp) -> compareUnordered(new DatumFieldIterable(self), new DatumFieldIterable(struct), new FieldComparator(comp)); - comps[PType.Kind.ROW.ordinal()] = (self, row, comp) -> compareOrdered(self.getFields(), row.getFields(), new FieldComparator(comp)); + comps[STRUCT] = (self, struct, comp) -> compareUnordered(new DatumFieldIterable(self), new DatumFieldIterable(struct), new FieldComparator(comp)); + comps[PType.ROW] = (self, row, comp) -> compareOrdered(self.getFields(), row.getFields(), new FieldComparator(comp)); return comps; } @@ -671,16 +701,16 @@ private static int compareUnordered(Iterable l, Iterable r, Comparator /** * @param lhs the original left-hand-side argument's type of {@link Comparator#compare(Object, Object)}. * @return an array that indicates the type precedence output of {@code lhs.compare(rhs)}. This uses the - * {@link PType.Kind#ordinal()} to make O(1) judgements. This array will be further modified by type-specific + * {@link PType#code() to make O(1) judgements. This array will be further modified by type-specific * methods. * @see #fillTinyIntComparator(DatumComparison[]) * @see #fillSmallIntComparator(DatumComparison[]) */ @NotNull - private static DatumComparison[] initializeComparatorArray(@NotNull PType.Kind lhs) { + private static DatumComparison[] initializeComparatorArray(int lhs) { DatumComparison[] array = new DatumComparison[TYPE_KINDS_LENGTH]; for (int i = 0; i < TYPE_KINDS_LENGTH; i++) { - PType.Kind rhs = TYPE_KINDS[i]; + int rhs = TYPE_KINDS[i]; int lhsPrecedence = TYPE_PRECEDENCE.getOrDefault(lhs, -1); int rhsPrecedence = TYPE_PRECEDENCE.getOrDefault(rhs, -1); if (lhsPrecedence < 0) { diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumInt.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumInt.java index ec3e4cee2..388a82977 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumInt.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumInt.java @@ -26,4 +26,11 @@ public int getInt() { public PType getType() { return _type; } + + @Override + public String toString() { + return "DatumInt{" + + "_value=" + _value + + '}'; + } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java index b6a773e1e..70da87d9e 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java @@ -39,7 +39,7 @@ public PType getType() { @Override public boolean getBoolean() { - if (_type.getKind() == PType.Kind.BOOL) { + if (_type.code() == PType.BOOL) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -48,7 +48,7 @@ public boolean getBoolean() { @Override public short getShort() { - if (_type.getKind() == PType.Kind.SMALLINT) { + if (_type.code() == PType.SMALLINT) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -57,7 +57,7 @@ public short getShort() { @Override public int getInt() { - if (_type.getKind() == PType.Kind.INTEGER) { + if (_type.code() == PType.INTEGER) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -66,7 +66,7 @@ public int getInt() { @Override public long getLong() { - if (_type.getKind() == PType.Kind.BIGINT) { + if (_type.code() == PType.BIGINT) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -76,7 +76,7 @@ public long getLong() { @NotNull @Override public BigInteger getBigInteger() { - if (_type.getKind() == PType.Kind.NUMERIC) { + if (_type.code() == PType.NUMERIC) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -86,7 +86,7 @@ public BigInteger getBigInteger() { @NotNull @Override public BigDecimal getBigDecimal() { - if (_type.getKind() == PType.Kind.DECIMAL) { + if (_type.code() == PType.DECIMAL) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -95,7 +95,7 @@ public BigDecimal getBigDecimal() { @Override public byte getByte() { - if (_type.getKind() == PType.Kind.TINYINT) { + if (_type.code() == PType.TINYINT) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -105,7 +105,7 @@ public byte getByte() { @NotNull @Override public byte[] getBytes() { - if (_type.getKind() == PType.Kind.BLOB || _type.getKind() == PType.Kind.CLOB) { + if (_type.code() == PType.BLOB || _type.code() == PType.CLOB) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -115,7 +115,7 @@ public byte[] getBytes() { @NotNull @Override public Date getDate() { - if (_type.getKind() == PType.Kind.DATE) { + if (_type.code() == PType.DATE) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -124,7 +124,7 @@ public Date getDate() { @Override public double getDouble() { - if (_type.getKind() == PType.Kind.DOUBLE) { + if (_type.code() == PType.DOUBLE) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -133,7 +133,7 @@ public double getDouble() { @Override public float getFloat() { - if (_type.getKind() == PType.Kind.REAL) { + if (_type.code() == PType.REAL) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -143,7 +143,7 @@ public float getFloat() { @NotNull @Override public Iterator iterator() { - if (_type.getKind() == PType.Kind.BAG || _type.getKind() == PType.Kind.ARRAY) { + if (_type.code() == PType.BAG || _type.code() == PType.ARRAY) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -153,7 +153,7 @@ public Iterator iterator() { @NotNull @Override public Iterator getFields() { - if (_type.getKind() == PType.Kind.STRUCT || _type.getKind() == PType.Kind.ROW) { + if (_type.code() == PType.STRUCT || _type.code() == PType.ROW) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -163,7 +163,7 @@ public Iterator getFields() { @NotNull @Override public String getString() { - if (_type.getKind() == PType.Kind.STRING || _type.getKind() == PType.Kind.CHAR) { + if (_type.code() == PType.STRING || _type.code() == PType.CHAR) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -173,7 +173,7 @@ public String getString() { @NotNull @Override public Time getTime() { - if (_type.getKind() == PType.Kind.TIMEZ || _type.getKind() == PType.Kind.TIME) { + if (_type.code() == PType.TIMEZ || _type.code() == PType.TIME) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); @@ -183,7 +183,7 @@ public Time getTime() { @NotNull @Override public Timestamp getTimestamp() { - if (_type.getKind() == PType.Kind.TIMESTAMPZ || _type.getKind() == PType.Kind.TIMESTAMP) { + if (_type.code() == PType.TIMESTAMPZ || _type.code() == PType.TIMESTAMP) { throw new NullPointerException(); } else { throw new UnsupportedOperationException(); diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Aggregation.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Aggregation.kt index 6545d93f3..b6177a345 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Aggregation.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Aggregation.kt @@ -71,8 +71,8 @@ public interface Aggregation : Routine { override fun getReturnType(args: Array): PType = returns override fun getAccumulator(args: Array): Accumulator = accumulator() override fun toString(): String { - val parameters = parameters.joinToString("__") { it.getType().kind.name } - val returnType = returns.kind.name + val parameters = parameters.joinToString("__") { it.getType().name() } + val returnType = returns.name() return "FN_${name}___${parameters}___$returnType" } } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Builtins.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Builtins.kt index 4cdc29fa9..cdd7f2f47 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Builtins.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Builtins.kt @@ -23,7 +23,7 @@ internal object Builtins { Fn_ABS__INT16__INT16, Fn_ABS__INT32__INT32, Fn_ABS__INT64__INT64, - Fn_ABS__INT__INT, + Fn_ABS__NUMERIC__NUMERIC, Fn_ABS__FLOAT32__FLOAT32, Fn_ABS__FLOAT64__FLOAT64, Fn_ABS__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY, @@ -261,7 +261,7 @@ internal object Builtins { Agg_AVG__INT16__INT16, Agg_AVG__INT32__INT32, Agg_AVG__INT64__INT64, - Agg_AVG__INT__INT, + Agg_AVG__NUMERIC__NUMERIC, Agg_AVG__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY, Agg_AVG__FLOAT32__FLOAT32, Agg_AVG__FLOAT64__FLOAT64, @@ -273,7 +273,7 @@ internal object Builtins { Agg_MAX__INT16__INT16, Agg_MAX__INT32__INT32, Agg_MAX__INT64__INT64, - Agg_MAX__INT__INT, + Agg_MAX__NUMERIC__NUMERIC, Agg_MAX__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY, Agg_MAX__FLOAT32__FLOAT32, Agg_MAX__FLOAT64__FLOAT64, @@ -293,7 +293,7 @@ internal object Builtins { Agg_SUM__INT16__INT16, Agg_SUM__INT32__INT32, Agg_SUM__INT64__INT64, - Agg_SUM__INT__INT, + Agg_SUM__NUMERIC__NUMERIC, Agg_SUM__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY, Agg_SUM__FLOAT32__FLOAT32, Agg_SUM__FLOAT64__FLOAT64, diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Function.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Function.kt index 64cc0a649..1d949caab 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Function.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Function.kt @@ -123,8 +123,8 @@ public interface Function : Routine { override fun getInstance(args: Array): Instance = instance override fun toString(): String { // TODO debug strings for SqlTypeFamily - // val parameters = parameters.joinToString("__") { it.getType().kind.name } - val returnType = returns.kind.name + // val parameters = parameters.joinToString("__") { it.getType().PType.name } + val returnType = returns.name() return "FN_${name}___${parameters}___$returnType" } } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Parameter.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Parameter.kt index 433c251f3..2fa564500 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/Parameter.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/Parameter.kt @@ -3,7 +3,7 @@ package org.partiql.spi.function import org.partiql.spi.internal.SqlTypeFamily import org.partiql.spi.internal.SqlTypes import org.partiql.types.PType -import org.partiql.types.PType.Kind.DYNAMIC +import org.partiql.types.PType.DYNAMIC /** * [Parameter] is a formal argument's definition. @@ -47,7 +47,7 @@ public class Parameter private constructor( * @param type Parameter type used for function resolution. */ public constructor(name: String, type: PType) : this(name, SqlTypeFamily(type)) { - dynamic = type.kind == DYNAMIC + dynamic = type.code() == DYNAMIC variadic = false } @@ -77,7 +77,7 @@ public class Parameter private constructor( if (dynamic || arg in type) { return arg // exact match } - if (arg.kind == DYNAMIC || SqlTypes.isAssignable(arg, type.preferred)) { + if (arg.code() == DYNAMIC || SqlTypes.isAssignable(arg, type.preferred)) { return type.preferred } return null diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggAvg.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggAvg.kt index 596ff59f9..d78de2bd4 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggAvg.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggAvg.kt @@ -45,12 +45,12 @@ internal val Agg_AVG__INT64__INT64 = Aggregation.static( accumulator = ::AccumulatorAvg, ) -internal val Agg_AVG__INT__INT = Aggregation.static( +internal val Agg_AVG__NUMERIC__NUMERIC = Aggregation.static( name = "avg", returns = AVG_DECIMAL, parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.numeric()), + Parameter("value", DefaultNumeric.NUMERIC), ), accumulator = ::AccumulatorAvg, ) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMax.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMax.kt index 2832b0a60..de8831d7b 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMax.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMax.kt @@ -48,12 +48,12 @@ internal val Agg_MAX__INT64__INT64 = Aggregation.static( accumulator = ::AccumulatorMax, ) -internal val Agg_MAX__INT__INT = Aggregation.static( +internal val Agg_MAX__NUMERIC__NUMERIC = Aggregation.static( name = "max", - returns = PType.numeric(), + returns = DefaultNumeric.NUMERIC, parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.numeric()), + Parameter("value", DefaultNumeric.NUMERIC), ), accumulator = ::AccumulatorMax, ) @@ -61,9 +61,9 @@ internal val Agg_MAX__INT__INT = Aggregation.static( internal val Agg_MAX__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Aggregation.static( name = "max", - returns = PType.decimal(), + returns = PType.decimal(38, 19), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.decimal()), + Parameter("value", PType.decimal(38, 19)), // TODO: Rewrite aggregations using new function modeling. ), accumulator = ::AccumulatorMax, diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMin.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMin.kt index df1aba810..140f569fe 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMin.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggMin.kt @@ -46,18 +46,18 @@ internal val Agg_MIN__INT64__INT64 = Aggregation.static( internal val Agg_MIN__INT__INT = Aggregation.static( name = "min", - returns = PType.numeric(), + returns = DefaultNumeric.NUMERIC, parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.numeric()), + Parameter("value", DefaultNumeric.NUMERIC), // TODO: Rewrite aggregations using new function modeling. ), accumulator = ::AccumulatorMin, ) internal val Agg_MIN__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Aggregation.static( name = "min", - returns = PType.decimal(), + returns = PType.decimal(38, 19), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.decimal()), + Parameter("value", PType.decimal(38, 19)), // TODO: Rewrite aggregations using new function modeling. ), accumulator = ::AccumulatorMin, ) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggSum.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggSum.kt index 8e6ec801e..b661e6dc7 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggSum.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/AggSum.kt @@ -44,22 +44,22 @@ internal val Agg_SUM__INT64__INT64 = Aggregation.static( accumulator = { AccumulatorSum(PType.bigint()) }, ) -internal val Agg_SUM__INT__INT = Aggregation.static( +internal val Agg_SUM__NUMERIC__NUMERIC = Aggregation.static( name = "sum", - returns = PType.numeric(), + returns = DefaultNumeric.NUMERIC, parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.numeric()), + Parameter("value", DefaultNumeric.NUMERIC), ), - accumulator = { AccumulatorSum(PType.numeric()) }, + accumulator = { AccumulatorSum(DefaultNumeric.NUMERIC) }, ) internal val Agg_SUM__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Aggregation.static( name = "sum", - returns = PType.decimal(), + returns = PType.decimal(38, 19), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.decimal()), + Parameter("value", PType.decimal(38, 19)), // TODO: Rewrite aggregations using new function modeling. ), - accumulator = { AccumulatorSum(PType.decimal()) }, + accumulator = { AccumulatorSum(PType.decimal(38, 19)) }, ) internal val Agg_SUM__FLOAT32__FLOAT32 = Aggregation.static( diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DefaultNumeric.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DefaultNumeric.kt new file mode 100644 index 000000000..cb9d44a30 --- /dev/null +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DefaultNumeric.kt @@ -0,0 +1,8 @@ +package org.partiql.spi.function.builtins + +import org.partiql.types.PType + +internal object DefaultNumeric { + // TODO: Once all functions are converted to use the new function modeling, this can be removed. + val NUMERIC: PType = PType.numeric(38, 19) +} diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicComparisonOperator.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicComparisonOperator.kt index 9e7a4e82a..948d5af29 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicComparisonOperator.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicComparisonOperator.kt @@ -26,7 +26,7 @@ internal abstract class DiadicComparisonOperator(name: String) : DiadicOperator( override fun getInstance(args: Array): Function.Instance? { val lhs = args[0] val rhs = args[1] - val hasDecimal = lhs.kind == PType.Kind.DECIMAL || rhs.kind == PType.Kind.DECIMAL + val hasDecimal = lhs.code() == PType.DECIMAL || rhs.code() == PType.DECIMAL val allNumbers = (SqlTypeFamily.NUMBER.contains(lhs) && SqlTypeFamily.NUMBER.contains(rhs)) if (hasDecimal && allNumbers) { return getNumberInstance(lhs, rhs) @@ -45,15 +45,15 @@ internal abstract class DiadicComparisonOperator(name: String) : DiadicOperator( abstract fun getNumberComparison(lhs: Number, rhs: Number): Boolean private fun Datum.getNumber(): Number { - return when (this.type.kind) { - PType.Kind.TINYINT -> this.byte - PType.Kind.INTEGER -> this.int - PType.Kind.SMALLINT -> this.short - PType.Kind.BIGINT -> this.long - PType.Kind.REAL -> this.float - PType.Kind.DOUBLE -> this.double - PType.Kind.DECIMAL -> this.bigDecimal - PType.Kind.NUMERIC -> this.bigInteger + return when (this.type.code()) { + PType.TINYINT -> this.byte + PType.INTEGER -> this.int + PType.SMALLINT -> this.short + PType.BIGINT -> this.long + PType.REAL -> this.float + PType.DOUBLE -> this.double + PType.DECIMAL -> this.bigDecimal + PType.NUMERIC -> this.bigInteger else -> error("Unexpected type: ${this.type}") } } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicOperator.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicOperator.kt index 7e5640974..bd233083c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicOperator.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/DiadicOperator.kt @@ -18,6 +18,13 @@ internal abstract class DiadicOperator( private val rhs: Parameter ) : Function { + companion object { + private val DEC_TINY_INT = PType.decimal(3, 0) + private val DEC_SMALL_INT = PType.decimal(5, 0) + private val DEC_INT = PType.decimal(10, 0) + private val DEC_BIG_INT = PType.decimal(19, 0) + } + override fun getName(): String { return name } @@ -29,14 +36,14 @@ internal abstract class DiadicOperator( override fun getInstance(args: Array): Function.Instance? { val lhs = args[0] val rhs = args[1] - val lhsPrecedence = TYPE_PRECEDENCE[lhs.kind] ?: throw IllegalArgumentException("Type not supported -- LHS = $lhs") - val rhsPrecedence = TYPE_PRECEDENCE[rhs.kind] ?: throw IllegalArgumentException("Type not supported -- RHS = $rhs") + val lhsPrecedence = TYPE_PRECEDENCE[lhs.code()] ?: throw IllegalArgumentException("Type not supported -- LHS = $lhs") + val rhsPrecedence = TYPE_PRECEDENCE[rhs.code()] ?: throw IllegalArgumentException("Type not supported -- RHS = $rhs") val (newLhs, newRhs) = when (lhsPrecedence.compareTo(rhsPrecedence)) { -1 -> (rhs to rhs) 0 -> (lhs to rhs) else -> (lhs to lhs) } - val instance = instances[lhs.kind.ordinal][rhs.kind.ordinal] + val instance = instances[lhs.code()][rhs.code()] return instance(newLhs, newRhs) } @@ -202,26 +209,26 @@ internal abstract class DiadicOperator( * This is a lookup table for finding the appropriate instance for the given types. The table is * initialized on construction using the get*Instance methods. */ - protected val instances: Array Function.Instance?>> = Array(PType.Kind.entries.size) { - Array(PType.Kind.entries.size) { + protected val instances: Array Function.Instance?>> = Array(PType.codes().size) { + Array(PType.codes().size) { { _, _ -> null } } } - protected fun fillTable(lhs: PType.Kind, rhs: PType.Kind, instance: (PType, PType) -> Function.Instance?) { - instances[lhs.ordinal][rhs.ordinal] = instance + protected fun fillTable(lhs: Int, rhs: Int, instance: (PType, PType) -> Function.Instance?) { + instances[lhs][rhs] = instance } - protected fun fillNumberTable(highPrecedence: PType.Kind, instance: (PType, PType) -> Function.Instance?) { + protected fun fillNumberTable(highPrecedence: Int, instance: (PType, PType) -> Function.Instance?) { return fillPrioritizedTable(highPrecedence, SqlTypeFamily.NUMBER, instance) } - private fun fillCharacterStringTable(highPrecedence: PType.Kind, instance: (PType, PType) -> Function.Instance?) { + private fun fillCharacterStringTable(highPrecedence: Int, instance: (PType, PType) -> Function.Instance?) { return fillPrioritizedTable(highPrecedence, SqlTypeFamily.TEXT, instance) } - protected fun fillPrioritizedTable(highPrecedence: PType.Kind, family: SqlTypeFamily, instance: (PType, PType) -> Function.Instance?) { - val members = family.members + setOf(PType.Kind.UNKNOWN) + protected fun fillPrioritizedTable(highPrecedence: Int, family: SqlTypeFamily, instance: (PType, PType) -> Function.Instance?) { + val members = family.members + setOf(PType.UNKNOWN) members.filter { (TYPE_PRECEDENCE[highPrecedence]!! > TYPE_PRECEDENCE[it]!!) }.forEach { @@ -232,67 +239,90 @@ internal abstract class DiadicOperator( } private fun fillBooleanTable(instance: (PType, PType) -> Function.Instance?) { - fillTable(PType.Kind.BOOL, PType.Kind.BOOL) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.BOOL, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.BOOL) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.BOOL, PType.BOOL) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.BOOL, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.UNKNOWN, PType.BOOL) { _, rhs -> instance(rhs, rhs) } } private fun fillTimestampTable(instance: (PType, PType) -> Function.Instance?) { - fillTable(PType.Kind.TIMESTAMPZ, PType.Kind.TIMESTAMPZ) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMESTAMP, PType.Kind.TIMESTAMP) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMESTAMPZ, PType.Kind.TIMESTAMP) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMESTAMP, PType.Kind.TIMESTAMPZ) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMESTAMP, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.TIMESTAMPZ, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.TIMESTAMP) { _, rhs -> instance(rhs, rhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.TIMESTAMPZ) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.TIMESTAMPZ, PType.TIMESTAMPZ) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMESTAMP, PType.TIMESTAMP) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMESTAMPZ, PType.TIMESTAMP) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMESTAMP, PType.TIMESTAMPZ) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMESTAMP, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.TIMESTAMPZ, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.UNKNOWN, PType.TIMESTAMP) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.UNKNOWN, PType.TIMESTAMPZ) { _, rhs -> instance(rhs, rhs) } } private fun fillTimeTable(instance: (PType, PType) -> Function.Instance?) { - fillTable(PType.Kind.TIMEZ, PType.Kind.TIMEZ) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIME, PType.Kind.TIME) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMEZ, PType.Kind.TIME) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIME, PType.Kind.TIMEZ) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.TIMEZ, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.TIME, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.TIME) { _, rhs -> instance(rhs, rhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.TIMEZ) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.TIMEZ, PType.TIMEZ) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIME, PType.TIME) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMEZ, PType.TIME) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIME, PType.TIMEZ) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.TIMEZ, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.TIME, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.UNKNOWN, PType.TIME) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.UNKNOWN, PType.TIMEZ) { _, rhs -> instance(rhs, rhs) } } private fun fillDateTable(instance: (PType, PType) -> Function.Instance?) { - fillTable(PType.Kind.DATE, PType.Kind.DATE) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.DATE, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.DATE) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.DATE, PType.DATE) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.DATE, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.UNKNOWN, PType.DATE) { _, rhs -> instance(rhs, rhs) } } private fun fillBlobTable(instance: (PType, PType) -> Function.Instance?) { - fillTable(PType.Kind.BLOB, PType.Kind.BLOB) { lhs, rhs -> instance(lhs, rhs) } - fillTable(PType.Kind.BLOB, PType.Kind.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } - fillTable(PType.Kind.UNKNOWN, PType.Kind.BLOB) { _, rhs -> instance(rhs, rhs) } + fillTable(PType.BLOB, PType.BLOB) { lhs, rhs -> instance(lhs, rhs) } + fillTable(PType.BLOB, PType.UNKNOWN) { lhs, _ -> instance(lhs, lhs) } + fillTable(PType.UNKNOWN, PType.BLOB) { _, rhs -> instance(rhs, rhs) } } - open fun fillDecimalTable() { - fillNumberTable(PType.Kind.DECIMAL, ::getDecimalInstance) + private fun fillDecimalTable() { + // Tiny Int + fillTable(PType.TINYINT, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(DEC_TINY_INT, rhs) } + fillTable(PType.DECIMAL, PType.TINYINT) { lhs, rhs -> getDecimalInstance(lhs, DEC_TINY_INT) } + + // Small Int + fillTable(PType.SMALLINT, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(DEC_SMALL_INT, rhs) } + fillTable(PType.DECIMAL, PType.SMALLINT) { lhs, rhs -> getDecimalInstance(lhs, DEC_SMALL_INT) } + + // Integer + fillTable(PType.INTEGER, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(DEC_INT, rhs) } + fillTable(PType.DECIMAL, PType.INTEGER) { lhs, rhs -> getDecimalInstance(lhs, DEC_INT) } + + // Big Int + fillTable(PType.BIGINT, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(DEC_BIG_INT, rhs) } + fillTable(PType.DECIMAL, PType.BIGINT) { lhs, rhs -> getDecimalInstance(lhs, DEC_BIG_INT) } + + // Numeric + fillTable(PType.NUMERIC, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(PType.decimal(38, 19), rhs) } // TODO: Convert numeric to decimal once numeric is not modeled as BigInteger + fillTable(PType.DECIMAL, PType.NUMERIC) { lhs, rhs -> getDecimalInstance(lhs, PType.decimal(38, 19)) } // TODO: Convert numeric to decimal once numeric is not modeled as BigInteger + + // Decimal + fillTable(PType.DECIMAL, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(lhs, rhs) } + fillTable(PType.UNKNOWN, PType.DECIMAL) { lhs, rhs -> getDecimalInstance(rhs, rhs) } + fillTable(PType.DECIMAL, PType.UNKNOWN) { lhs, rhs -> getDecimalInstance(lhs, lhs) } } - open fun fillTable() { + protected fun fillTable() { fillBooleanTable(::getBooleanInstance) - fillNumberTable(PType.Kind.TINYINT, ::getTinyIntInstance) - fillNumberTable(PType.Kind.SMALLINT, ::getSmallIntInstance) - fillNumberTable(PType.Kind.INTEGER, ::getIntegerInstance) - fillNumberTable(PType.Kind.BIGINT, ::getBigIntInstance) + fillNumberTable(PType.TINYINT, ::getTinyIntInstance) + fillNumberTable(PType.SMALLINT, ::getSmallIntInstance) + fillNumberTable(PType.INTEGER, ::getIntegerInstance) + fillNumberTable(PType.BIGINT, ::getBigIntInstance) fillDecimalTable() - fillNumberTable(PType.Kind.NUMERIC, ::getNumericInstance) - fillNumberTable(PType.Kind.REAL, ::getRealInstance) - fillNumberTable(PType.Kind.DOUBLE, ::getDoubleInstance) + fillNumberTable(PType.NUMERIC, ::getNumericInstance) + fillNumberTable(PType.REAL, ::getRealInstance) + fillNumberTable(PType.DOUBLE, ::getDoubleInstance) fillTimeTable(::getTimeInstance) fillDateTable(::getDateInstance) fillBlobTable(::getBlobInstance) fillTimestampTable(::getTimestampInstance) - fillCharacterStringTable(PType.Kind.STRING, ::getStringInstance) - fillCharacterStringTable(PType.Kind.CHAR, ::getCharInstance) - fillCharacterStringTable(PType.Kind.VARCHAR, ::getVarcharInstance) - fillCharacterStringTable(PType.Kind.CLOB, ::getClobInstance) + fillCharacterStringTable(PType.STRING, ::getStringInstance) + fillCharacterStringTable(PType.CHAR, ::getCharInstance) + fillCharacterStringTable(PType.VARCHAR, ::getVarcharInstance) + fillCharacterStringTable(PType.CLOB, ::getClobInstance) } protected fun basic(returns: PType, lhs: PType, rhs: PType, invocation: (Array) -> Datum): Function.Instance { diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnAbs.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnAbs.kt index a54f71d14..d97538786 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnAbs.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnAbs.kt @@ -47,10 +47,10 @@ internal val Fn_ABS__INT64__INT64 = Function.static( Datum.bigint(value.absoluteValue) } -internal val Fn_ABS__INT__INT = Function.static( +internal val Fn_ABS__NUMERIC__NUMERIC = Function.static( name = "abs", - returns = PType.numeric(), - parameters = arrayOf(Parameter("value", PType.numeric())), + returns = DefaultNumeric.NUMERIC, + parameters = arrayOf(Parameter("value", DefaultNumeric.NUMERIC)), ) { args -> val value = args[0].bigInteger Datum.numeric(value.abs()) @@ -58,8 +58,8 @@ internal val Fn_ABS__INT__INT = Function.static( internal val Fn_ABS__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Function.static( name = "abs", - returns = PType.decimal(), - parameters = arrayOf(Parameter("value", PType.decimal())), + returns = PType.decimal(39, 19), // TODO: Rewrite using new function modeling. + parameters = arrayOf(Parameter("value", PType.decimal(38, 19))), ) { args -> val value = args[0].bigDecimal Datum.decimal(value.abs()) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBetween.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBetween.kt index 7b5ffe259..3df72bc16 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBetween.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBetween.kt @@ -81,9 +81,9 @@ internal val Fn_BETWEEN__INT_INT_INT__BOOL = Function.static( name = "between", returns = PType.bool(), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("value", PType.numeric()), - @Suppress("DEPRECATION") Parameter("lower", PType.numeric()), - @Suppress("DEPRECATION") Parameter("upper", PType.numeric()), + Parameter("value", DefaultNumeric.NUMERIC), + Parameter("lower", DefaultNumeric.NUMERIC), + Parameter("upper", DefaultNumeric.NUMERIC), ), ) { args -> @@ -98,9 +98,9 @@ internal val Fn_BETWEEN__DECIMAL_ARBITRARY_DECIMAL_ARBITRARY_DECIMAL_ARBITRARY__ name = "between", returns = PType.bool(), parameters = arrayOf( - Parameter("value", PType.decimal()), - Parameter("lower", PType.decimal()), - Parameter("upper", PType.decimal()), + Parameter("value", PType.decimal(38, 19)), // TODO: Rewrite using new function modeling. + Parameter("lower", PType.decimal(38, 19)), + Parameter("upper", PType.decimal(38, 19)), ), ) { args -> diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBitwiseAnd.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBitwiseAnd.kt index cdba43d3c..f2e1db52b 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBitwiseAnd.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnBitwiseAnd.kt @@ -48,7 +48,7 @@ internal object FnBitwiseAnd : DiadicArithmeticOperator("bitwise_and") { // TODO: Probably remove this if we don't expose NUMERIC override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 and arg1) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddDay.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddDay.kt index 8a2d0fb92..98f9e4f5a 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddDay.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddDay.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_DAY__INT_DATE__DATE = Function.static( name = "date_add_day", returns = PType.date(), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.date()), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_DAY__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_day", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddHour.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddHour.kt index 31c919426..be21e3c08 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddHour.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddHour.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_HOUR__INT_TIME__TIME = Function.static( name = "date_add_hour", returns = PType.time(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.time(6)), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_HOUR__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_hour", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMinute.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMinute.kt index 4e26500c4..9811538a9 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMinute.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMinute.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_MINUTE__INT_TIME__TIME = Function.static( name = "date_add_minute", returns = PType.time(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.time(6)), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_MINUTE__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_minute", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMonth.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMonth.kt index 443d26a81..5a61e31c5 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMonth.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddMonth.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_MONTH__INT_DATE__DATE = Function.static( name = "date_add_month", returns = PType.date(), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.date()), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_MONTH__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_month", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddSecond.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddSecond.kt index 995ecfd11..53c3415e5 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddSecond.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddSecond.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_SECOND__INT_TIME__TIME = Function.static( name = "date_add_second", returns = PType.time(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.time(6)), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_SECOND__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_second", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddYear.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddYear.kt index 3ba1f66e1..4beae8cbb 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddYear.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDateAddYear.kt @@ -49,7 +49,7 @@ internal val Fn_DATE_ADD_YEAR__INT_DATE__DATE = Function.static( name = "date_add_year", returns = PType.date(), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.date()), ), @@ -104,7 +104,7 @@ internal val Fn_DATE_ADD_YEAR__INT_TIMESTAMP__TIMESTAMP = Function.static( name = "date_add_year", returns = PType.timestamp(6), parameters = arrayOf( - @Suppress("DEPRECATION") Parameter("interval", PType.numeric()), + Parameter("interval", DefaultNumeric.NUMERIC), Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDivide.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDivide.kt index e8d243d1c..cc1f6f1a2 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDivide.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnDivide.kt @@ -46,7 +46,7 @@ internal object FnDivide : DiadicArithmeticOperator("divide") { } override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 / arg1) @@ -59,7 +59,7 @@ internal object FnDivide : DiadicArithmeticOperator("divide") { override fun getDecimalInstance(decimalLhs: PType, decimalRhs: PType): Function.Instance { val p = decimalLhs.precision - decimalLhs.scale + decimalRhs.scale + Math.max(6, decimalLhs.scale + decimalRhs.precision + 1) val s = Math.max(6, decimalLhs.scale + decimalRhs.precision + 1) - return basic(PType.decimal()) { args -> + return basic(PType.decimal(p, s), decimalLhs, decimalRhs) { args -> val arg0 = args[0].bigDecimal val arg1 = args[1].bigDecimal Datum.decimal(arg0 / arg1, p, s) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnEq.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnEq.kt index 09f6dcd54..22d8582bb 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnEq.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnEq.kt @@ -5,7 +5,6 @@ package org.partiql.spi.function.builtins import org.partiql.spi.function.Function import org.partiql.spi.function.Parameter -import org.partiql.spi.function.builtins.FnPlus.fillTable import org.partiql.spi.value.Datum import org.partiql.types.PType @@ -25,10 +24,6 @@ import org.partiql.types.PType */ internal object FnEq : Function { - init { - fillTable() - } - // Memoize shared variables private val comparator = Datum.comparator() private val boolType = PType.bool() diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnExtract.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnExtract.kt index aca766682..dfe6db4cb 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnExtract.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnExtract.kt @@ -161,7 +161,7 @@ internal val Fn_EXTRACT_MINUTE__TIMESTAMP__INT32 = Function.static( internal val Fn_EXTRACT_SECOND__TIME__DECIMAL_ARBITRARY = Function.static( name = "extract_second", - returns = PType.decimal(), + returns = PType.decimal(38, 19), // TODO: Rewrite using new function modeling. parameters = arrayOf( Parameter("datetime", PType.time(6)), ), @@ -174,7 +174,7 @@ internal val Fn_EXTRACT_SECOND__TIME__DECIMAL_ARBITRARY = Function.static( internal val Fn_EXTRACT_SECOND__TIMESTAMP__DECIMAL_ARBITRARY = Function.static( name = "extract_second", - returns = PType.decimal(), + returns = PType.decimal(38, 19), // TODO: Rewrite using new function modeling. parameters = arrayOf( Parameter("datetime", PType.timestamp(6)), ), diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGt.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGt.kt index da1efb025..c0077be00 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGt.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGt.kt @@ -52,7 +52,7 @@ internal object FnGt : DiadicComparisonOperator("gt") { // TODO: Update numeric to use bigDecimal rather than bigInteger. override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.bool(), PType.numeric()) { args -> + return basic(PType.bool(), DefaultNumeric.NUMERIC) { args -> val lhs = args[0].bigInteger val rhs = args[1].bigInteger Datum.bool(lhs > rhs) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGte.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGte.kt index 714be6a7a..9a581b5c2 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGte.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnGte.kt @@ -52,7 +52,7 @@ internal object FnGte : DiadicComparisonOperator("gte") { // TODO: Update override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.bool(), PType.numeric()) { args -> + return basic(PType.bool(), DefaultNumeric.NUMERIC) { args -> val lhs = args[0].bigInteger val rhs = args[1].bigInteger Datum.bool(lhs >= rhs) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnInCollection.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnInCollection.kt index 5afb5aae6..c54fe8f12 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnInCollection.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnInCollection.kt @@ -25,7 +25,7 @@ internal object FnInCollection : Function { override fun getInstance(args: Array): Function.Instance? { val vType = args[0] val cType = args[1] - if (cType.kind !in setOf(PType.Kind.UNKNOWN, PType.Kind.ARRAY, PType.Kind.BAG)) { + if (cType.code() !in setOf(PType.UNKNOWN, PType.ARRAY, PType.BAG)) { return null } return object : Function.Instance( diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBag.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBag.kt index 28709fa63..e35758ea2 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBag.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBag.kt @@ -7,12 +7,11 @@ import org.partiql.spi.function.Function import org.partiql.spi.function.Parameter import org.partiql.spi.value.Datum import org.partiql.types.PType -import org.partiql.types.PType.Kind internal val Fn_IS_BAG__ANY__BOOL = Function.static( name = "is_bag", returns = PType.bool(), parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == Kind.BAG) + Datum.bool(args[0].type.code() == PType.BAG) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBlob.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBlob.kt index c325f43b8..abefbf0bb 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBlob.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBlob.kt @@ -13,5 +13,5 @@ internal val Fn_IS_BLOB__ANY__BOOL = Function.static( returns = PType.bool(), parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.BLOB) + Datum.bool(args[0].type.code() == PType.BLOB) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBool.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBool.kt index dc6c584e7..2ca7040c4 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBool.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsBool.kt @@ -13,5 +13,5 @@ internal val Fn_IS_BOOL__ANY__BOOL = Function.static( returns = PType.bool(), parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.BOOL) + Datum.bool(args[0].type.code() == PType.BOOL) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsChar.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsChar.kt index c105ca2e3..ae1da6b8f 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsChar.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsChar.kt @@ -14,12 +14,12 @@ internal val Fn_IS_CHAR__ANY__BOOL = Function.static( returns = PType.bool(), parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.CHAR) + Datum.bool(args[0].type.code() == PType.CHAR) } private val TEXT_TYPES_WITH_LENGTH = setOf( - PType.Kind.CHAR, - PType.Kind.VARCHAR + PType.CHAR, + PType.VARCHAR ) internal val Fn_IS_CHAR__INT32_ANY__BOOL = Function.static( @@ -31,7 +31,7 @@ internal val Fn_IS_CHAR__INT32_ANY__BOOL = Function.static( ), ) { args -> val value = args[0] - if (value.type.kind in TEXT_TYPES_WITH_LENGTH) { + if (value.type.code() in TEXT_TYPES_WITH_LENGTH) { Datum.bool(false) } val length = args[0].int diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsClob.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsClob.kt index b7d80d212..d88d0849e 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsClob.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsClob.kt @@ -15,5 +15,5 @@ internal val Fn_IS_CLOB__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.CLOB) + Datum.bool(args[0].type.code() == PType.CLOB) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDate.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDate.kt index 77f2ac370..adf281acd 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDate.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDate.kt @@ -15,5 +15,5 @@ internal val Fn_IS_DATE__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.DATE) + Datum.bool(args[0].type.code() == PType.DATE) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDecimal.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDecimal.kt index 8dcab3f5f..3cc07bb7e 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDecimal.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsDecimal.kt @@ -15,7 +15,7 @@ internal val Fn_IS_DECIMAL__ANY__BOOL = Function.static( returns = PType.bool(), parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.DECIMAL) + Datum.bool(args[0].type.code() == PType.DECIMAL) } internal val Fn_IS_DECIMAL__INT32_INT32_ANY__BOOL = Function.static( @@ -45,7 +45,7 @@ internal val Fn_IS_DECIMAL__INT32_INT32_ANY__BOOL = Function.static( */ { args -> val v = args[2] - if (v.type.kind != PType.Kind.DECIMAL) { + if (v.type.code() != PType.DECIMAL) { return@static Datum.bool(false) } val p = args[0].int diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat32.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat32.kt index 8db6e5af9..0f873d9f8 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat32.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat32.kt @@ -16,9 +16,9 @@ internal val Fn_IS_FLOAT32__ANY__BOOL = Function.static( ) { args -> val arg = args[0] - when (arg.type.kind) { - PType.Kind.REAL -> Datum.bool(true) - PType.Kind.DOUBLE -> { + when (arg.type.code()) { + PType.REAL -> Datum.bool(true) + PType.DOUBLE -> { val v = arg.double Datum.bool(Float.MIN_VALUE <= v && v <= Float.MAX_VALUE) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat64.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat64.kt index 9955af77a..424c0a86d 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat64.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsFloat64.kt @@ -15,9 +15,9 @@ internal val Fn_IS_FLOAT64__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - when (args[0].type.kind) { - PType.Kind.REAL, - PType.Kind.DOUBLE, + when (args[0].type.code()) { + PType.REAL, + PType.DOUBLE, -> Datum.bool(true) else -> Datum.bool(false) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt.kt index b5d20a516..09bdf95c6 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt.kt @@ -9,11 +9,11 @@ import org.partiql.spi.value.Datum import org.partiql.types.PType private val INT_TYPES = setOf( - PType.Kind.TINYINT, - PType.Kind.SMALLINT, - PType.Kind.INTEGER, - PType.Kind.BIGINT, - PType.Kind.NUMERIC + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, + PType.NUMERIC ) internal val Fn_IS_INT__ANY__BOOL = Function.static( @@ -22,5 +22,5 @@ internal val Fn_IS_INT__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())) ) { args -> val arg = args[0] - Datum.bool(arg.type.kind in INT_TYPES) + Datum.bool(arg.type.code() in INT_TYPES) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt16.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt16.kt index 536774a68..8bf34170e 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt16.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt16.kt @@ -16,19 +16,19 @@ internal val Fn_IS_INT16__ANY__BOOL = Function.static( ) { args -> val arg = args[0] - when (arg.type.kind) { - PType.Kind.TINYINT, - PType.Kind.SMALLINT, + when (arg.type.code()) { + PType.TINYINT, + PType.SMALLINT, -> Datum.bool(true) - PType.Kind.INTEGER -> { + PType.INTEGER -> { val v = arg.int Datum.bool(Short.MIN_VALUE <= v && v <= Short.MAX_VALUE) } - PType.Kind.BIGINT -> { + PType.BIGINT -> { val v = arg.long Datum.bool(Short.MIN_VALUE <= v && v <= Short.MAX_VALUE) } - PType.Kind.NUMERIC -> { + PType.NUMERIC -> { val v = arg.bigInteger try { v.shortValueExact() diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt32.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt32.kt index 86d19ae3b..3c16b7383 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt32.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt32.kt @@ -16,16 +16,16 @@ internal val Fn_IS_INT32__ANY__BOOL = Function.static( ) { args -> val arg = args[0] - when (arg.type.kind) { - PType.Kind.TINYINT, - PType.Kind.SMALLINT, - PType.Kind.INTEGER, + when (arg.type.code()) { + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, -> Datum.bool(true) - PType.Kind.BIGINT -> { + PType.BIGINT -> { val v = arg Datum.bool(Integer.MIN_VALUE <= v.long && v.long <= Integer.MAX_VALUE) } - PType.Kind.NUMERIC -> { + PType.NUMERIC -> { val v = arg.bigInteger try { v.intValueExact() diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt64.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt64.kt index 0a38b2063..1a55a5155 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt64.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt64.kt @@ -16,13 +16,13 @@ internal val Fn_IS_INT64__ANY__BOOL = Function.static( ) { args -> val arg = args[0] - when (arg.type.kind) { - PType.Kind.TINYINT, - PType.Kind.SMALLINT, - PType.Kind.INTEGER, - PType.Kind.BIGINT, + when (arg.type.code()) { + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, -> Datum.bool(true) - PType.Kind.NUMERIC -> { + PType.NUMERIC -> { val v = arg.bigInteger try { v.longValueExact() diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt8.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt8.kt index 0de805c9e..46379417b 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt8.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsInt8.kt @@ -16,21 +16,21 @@ internal val Fn_IS_INT8__ANY__BOOL = Function.static( ) { args -> val arg = args[0] - when (arg.type.kind) { - PType.Kind.TINYINT -> Datum.bool(true) - PType.Kind.SMALLINT -> { + when (arg.type.code()) { + PType.TINYINT -> Datum.bool(true) + PType.SMALLINT -> { val v = arg.short Datum.bool(Byte.MIN_VALUE <= v && v <= Byte.MAX_VALUE) } - PType.Kind.INTEGER -> { + PType.INTEGER -> { val v = arg.int Datum.bool(Byte.MIN_VALUE <= v && v <= Byte.MAX_VALUE) } - PType.Kind.BIGINT -> { + PType.BIGINT -> { val v = arg.long Datum.bool(Byte.MIN_VALUE <= v && v <= Byte.MAX_VALUE) } - PType.Kind.NUMERIC -> { + PType.NUMERIC -> { val v = arg.bigInteger try { v.byteValueExact() diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsList.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsList.kt index 24a54dbaa..0bf3d3819 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsList.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsList.kt @@ -15,5 +15,5 @@ internal val Fn_IS_LIST__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.ARRAY) + Datum.bool(args[0].type.code() == PType.ARRAY) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsString.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsString.kt index eb7cf5ac3..2d6c98133 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsString.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsString.kt @@ -15,7 +15,7 @@ internal val Fn_IS_STRING__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.STRING) + Datum.bool(args[0].type.code() == PType.STRING) } internal val Fn_IS_STRING__INT32_ANY__BOOL = Function.static( @@ -27,7 +27,7 @@ internal val Fn_IS_STRING__INT32_ANY__BOOL = Function.static( ), ) { args -> val v = args[1] - if (v.type.kind != PType.Kind.STRING) { + if (v.type.code() != PType.STRING) { return@static Datum.bool(false) } val length = args[0].int diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsStruct.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsStruct.kt index df12f7ef0..e83155c0c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsStruct.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsStruct.kt @@ -15,5 +15,5 @@ internal val Fn_IS_STRUCT__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - Datum.bool(args[0].type.kind == PType.Kind.STRUCT) + Datum.bool(args[0].type.code() == PType.STRUCT) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTime.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTime.kt index 8d6905487..ae3f6b36c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTime.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTime.kt @@ -15,8 +15,8 @@ internal val Fn_IS_TIME__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - val argKind = args[0].type.kind - Datum.bool(argKind == PType.Kind.TIMEZ || argKind == PType.Kind.TIME) + val argKind = args[0].type.code() + Datum.bool(argKind == PType.TIMEZ || argKind == PType.TIME) } internal val Fn_IS_TIME__BOOL_INT32_ANY__BOOL = Function.static( diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTimestamp.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTimestamp.kt index a05dbae20..63f798281 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTimestamp.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnIsTimestamp.kt @@ -15,8 +15,8 @@ internal val Fn_IS_TIMESTAMP__ANY__BOOL = Function.static( parameters = arrayOf(Parameter("value", PType.dynamic())), ) { args -> - val argKind = args[0].type.kind - Datum.bool(argKind == PType.Kind.TIMESTAMPZ || argKind == PType.Kind.TIMESTAMP) + val argKind = args[0].type.code() + Datum.bool(argKind == PType.TIMESTAMPZ || argKind == PType.TIMESTAMP) } internal val Fn_IS_TIMESTAMP__BOOL_INT32_ANY__BOOL = Function.static( diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLt.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLt.kt index cf685ea4e..8e526a2be 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLt.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLt.kt @@ -48,7 +48,7 @@ internal object FnLt : DiadicComparisonOperator("lt") { // TODO: Update override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.bool(), PType.numeric()) { args -> + return basic(PType.bool(), DefaultNumeric.NUMERIC) { args -> val lhs = args[0].bigInteger val rhs = args[1].bigInteger Datum.bool(lhs < rhs) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLte.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLte.kt index 11a9208a8..35d6cba0e 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLte.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnLte.kt @@ -52,7 +52,7 @@ internal object FnLte : DiadicComparisonOperator("lte") { // TODO: Update override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.bool(), PType.numeric()) { args -> + return basic(PType.bool(), DefaultNumeric.NUMERIC) { args -> val lhs = args[0].bigInteger val rhs = args[1].bigInteger Datum.bool(lhs <= rhs) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnMinus.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnMinus.kt index 348300ce3..df7de273c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnMinus.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnMinus.kt @@ -48,7 +48,7 @@ internal object FnMinus : DiadicArithmeticOperator("minus") { // TODO: Delete this override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 - arg1) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnModulo.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnModulo.kt index 772390887..a785a020e 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnModulo.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnModulo.kt @@ -46,7 +46,7 @@ internal object FnModulo : DiadicArithmeticOperator("modulo") { } override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 % arg1) @@ -61,7 +61,7 @@ internal object FnModulo : DiadicArithmeticOperator("modulo") { override fun getDecimalInstance(decimalLhs: PType, decimalRhs: PType): Function.Instance { val p = Math.min(decimalLhs.precision - decimalLhs.scale, decimalRhs.precision - decimalRhs.scale) + Math.max(decimalLhs.scale, decimalRhs.scale) val s = Math.max(decimalLhs.scale, decimalRhs.scale) - return basic(PType.decimal()) { args -> + return basic(PType.decimal(p, s), decimalLhs, decimalRhs) { args -> val arg0 = args[0].bigDecimal val arg1 = args[1].bigDecimal Datum.decimal(arg0 % arg1, p, s) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnNeg.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnNeg.kt index a7e2a4936..0ebc9380c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnNeg.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnNeg.kt @@ -57,8 +57,8 @@ internal val Fn_NEG__INT64__INT64 = Function.static( internal val Fn_NEG__INT__INT = Function.static( name = "neg", - returns = PType.numeric(), - parameters = arrayOf(Parameter("value", PType.numeric())), + returns = DefaultNumeric.NUMERIC, + parameters = arrayOf(Parameter("value", DefaultNumeric.NUMERIC)), ) { args -> val value = args[0].bigInteger @@ -68,8 +68,8 @@ internal val Fn_NEG__INT__INT = Function.static( internal val Fn_NEG__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Function.static( name = "neg", - returns = PType.decimal(), - parameters = arrayOf(Parameter("value", PType.decimal())), + returns = PType.decimal(38, 19), // TODO: Rewrite using new function modeling. + parameters = arrayOf(Parameter("value", PType.decimal(38, 19))), ) { args -> val value = args[0].bigDecimal diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPlus.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPlus.kt index f3ca315e3..576951390 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPlus.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPlus.kt @@ -48,7 +48,7 @@ internal object FnPlus : DiadicArithmeticOperator("plus") { // TODO: Probably remove this if we don't expose NUMERIC override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 + arg1) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPos.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPos.kt index 474ed6f7e..bb0ab5085 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPos.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnPos.kt @@ -50,8 +50,8 @@ internal val Fn_POS__INT64__INT64 = Function.static( internal val Fn_POS__INT__INT = Function.static( name = "pos", - returns = PType.numeric(), - parameters = arrayOf(Parameter("value", PType.numeric())), + returns = DefaultNumeric.NUMERIC, + parameters = arrayOf(Parameter("value", DefaultNumeric.NUMERIC)), ) { args -> args[0] @@ -60,8 +60,8 @@ internal val Fn_POS__INT__INT = Function.static( internal val Fn_POS__DECIMAL_ARBITRARY__DECIMAL_ARBITRARY = Function.static( name = "pos", - returns = PType.decimal(), - parameters = arrayOf(Parameter("value", PType.decimal())), + returns = PType.decimal(38, 19), // TODO: Rewrite this using the new modeling + parameters = arrayOf(Parameter("value", PType.decimal(38, 19))), ) { args -> args[0] diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnTimes.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnTimes.kt index ec2fbc4f9..9e3b00f64 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnTimes.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/FnTimes.kt @@ -46,7 +46,7 @@ internal object FnTimes : DiadicArithmeticOperator("times") { } override fun getNumericInstance(numericLhs: PType, numericRhs: PType): Function.Instance { - return basic(PType.numeric()) { args -> + return basic(DefaultNumeric.NUMERIC) { args -> val arg0 = args[0].bigInteger val arg1 = args[1].bigInteger Datum.numeric(arg0 * arg1) @@ -59,7 +59,7 @@ internal object FnTimes : DiadicArithmeticOperator("times") { override fun getDecimalInstance(decimalLhs: PType, decimalRhs: PType): Function.Instance { val p = decimalLhs.precision + decimalRhs.precision + 1 val s = decimalLhs.scale + decimalRhs.scale - return basic(PType.decimal()) { args -> + return basic(PType.decimal(p, s), decimalLhs, decimalRhs) { args -> val arg0 = args[0].bigDecimal val arg1 = args[1].bigDecimal Datum.decimal(arg0 * arg1, p, s) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/TypePrecedence.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/TypePrecedence.kt index fdb4b03a2..3cfc527e6 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/TypePrecedence.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/TypePrecedence.kt @@ -1,38 +1,38 @@ package org.partiql.spi.function.builtins -import org.partiql.types.PType.Kind +import org.partiql.types.PType internal object TypePrecedence { /** * @return the precedence of the types for the PartiQL comparator. - * @see .TYPE_PRECEDENCE + * @see TYPE_PRECEDENCE */ - internal val TYPE_PRECEDENCE: Map = listOf( - Kind.UNKNOWN, - Kind.BOOL, - Kind.TINYINT, - Kind.SMALLINT, - Kind.INTEGER, - Kind.BIGINT, - Kind.NUMERIC, - Kind.DECIMAL, - Kind.REAL, - Kind.DOUBLE, - Kind.CHAR, - Kind.VARCHAR, - Kind.STRING, - Kind.CLOB, - Kind.BLOB, - Kind.DATE, - Kind.TIME, - Kind.TIMEZ, - Kind.TIMESTAMP, - Kind.TIMESTAMPZ, - Kind.ARRAY, - Kind.BAG, - Kind.ROW, - Kind.STRUCT, - Kind.DYNAMIC + internal val TYPE_PRECEDENCE: Map = listOf( + PType.UNKNOWN, + PType.BOOL, + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, + PType.NUMERIC, + PType.DECIMAL, + PType.REAL, + PType.DOUBLE, + PType.CHAR, + PType.VARCHAR, + PType.STRING, + PType.CLOB, + PType.BLOB, + PType.DATE, + PType.TIME, + PType.TIMEZ, + PType.TIMESTAMP, + PType.TIMESTAMPZ, + PType.ARRAY, + PType.BAG, + PType.ROW, + PType.STRUCT, + PType.DYNAMIC ).mapIndexed { precedence, type -> type to precedence }.toMap() } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/Accumulator.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/Accumulator.kt index b6e4bba14..6e8ae0082 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/Accumulator.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/Accumulator.kt @@ -97,37 +97,37 @@ private fun Long.checkOverflowPlus(other: Long): Number { } internal fun checkIsBooleanType(funcName: String, value: Datum) { - if (value.type.kind != PType.Kind.BOOL) { - throw TypeCheckException("Expected ${PType.Kind.BOOL} but received ${value.type}.") + if (value.type.code() != PType.BOOL) { + throw TypeCheckException("Expected ${PType.BOOL} but received ${value.type}.") } } -internal fun Datum.numberValue(): Number = when (this.type.kind) { - PType.Kind.TINYINT -> this.byte - PType.Kind.SMALLINT -> this.short - PType.Kind.INTEGER -> this.int - PType.Kind.BIGINT -> this.long - PType.Kind.NUMERIC -> this.bigInteger - PType.Kind.REAL -> this.float - PType.Kind.DOUBLE -> this.double - PType.Kind.DECIMAL -> this.bigDecimal +internal fun Datum.numberValue(): Number = when (this.type.code()) { + PType.TINYINT -> this.byte + PType.SMALLINT -> this.short + PType.INTEGER -> this.int + PType.BIGINT -> this.long + PType.NUMERIC -> this.bigInteger + PType.REAL -> this.float + PType.DOUBLE -> this.double + PType.DECIMAL -> this.bigDecimal else -> error("Cannot convert PartiQLValue ($this) to number.") } -internal fun Datum.booleanValue(): Boolean = when (this.type.kind) { - PType.Kind.BOOL -> this.boolean +internal fun Datum.booleanValue(): Boolean = when (this.type.code()) { + PType.BOOL -> this.boolean else -> error("Cannot convert PartiQLValue ($this) to boolean.") } -internal fun PType.isNumber(): Boolean = when (this.kind) { - PType.Kind.INTEGER, - PType.Kind.TINYINT, - PType.Kind.SMALLINT, - PType.Kind.BIGINT, - PType.Kind.NUMERIC, - PType.Kind.REAL, - PType.Kind.DOUBLE, - PType.Kind.DECIMAL, +internal fun PType.isNumber(): Boolean = when (this.code()) { + PType.INTEGER, + PType.TINYINT, + PType.SMALLINT, + PType.BIGINT, + PType.NUMERIC, + PType.REAL, + PType.DOUBLE, + PType.DECIMAL, -> true else -> false } @@ -140,11 +140,11 @@ internal fun nullToTargetType(type: PType): Datum = Datum.nullValue(type) /** * This is specifically for SUM/AVG */ -internal fun Number.toTargetType(type: PType): Datum = when (type.kind) { - PType.Kind.DYNAMIC -> this.toDatum() - PType.Kind.REAL -> Datum.real(this.toFloat()) - PType.Kind.DOUBLE -> Datum.doublePrecision(this.toDouble()) - PType.Kind.DECIMAL -> { +internal fun Number.toTargetType(type: PType): Datum = when (type.code()) { + PType.DYNAMIC -> this.toDatum() + PType.REAL -> Datum.real(this.toFloat()) + PType.DOUBLE -> Datum.doublePrecision(this.toDouble()) + PType.DECIMAL -> { when (this) { is BigDecimal -> Datum.decimal(this, this.precision(), this.scale()) is BigInteger -> { @@ -157,11 +157,11 @@ internal fun Number.toTargetType(type: PType): Datum = when (type.kind) { } } } - PType.Kind.TINYINT -> Datum.tinyint(this.toByte()) - PType.Kind.SMALLINT -> Datum.smallint(this.toShort()) - PType.Kind.INTEGER -> Datum.integer(this.toInt()) - PType.Kind.BIGINT -> Datum.bigint(this.toLong()) - PType.Kind.NUMERIC -> when (this) { + PType.TINYINT -> Datum.tinyint(this.toByte()) + PType.SMALLINT -> Datum.smallint(this.toShort()) + PType.INTEGER -> Datum.integer(this.toInt()) + PType.BIGINT -> Datum.bigint(this.toLong()) + PType.NUMERIC -> when (this) { is BigInteger -> Datum.numeric(this) is BigDecimal -> Datum.numeric(this.toBigInteger()) else -> Datum.numeric(BigInteger.valueOf(this.toLong())) diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/AccumulatorAvg.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/AccumulatorAvg.kt index 04590b175..1b5b6a462 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/AccumulatorAvg.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/function/builtins/internal/AccumulatorAvg.kt @@ -5,7 +5,7 @@ import org.partiql.types.PType internal class AccumulatorAvg : Accumulator() { - private var targetType = PType.decimal() + private var targetType = PType.decimal(38, 19) private var sum: Number = 0.0 private var count: Long = 0L diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypeFamily.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypeFamily.kt index 1cd6ae1cf..cc2dabd86 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypeFamily.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypeFamily.kt @@ -1,7 +1,6 @@ package org.partiql.spi.internal import org.partiql.types.PType -import org.partiql.types.PType.Kind /** * A basic "set" representation for type categorization; perhaps we optimize later.. @@ -26,15 +25,15 @@ import org.partiql.types.PType.Kind */ internal class SqlTypeFamily private constructor( @JvmField val preferred: PType, - @JvmField val members: Set, + @JvmField val members: Set, ) { /** * Constructor a singleton [SqlTypeFamily]. */ - constructor(preferred: PType) : this(preferred, setOf(preferred.kind)) + constructor(preferred: PType) : this(preferred, setOf(preferred.code())) - operator fun contains(type: PType) = type.kind in members + operator fun contains(type: PType) = type.code() in members companion object { @@ -42,10 +41,10 @@ internal class SqlTypeFamily private constructor( val TEXT = SqlTypeFamily( preferred = PType.string(), members = setOf( - Kind.CHAR, - Kind.VARCHAR, - Kind.STRING, - Kind.CLOB, + PType.CHAR, + PType.VARCHAR, + PType.STRING, + PType.CLOB, ) ) @@ -53,23 +52,23 @@ internal class SqlTypeFamily private constructor( val COLLECTION = SqlTypeFamily( preferred = PType.bag(), members = setOf( - Kind.ARRAY, - Kind.BAG + PType.ARRAY, + PType.BAG ) ) @JvmStatic val NUMBER = SqlTypeFamily( - preferred = PType.decimal(), + preferred = PType.decimal(38, 19), members = setOf( - Kind.TINYINT, - Kind.SMALLINT, - Kind.INTEGER, - Kind.BIGINT, - Kind.NUMERIC, - Kind.REAL, - Kind.DOUBLE, - Kind.DECIMAL, + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, + PType.NUMERIC, + PType.REAL, + PType.DOUBLE, + PType.DECIMAL, ) ) } diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypes.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypes.kt index 550c751f6..9a327825c 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypes.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/spi/internal/SqlTypes.kt @@ -2,7 +2,6 @@ package org.partiql.spi.internal import org.partiql.types.Field import org.partiql.types.PType -import org.partiql.types.PType.Kind /** * Important SQL Definitions: @@ -49,7 +48,7 @@ internal object SqlTypes { * for the [PType.getTypeParameter] and [PType.getFields] */ private fun areAssignableDynamicTypes(target: PType): Boolean { - return target.kind == Kind.DYNAMIC + return target.code() == PType.DYNAMIC } /** @@ -66,10 +65,10 @@ internal object SqlTypes { */ private fun areAssignableStructuralTypes(input: PType, target: PType): Boolean { return when { - input.kind == Kind.ROW && target.kind == Kind.ROW -> fieldsAreAssignable(input.fields.toList(), target.fields!!.toList()) - input.kind == Kind.STRUCT && target.kind == Kind.ROW -> true - input.kind == Kind.ROW && target.kind == Kind.STRUCT -> true - input.kind == Kind.STRUCT && target.kind == Kind.STRUCT -> true + input.code() == PType.ROW && target.code() == PType.ROW -> fieldsAreAssignable(input.fields.toList(), target.fields!!.toList()) + input.code() == PType.STRUCT && target.code() == PType.ROW -> true + input.code() == PType.ROW && target.code() == PType.STRUCT -> true + input.code() == PType.STRUCT && target.code() == PType.STRUCT -> true else -> false } } @@ -130,7 +129,7 @@ internal object SqlTypes { * ``` */ private fun areAssignableBooleanTypes(input: PType, target: PType): Boolean { - return input.kind == Kind.BOOL && target.kind == Kind.BOOL + return input.code() == PType.BOOL && target.code() == PType.BOOL } /** @@ -156,12 +155,12 @@ internal object SqlTypes { * ``` */ private fun areAssignableDateTimeTypes(input: PType, target: PType): Boolean { - val i = input.kind - val t = target.kind + val i = input.code() + val t = target.code() return when { - i == Kind.DATE && t == Kind.DATE -> true - (i == Kind.TIMEZ || i == Kind.TIME) && (t == Kind.TIMEZ || t == Kind.TIME) -> true - (i == Kind.TIMESTAMPZ || i == Kind.TIMESTAMP) && (t == Kind.TIMESTAMPZ || t == Kind.TIMESTAMP) -> true + i == PType.DATE && t == PType.DATE -> true + (i == PType.TIMEZ || i == PType.TIME) && (t == PType.TIMEZ || t == PType.TIME) -> true + (i == PType.TIMESTAMPZ || i == PType.TIMESTAMP) && (t == PType.TIMESTAMPZ || t == PType.TIMESTAMP) -> true else -> false } } diff --git a/partiql-spi/src/main/kotlin/org/partiql/value/PartiQLValueType.kt b/partiql-spi/src/main/kotlin/org/partiql/value/PartiQLValueType.kt index 47873ec25..770712958 100644 --- a/partiql-spi/src/main/kotlin/org/partiql/value/PartiQLValueType.kt +++ b/partiql-spi/src/main/kotlin/org/partiql/value/PartiQLValueType.kt @@ -70,7 +70,7 @@ public enum class PartiQLValueType { ) public fun toPType(): PType { return when (this) { - DECIMAL -> PType.decimal() + DECIMAL -> PType.decimal(38, 0) DECIMAL_ARBITRARY -> error("DECIMAL_ARB has been removed.") INT8 -> PType.tinyint() CHAR -> PType.character(255) @@ -84,7 +84,7 @@ public enum class PartiQLValueType { LIST -> PType.array() BAG -> PType.bag() FLOAT32 -> PType.real() - INT -> PType.numeric() + INT -> PType.numeric(38, 0) INT64 -> PType.bigint() INT32 -> PType.integer() INT16 -> PType.smallint() diff --git a/partiql-spi/src/test/kotlin/org/partiql/eval/value/DatumComparatorTest.kt b/partiql-spi/src/test/kotlin/org/partiql/eval/value/DatumComparatorTest.kt index aac37eec0..9b19422c3 100644 --- a/partiql-spi/src/test/kotlin/org/partiql/eval/value/DatumComparatorTest.kt +++ b/partiql-spi/src/test/kotlin/org/partiql/eval/value/DatumComparatorTest.kt @@ -100,7 +100,7 @@ class DatumComparatorTest { Datum.missing(), // missing Datum.nullValue(), // TODO: annotations = listOf("a")), // `a::null` Datum.missing(), // TODO: annotations = listOf("a")), // `a::missing` - Datum.nullValue(PType.numeric()), // `null.int`, + Datum.nullValue(PType.numeric(38, 0)), // `null.int`, Datum.nullValue(PType.struct()) // `null.struct` ) ) diff --git a/partiql-types/api/partiql-types.api b/partiql-types/api/partiql-types.api index 6145bbbf8..27e71076c 100644 --- a/partiql-types/api/partiql-types.api +++ b/partiql-types/api/partiql-types.api @@ -1,10 +1,45 @@ +public abstract class org/partiql/types/Enum { + protected fun (I)V + public final fun code ()I + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I + public abstract fun name ()Ljava/lang/String; +} + public abstract interface class org/partiql/types/Field { public abstract fun getName ()Ljava/lang/String; public abstract fun getType ()Lorg/partiql/types/PType; public static fun of (Ljava/lang/String;Lorg/partiql/types/PType;)Lorg/partiql/types/Field; } -public abstract interface class org/partiql/types/PType { +public abstract class org/partiql/types/PType : org/partiql/types/Enum { + public static final field ARRAY I + public static final field BAG I + public static final field BIGINT I + public static final field BLOB I + public static final field BOOL I + public static final field CHAR I + public static final field CLOB I + public static final field DATE I + public static final field DECIMAL I + public static final field DOUBLE I + public static final field DYNAMIC I + public static final field INTEGER I + public static final field NUMERIC I + public static final field REAL I + public static final field ROW I + public static final field SMALLINT I + public static final field STRING I + public static final field STRUCT I + public static final field TIME I + public static final field TIMESTAMP I + public static final field TIMESTAMPZ I + public static final field TIMEZ I + public static final field TINYINT I + public static final field UNKNOWN I + public static final field VARCHAR I + public static final field VARIANT I + protected fun (I)V public static fun array ()Lorg/partiql/types/PType; public static fun array (Lorg/partiql/types/PType;)Lorg/partiql/types/PType; public static fun bag ()Lorg/partiql/types/PType; @@ -14,20 +49,19 @@ public abstract interface class org/partiql/types/PType { public static fun bool ()Lorg/partiql/types/PType; public static fun character (I)Lorg/partiql/types/PType; public static fun clob (I)Lorg/partiql/types/PType; + public static fun codes ()[I public static fun date ()Lorg/partiql/types/PType; - public static fun decimal ()Lorg/partiql/types/PType; - public static fun decimal (I)Lorg/partiql/types/PType; public static fun decimal (II)Lorg/partiql/types/PType; public static fun doublePrecision ()Lorg/partiql/types/PType; public static fun dynamic ()Lorg/partiql/types/PType; public fun getFields ()Ljava/util/Collection; - public abstract fun getKind ()Lorg/partiql/types/PType$Kind; public fun getLength ()I public fun getPrecision ()I public fun getScale ()I public fun getTypeParameter ()Lorg/partiql/types/PType; public static fun integer ()Lorg/partiql/types/PType; - public static fun numeric ()Lorg/partiql/types/PType; + public fun name ()Ljava/lang/String; + public static fun numeric (II)Lorg/partiql/types/PType; public static fun real ()Lorg/partiql/types/PType; public static fun row (Ljava/util/Collection;)Lorg/partiql/types/PType; public static fun row ([Lorg/partiql/types/Field;)Lorg/partiql/types/PType; @@ -44,34 +78,3 @@ public abstract interface class org/partiql/types/PType { public static fun variant (Ljava/lang/String;)Lorg/partiql/types/PType; } -public final class org/partiql/types/PType$Kind : java/lang/Enum { - public static final field ARRAY Lorg/partiql/types/PType$Kind; - public static final field BAG Lorg/partiql/types/PType$Kind; - public static final field BIGINT Lorg/partiql/types/PType$Kind; - public static final field BLOB Lorg/partiql/types/PType$Kind; - public static final field BOOL Lorg/partiql/types/PType$Kind; - public static final field CHAR Lorg/partiql/types/PType$Kind; - public static final field CLOB Lorg/partiql/types/PType$Kind; - public static final field DATE Lorg/partiql/types/PType$Kind; - public static final field DECIMAL Lorg/partiql/types/PType$Kind; - public static final field DOUBLE Lorg/partiql/types/PType$Kind; - public static final field DYNAMIC Lorg/partiql/types/PType$Kind; - public static final field INTEGER Lorg/partiql/types/PType$Kind; - public static final field NUMERIC Lorg/partiql/types/PType$Kind; - public static final field REAL Lorg/partiql/types/PType$Kind; - public static final field ROW Lorg/partiql/types/PType$Kind; - public static final field SMALLINT Lorg/partiql/types/PType$Kind; - public static final field STRING Lorg/partiql/types/PType$Kind; - public static final field STRUCT Lorg/partiql/types/PType$Kind; - public static final field TIME Lorg/partiql/types/PType$Kind; - public static final field TIMESTAMP Lorg/partiql/types/PType$Kind; - public static final field TIMESTAMPZ Lorg/partiql/types/PType$Kind; - public static final field TIMEZ Lorg/partiql/types/PType$Kind; - public static final field TINYINT Lorg/partiql/types/PType$Kind; - public static final field UNKNOWN Lorg/partiql/types/PType$Kind; - public static final field VARCHAR Lorg/partiql/types/PType$Kind; - public static final field VARIANT Lorg/partiql/types/PType$Kind; - public static fun valueOf (Ljava/lang/String;)Lorg/partiql/types/PType$Kind; - public static fun values ()[Lorg/partiql/types/PType$Kind; -} - diff --git a/partiql-types/src/main/java/org/partiql/types/Enum.java b/partiql-types/src/main/java/org/partiql/types/Enum.java new file mode 100644 index 000000000..d44926067 --- /dev/null +++ b/partiql-types/src/main/java/org/partiql/types/Enum.java @@ -0,0 +1,50 @@ +package org.partiql.types; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * All enumerated types should extend this class for backward/forward compatibility. + */ +public abstract class Enum { + + /** + * Enum variants are represented with integers. + */ + private final int code; + + /** + * Creates an {@link Enum} with the specified {@code code}. + * @param code the unique code of this enum. + */ + protected Enum(int code) { + this.code = code; + } + + /** + * @return a unique integer corresponding with the variant of the enum. + */ + public final int code() { + return code; + } + + /** + * @return the name of the enum variant. + */ + @NotNull + public abstract String name(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Enum)) return false; + Enum other = (Enum) o; + return code == other.code; + } + + @Override + public int hashCode() { + return Objects.hashCode(code); + } +} diff --git a/partiql-types/src/main/java/org/partiql/types/PType.java b/partiql-types/src/main/java/org/partiql/types/PType.java index 094e3c769..afc74138a 100644 --- a/partiql-types/src/main/java/org/partiql/types/PType.java +++ b/partiql-types/src/main/java/org/partiql/types/PType.java @@ -8,11 +8,11 @@ /** * This represents a PartiQL type, whether it be a PartiQL primitive or user-defined. *

- * This implementation allows for parameterization of the core type ({@link Kind}) while allowing for APIs + * This implementation allows for parameterization of the core type ({@link PType#code()}) while allowing for APIs * to access their parameters ({@link PType#getPrecision()}, {@link PType#getTypeParameter()}, etc.) *

* Before using these methods, please be careful to read each method's documentation to ensure that it applies to the current - * {@link PType#getKind()}. If one carelessly invokes the wrong method, an {@link UnsupportedOperationException} will be + * {@link PType#code()}. If one carelessly invokes the wrong method, an {@link UnsupportedOperationException} will be * thrown. *

* This representation of a PartiQL type is intentionally modeled as a "fat" interface -- holding all methods relevant @@ -23,34 +23,25 @@ * Users should NOT author their own implementation. The current recommendation is to use the static methods * (exposed by this interface) to instantiate a type. */ -public interface PType { - - /** - * Dictates the associates {@link Kind} of this instance. This method should be called and its return should be - * analyzed before calling any other method. For example: - *

- * {@code - * public int getPrecisionOrNull(PType type) { - * if (type.base == {@link Kind#DECIMAL}) { - * return type.getPrecision(); - * } - * return null; - * } - * } +public abstract class PType extends Enum { + + /** + * Creates an {@link java.lang.Enum} with the specified {@code code}. * - * @return the corresponding PartiQL {@link Kind}. + * @param code the unique code of this enum. */ - @NotNull - Kind getKind(); + protected PType(int code) { + super(code); + } /** * The fields of the type * - * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: - * {@link Kind#ROW} + * @throws UnsupportedOperationException if this is called on a type whose {@link PType#code()} is not: + * {@link PType#ROW} */ @NotNull - default Collection getFields() throws UnsupportedOperationException { + public Collection getFields() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @@ -58,11 +49,11 @@ default Collection getFields() throws UnsupportedOperationException { * The decimal precision of the type * * @return decimal precision - * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: - * {@link Kind#DECIMAL}, {@link Kind#TIMESTAMPZ}, {@link Kind#TIMESTAMP}, {@link Kind#TIMEZ}, - * {@link Kind#TIME}, {@link Kind#REAL}, {@link Kind#DOUBLE} + * @throws UnsupportedOperationException if this is called on a type whose {@link PType#code()} is not: + * {@link PType#DECIMAL}, {@link PType#TIMESTAMPZ}, {@link PType#TIMESTAMP}, {@link PType#TIMEZ}, + * {@link PType#TIME}, {@link PType#REAL}, {@link PType#DOUBLE} */ - default int getPrecision() throws UnsupportedOperationException { + public int getPrecision() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @@ -70,10 +61,10 @@ default int getPrecision() throws UnsupportedOperationException { * The max length of the type * * @return max length of a type - * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: - * {@link Kind#CHAR}, {@link Kind#CLOB}, {@link Kind#BLOB} + * @throws UnsupportedOperationException if this is called on a type whose {@link PType#code()} is not: + * {@link PType#CHAR}, {@link PType#CLOB}, {@link PType#BLOB} */ - default int getLength() throws UnsupportedOperationException { + public int getLength() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @@ -81,10 +72,10 @@ default int getLength() throws UnsupportedOperationException { * The scale of the type. Example: DECIMAL(<param>, <scale>) * * @return the scale of the type - * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: - * {@link Kind#DECIMAL} + * @throws UnsupportedOperationException if this is called on a type whose {@link PType#code()} is not: + * {@link PType#DECIMAL} */ - default int getScale() throws UnsupportedOperationException { + public int getScale() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @@ -92,567 +83,616 @@ default int getScale() throws UnsupportedOperationException { * The type parameter of the type. Example: BAG(<param>) * * @return type parameter of the type - * @throws UnsupportedOperationException if this is called on a type whose {@link Kind} is not: - * {@link Kind#ARRAY}, {@link Kind#BAG} + * @throws UnsupportedOperationException if this is called on a type whose {@link PType#code()} is not: + * {@link PType#ARRAY}, {@link PType#BAG} */ @NotNull - default PType getTypeParameter() throws UnsupportedOperationException { + public PType getTypeParameter() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } + public static int[] codes() { + return new int[] { + PType.DYNAMIC, + PType.BOOL, + PType.TINYINT, + PType.SMALLINT, + PType.INTEGER, + PType.BIGINT, + PType.NUMERIC, + PType.DECIMAL, + PType.REAL, + PType.DOUBLE, + PType.CHAR, + PType.VARCHAR, + PType.STRING, + PType.BLOB, + PType.CLOB, + PType.DATE, + PType.TIME, + PType.TIMEZ, + PType.TIMESTAMP, + PType.TIMESTAMPZ, + PType.ARRAY, + PType.BAG, + PType.ROW, + PType.STRUCT, + PType.UNKNOWN, + PType.VARIANT, + }; + } + + @Override + public @NotNull String name() { + switch (code()) { + case PType.DYNAMIC: + return "DYNAMIC"; + case PType.BOOL: + return "BOOL"; + case PType.TINYINT: + return "TINYINT"; + case PType.SMALLINT: + return "SMALLINT"; + case PType.INTEGER: + return "INTEGER"; + case PType.BIGINT: + return "BIGINT"; + case PType.NUMERIC: + return "NUMERIC"; + case PType.DECIMAL: + return "DECIMAL"; + case PType.REAL: + return "REAL"; + case PType.DOUBLE: + return "DOUBLE"; + case PType.CHAR: + return "CHAR"; + case PType.VARCHAR: + return "VARCHAR"; + case PType.STRING: + return "STRING"; + case PType.BLOB: + return "BLOB"; + case PType.CLOB: + return "CLOB"; + case PType.DATE: + return "DATE"; + case PType.TIME: + return "TIME"; + case PType.TIMEZ: + return "TIMEZ"; + case PType.TIMESTAMP: + return "TIMESTAMP"; + case PType.TIMESTAMPZ: + return "TIMESTAMPZ"; + case PType.ARRAY: + return "ARRAY"; + case PType.BAG: + return "BAG"; + case PType.ROW: + return "ROW"; + case PType.STRUCT: + return "STRUCT"; + case PType.UNKNOWN: + return "UNKNOWN"; + case PType.VARIANT: + return "VARIANT"; + default: + return "UNKNOWN"; + } + } + + /** + * PartiQL's dynamic type. This is solely used during compilation -- it is not a possible runtime type. + *
+ *
+ * Type Syntax: DYNAMIC + *
+ * Applicable methods: NONE + */ + public static final int DYNAMIC = 0; + + /** + * SQL's boolean type. + *
+ *
+ * Type Syntax: BOOL, BOOLEAN + *
+ * Applicable methods: NONE + */ + public static final int BOOL = 1; + + /** + * PartiQL's tiny integer type. + *
+ *
+ * Type Syntax: TINYINT + *
+ * Applicable methods: NONE + */ + public static final int TINYINT = 2; + + /** + * SQL's small integer type. + *
+ *
+ * Type Syntax: SMALLINT + *
+ * Applicable methods: NONE + */ + public static final int SMALLINT = 3; + + /** + * SQL's integer type. + *
+ *
+ * Type Syntax: INT, INTEGER + *
+ * Applicable methods: NONE + */ + public static final int INTEGER = 4; + + /** + * PartiQL's big integer type. + *
+ *
+ * Type Syntax: BIGINT + *
+ * Applicable methods: NONE + */ + public static final int BIGINT = 5; + + /** + * PartiQL's big integer type. + *
+ *
+ * Type Syntax: NUMERIC + *
+ * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} + */ + public static final int NUMERIC = 6; + /** - * PartiQL Core Type Kinds - *

- * Each of these types correspond with a subset of APIs established in {@link PType}. Each of these can be seen as - * a category of types, distinguished only by the APIs available to them. For instance, all instances of {@link Kind#DECIMAL} - * may utilize {@link PType#getPrecision()} (and may return different results), however, they may never return a - * valid value for {@link PType#getFields()}. Consumers of this API should be careful to read the documentation - * for each API exposed in {@link PType} before using them. - *

- * Future additions may add enums such as INTERVAL_YEAR_MONTH, INTERVAL_DAY_TIME, and more. - * - * @see PType - */ - enum Kind { - - /** - * PartiQL's dynamic type. This is solely used during compilation -- it is not a possible runtime type. - *
- *
- * Type Syntax: DYNAMIC - *
- * Applicable methods: NONE - */ - DYNAMIC, - - /** - * SQL's boolean type. - *
- *
- * Type Syntax: BOOL, BOOLEAN - *
- * Applicable methods: NONE - */ - BOOL, - - /** - * PartiQL's tiny integer type. - *
- *
- * Type Syntax: TINYINT - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - TINYINT, - - /** - * SQL's small integer type. - *
- *
- * Type Syntax: SMALLINT - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - SMALLINT, - - /** - * SQL's integer type. - *
- *
- * Type Syntax: INT, INTEGER - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - INTEGER, - - /** - * PartiQL's big integer type. - *
- *
- * Type Syntax: BIGINT - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - BIGINT, - - /** - * PartiQL's big integer type. - *
- *
- * Type Syntax: NUMERIC - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - NUMERIC, - - /** - * SQL's decimal type. - *
- *
- * Type Syntax: DECIMAL(<precision>, <scale>), DECIMAL(<precision>) - *
- * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} - */ - DECIMAL, - - /** - * SQL's real type. - *
- *
- * Type Syntax: REAL - *
- * Applicable methods: {@link PType#getPrecision()} - */ - REAL, - - /** - * SQL's double precision type. - *
- *
- * Type Syntax: DOUBLE PRECISION - *
- * Applicable methods: {@link PType#getPrecision()} - */ - DOUBLE, - - /** - * SQL's character type. - *
- *
- * Type Syntax: CHAR(<length>), CHARACTER(<length>), CHAR, CHARACTER - *
- * Applicable methods: {@link PType#getLength()} - */ - CHAR, - - /** - * SQL's character varying type. - *
- *
- * Type Syntax: VARCHAR(<length>), CHAR VARYING(<length>), - * CHARACTER VARYING(<length>), - * VARCHAR, CHAR VARYING, CHARACTER VARYING - *
- * Applicable methods: {@link PType#getLength()} - */ - VARCHAR, - - /** - * PartiQL's string type. - *
- *
- * Type Syntax: TO_BE_DETERMINED - *
- * Applicable methods: NONE - */ - STRING, - - /** - * SQL's blob type. - *
- *
- * Type Syntax: BLOB, BLOB(<large object length>), - * BINARY LARGE OBJECT, BINARY LARGE OBJECT(<large object length>) - *
- * Applicable methods: {@link PType#getLength()} - * - * @deprecated this is an experimental API and is subject to modification/deletion without prior notice. - */ - @Deprecated - BLOB, - - /** - * SQL's clob type. - *
- *
- * Type Syntax: CLOB, CLOB(<large object length>), - * CHAR LARGE OBJECT, CHAR LARGE OBJECT(<large object length>) - * CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(<large object length>) - *
- * Applicable methods: {@link PType#getLength()} - * - * @deprecated this is an experimental API and is subject to modification/deletion without prior notice. - */ - @Deprecated - CLOB, - - /** - * SQL's date type. - *
- *
- * Type Syntax: DATE - *
- * Applicable methods: NONE - */ - DATE, - - /** - * SQL's time without timezone type. - *
- *
- * Type Syntax: TIME, TIME WITHOUT TIME ZONE, - * TIME(<precision>), TIME(<precision>) WITHOUT TIME ZONE - *
- * Applicable methods: NONE - */ - TIME, - - /** - * SQL's time with timezone type. - *
- *
- * Type Syntax: TIME WITH TIME ZONE, TIME(<precision>) WITH TIME ZONE - *
- * Applicable methods: NONE - */ - TIMEZ, - - /** - * SQL's timestamp without timezone type. - *
- *
- * Type Syntax: TIMESTAMP, TIMESTAMP WITHOUT TIME ZONE, - * TIMESTAMP(<precision>), TIMESTAMP(<precision>) WITHOUT TIME ZONE - *
- * Applicable methods: NONE - */ - TIMESTAMP, - - /** - * SQL's timestamp with timezone type. - *
- *
- * Type Syntax: TIMESTAMP WITH TIME ZONE, TIMESTAMP(<precision>) WITH TIME ZONE - *
- * Applicable methods: NONE - */ - TIMESTAMPZ, - - /** - * ARRAY (LIST) represents an ordered collection of elements with type T. - *
- *
- * Type Syntax - *
    - *
  • ARRAY
  • - *
  • T ARRAY[N]
  • - *
  • ARRAY{@literal }[N]
  • - *
- *
- *
- * Equivalences - *
    - *
  1. T ARRAY[N] {@literal <->} ARRAY{@literal }[N]
  2. - *
  3. ARRAY[N] {@literal <->} DYNAMIC ARRAY[N] {@literal <->} ARRAY{@literal }[N]
  4. - *
  5. ARRAY {@literal <->} DYNAMIC ARRAY {@literal <->} ARRAY{@literal } {@literal <->} LIST
  6. - *
- *
- * Applicable methods: - * {@link PType#getTypeParameter()} - */ - ARRAY, - - /** - * BAG represents an unordered collection of elements with type T. - *
- *
- * Type Syntax - *
    - *
  • BAG
  • - *
  • T BAG[N]
  • - *
  • BAG{@literal }[N]
  • - *
- *
- *
- * Equivalences - *
    - *
  1. T BAG[N] {@literal <->} BAG{@literal }[N]
  2. - *
  3. BAG[N] {@literal <->} DYNAMIC BAG[N] {@literal <->} BAG{@literal }[N]
  4. - *
  5. BAG {@literal <->} DYNAMIC BAG {@literal <->} BAG{@literal }
  6. - *
- *
- * Applicable methods: - * {@link PType#getTypeParameter()} - */ - BAG, - - /** - * SQL's row type. Characterized as a closed, ordered collection of fields. - *
- *
- * Type Syntax: ROW(<str>: <type>, ...) - *
- * Applicable methods: - * {@link PType#getFields()} - * - * @deprecated this is an experimental API and is subject to modification/deletion without prior notice. - */ - @Deprecated - ROW, - - /** - * Ion's struct type. Characterized as an open, unordered collection of fields (duplicates allowed). - *
- *
- * Type Syntax: STRUCT - *
- * Applicable methods: NONE - */ - STRUCT, - - /** - * PartiQL's unknown type. This temporarily represents literal null and missing values. - *
- *
- * Type Syntax: NONE - *
- * Applicable methods: NONE - * - * @deprecated this is an experimental API and is subject to modification/deletion without prior notice. - */ - @Deprecated - UNKNOWN, - - /** - * The variant type. - *
- *
- * Type Syntax: T VARIANT or VARIANT[T] - *
- */ - VARIANT, - } + * SQL's decimal type. + *
+ *
+ * Type Syntax: DECIMAL(<precision>, <scale>), DECIMAL(<precision>) + *
+ * Applicable methods: {@link PType#getPrecision()}, {@link PType#getScale()} + */ + public static final int DECIMAL = 7; /** - * @return a PartiQL dynamic type + * SQL's real type. + *
+ *
+ * Type Syntax: REAL + *
+ * Applicable methods: NONE */ - @NotNull - static PType dynamic() { - return new PTypePrimitive(Kind.DYNAMIC); - } + public static final int REAL = 8; /** - * @return a PartiQL boolean type + * SQL's double precision type. + *
+ *
+ * Type Syntax: DOUBLE PRECISION + *
+ * Applicable methods: NONE */ - @NotNull - static PType bool() { - return new PTypePrimitive(Kind.BOOL); - } + public static final int DOUBLE = 9; /** - * @return a PartiQL tiny integer type + * SQL's character type. + *
+ *
+ * Type Syntax: CHAR(<length>), CHARACTER(<length>), CHAR, CHARACTER + *
+ * Applicable methods: {@link PType#getLength()} + */ + public static final int CHAR = 10; + + /** + * SQL's character varying type. + *
+ *
+ * Type Syntax: VARCHAR(<length>), CHAR VARYING(<length>), + * CHARACTER VARYING(<length>), + * VARCHAR, CHAR VARYING, CHARACTER VARYING + *
+ * Applicable methods: {@link PType#getLength()} + */ + public static final int VARCHAR = 11; + + /** + * PartiQL's string type. + *
+ *
+ * Type Syntax: TO_BE_DETERMINED + *
+ * Applicable methods: NONE + */ + public static final int STRING = 12; + + /** + * SQL's blob type. + *
+ *
+ * Type Syntax: BLOB, BLOB(<large object length>), + * BINARY LARGE OBJECT, BINARY LARGE OBJECT(<large object length>) + *
+ * Applicable methods: {@link PType#getLength()} + */ + public static final int BLOB = 13; + + /** + * SQL's clob type. + *
+ *
+ * Type Syntax: CLOB, CLOB(<large object length>), + * CHAR LARGE OBJECT, CHAR LARGE OBJECT(<large object length>) + * CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(<large object length>) + *
+ * Applicable methods: {@link PType#getLength()} + */ + public static final int CLOB = 14; + + /** + * SQL's date type. + *
+ *
+ * Type Syntax: DATE + *
+ * Applicable methods: NONE + */ + public static final int DATE = 15; + + /** + * SQL's time without timezone type. + *
+ *
+ * Type Syntax: TIME, TIME WITHOUT TIME ZONE, + * TIME(<precision>), TIME(<precision>) WITHOUT TIME ZONE + *
+ * Applicable methods: NONE + */ + public static final int TIME = 16; + + /** + * SQL's time with timezone type. + *
+ *
+ * Type Syntax: TIME WITH TIME ZONE, TIME(<precision>) WITH TIME ZONE + *
+ * Applicable methods: NONE + */ + public static final int TIMEZ = 17; + + /** + * SQL's timestamp without timezone type. + *
+ *
+ * Type Syntax: TIMESTAMP, TIMESTAMP WITHOUT TIME ZONE, + * TIMESTAMP(<precision>), TIMESTAMP(<precision>) WITHOUT TIME ZONE + *
+ * Applicable methods: NONE + */ + public static final int TIMESTAMP = 18; + + /** + * SQL's timestamp with timezone type. + *
+ *
+ * Type Syntax: TIMESTAMP WITH TIME ZONE, TIMESTAMP(<precision>) WITH TIME ZONE + *
+ * Applicable methods: NONE + */ + public static final int TIMESTAMPZ = 19; + + /** + * ARRAY (LIST) represents an ordered collection of elements with type T. + *
+ *
+ * Type Syntax + *
    + *
  • ARRAY
  • + *
  • T ARRAY[N]
  • + *
  • ARRAY{@literal }[N]
  • + *
+ *
+ *
+ * Equivalences + *
    + *
  1. T ARRAY[N] {@literal <->} ARRAY{@literal }[N]
  2. + *
  3. ARRAY[N] {@literal <->} DYNAMIC ARRAY[N] {@literal <->} ARRAY{@literal }[N]
  4. + *
  5. ARRAY {@literal <->} DYNAMIC ARRAY {@literal <->} ARRAY{@literal } {@literal <->} LIST
  6. + *
+ *
+ * Applicable methods: + * {@link PType#getTypeParameter()} + */ + public static final int ARRAY = 20; + + /** + * BAG represents an unordered collection of elements with type T. + *
+ *
+ * Type Syntax + *
    + *
  • BAG
  • + *
  • T BAG[N]
  • + *
  • BAG{@literal }[N]
  • + *
+ *
+ *
+ * Equivalences + *
    + *
  1. T BAG[N] {@literal <->} BAG{@literal }[N]
  2. + *
  3. BAG[N] {@literal <->} DYNAMIC BAG[N] {@literal <->} BAG{@literal }[N]
  4. + *
  5. BAG {@literal <->} DYNAMIC BAG {@literal <->} BAG{@literal }
  6. + *
+ *
+ * Applicable methods: + * {@link PType#getTypeParameter()} + */ + public static final int BAG = 21; + + /** + * SQL's row type. Characterized as a closed, ordered collection of fields. + *
+ *
+ * Type Syntax: ROW(<str>: <type>, ...) + *
+ * Applicable methods: + * {@link PType#getFields()} + */ + public static final int ROW = 22; + + /** + * Ion's struct type. Characterized as an open, unordered collection of fields (duplicates allowed). + *
+ *
+ * Type Syntax: STRUCT + *
+ * Applicable methods: NONE + */ + public static final int STRUCT = 23; + + /** + * PartiQL's unknown type. This temporarily represents literal null and missing values. + *
+ *
+ * Type Syntax: NONE + *
+ * Applicable methods: NONE + */ + public static final int UNKNOWN = 24; + + /** + * The variant type. + *
+ *
+ * Type Syntax: T VARIANT or VARIANT[T] + *
+ */ + public static final int VARIANT = 25; + + /** + * @return a PartiQL dynamic type */ @NotNull - static PType tinyint() { - return new PTypePrimitive(Kind.TINYINT); + public static PType dynamic() { + return new PTypePrimitive(DYNAMIC); } /** - * @return a PartiQL small integer type + * @return a PartiQL boolean type */ @NotNull - static PType smallint() { - return new PTypePrimitive(Kind.SMALLINT); + public static PType bool() { + return new PTypePrimitive(BOOL); } /** - * @return a PartiQL integer type + * @return a PartiQL tiny integer type */ @NotNull - static PType integer() { - return new PTypePrimitive(Kind.INTEGER); + @SuppressWarnings("unused") + public static PType tinyint() { + return new PTypePrimitive(TINYINT); } /** - * @return a PartiQL big integer type + * @return a PartiQL small integer type */ @NotNull - static PType bigint() { - return new PTypePrimitive(Kind.BIGINT); + public static PType smallint() { + return new PTypePrimitive(SMALLINT); } /** - * @return a PartiQL int (arbitrary precision) type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. + * @return a PartiQL integer type */ @NotNull - @Deprecated - static PType numeric() { - return new PTypePrimitive(Kind.NUMERIC); + public static PType integer() { + return new PTypePrimitive(INTEGER); } /** - * @return a PartiQL decimal type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. + * @return a PartiQL big integer type */ @NotNull - static PType decimal() { - return new PTypeDecimal(38, 0); + public static PType bigint() { + return new PTypePrimitive(BIGINT); } /** - * @return a decimal with user-specified precision and default scale (0) + * @return a SQL:1999 NUMERIC type. */ @NotNull - static PType decimal(int precision) { - return new PTypeDecimal(precision, 0); + public static PType numeric(int precision, int scale) { + return new PTypeDecimal(NUMERIC, precision, scale); } /** * @return a PartiQL decimal type */ @NotNull - static PType decimal(int precision, int scale) { - return new PTypeDecimal(precision, scale); + public static PType decimal(int precision, int scale) { + return new PTypeDecimal(PType.DECIMAL, precision, scale); } /** * @return a PartiQL real type. */ @NotNull - static PType real() { - return new PTypePrimitive(Kind.REAL); + @SuppressWarnings("unused") + public static PType real() { + return new PTypePrimitive(REAL); } /** * @return a PartiQL double precision type */ @NotNull - static PType doublePrecision() { - return new PTypePrimitive(Kind.DOUBLE); + public static PType doublePrecision() { + return new PTypePrimitive(DOUBLE); } /** * @return a PartiQL char type */ @NotNull - static PType character(int length) { - return new PTypeWithMaxLength(Kind.CHAR, length); + @SuppressWarnings("unused") + public static PType character(int length) { + return new PTypeWithMaxLength(CHAR, length); } /** * @return a PartiQL char type */ @NotNull - static PType varchar(int length) { - return new PTypeWithMaxLength(Kind.VARCHAR, length); + @SuppressWarnings("unused") + public static PType varchar(int length) { + return new PTypeWithMaxLength(VARCHAR, length); } /** * @return a PartiQL string type - * - * TODO remove in favor of non-parameterized VARCHAR */ @NotNull - static PType string() { - return new PTypePrimitive(Kind.STRING); + public static PType string() { + return new PTypePrimitive(STRING); } /** * @return a PartiQL clob type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. */ @NotNull - static PType clob(int length) { - return new PTypeWithMaxLength(Kind.CLOB, length); + @SuppressWarnings("SameParameterValue") + public static PType clob(int length) { + return new PTypeWithMaxLength(CLOB, length); } /** * @return a PartiQL blob type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. */ @NotNull - static PType blob(int length) { - return new PTypeWithMaxLength(Kind.BLOB, length); + @SuppressWarnings("SameParameterValue") + public static PType blob(int length) { + return new PTypeWithMaxLength(BLOB, length); } /** * @return a PartiQL date type */ @NotNull - static PType date() { - return new PTypePrimitive(Kind.DATE); + public static PType date() { + return new PTypePrimitive(DATE); } /** * @return a PartiQL time without timezone type */ @NotNull - static PType time(int precision) { - return new PTypeWithPrecisionOnly(Kind.TIME, precision); + public static PType time(int precision) { + return new PTypeWithPrecisionOnly(TIME, precision); } /** * @return a PartiQL time with timezone type */ @NotNull - static PType timez(int precision) { - return new PTypeWithPrecisionOnly(Kind.TIMEZ, precision); + @SuppressWarnings("unused") + public static PType timez(int precision) { + return new PTypeWithPrecisionOnly(TIMEZ, precision); } /** * @return a PartiQL timestamp without timezone type */ @NotNull - static PType timestamp(int precision) { - return new PTypeWithPrecisionOnly(Kind.TIMESTAMP, precision); + public static PType timestamp(int precision) { + return new PTypeWithPrecisionOnly(TIMESTAMP, precision); } /** * @return a PartiQL timestamp with timezone type */ @NotNull - static PType timestampz(int precision) { - return new PTypeWithPrecisionOnly(Kind.TIMESTAMPZ, precision); + @SuppressWarnings("unused") + public static PType timestampz(int precision) { + return new PTypeWithPrecisionOnly(TIMESTAMPZ, precision); } /** * @return a PartiQL list type with a component type of dynamic */ @NotNull - static PType array() { - return new PTypeCollection(Kind.ARRAY, PType.dynamic()); + @SuppressWarnings("unused") + public static PType array() { + return new PTypeCollection(ARRAY, PType.dynamic()); } /** * @return a PartiQL list type with a component type of {@code typeParam} */ @NotNull - static PType array(@NotNull PType typeParam) { - return new PTypeCollection(Kind.ARRAY, typeParam); + public static PType array(@NotNull PType typeParam) { + return new PTypeCollection(ARRAY, typeParam); } /** * @return a PartiQL bag type with a component type of dynamic */ @NotNull - static PType bag() { - return new PTypeCollection(Kind.BAG, PType.dynamic()); + @SuppressWarnings("unused") + public static PType bag() { + return new PTypeCollection(BAG, PType.dynamic()); } /** * @return a PartiQL bag type with a component type of {@code typeParam} */ @NotNull - static PType bag(@NotNull PType typeParam) { - return new PTypeCollection(Kind.BAG, typeParam); + public static PType bag(@NotNull PType typeParam) { + return new PTypeCollection(BAG, typeParam); } /** * @return a PartiQL row type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. */ @NotNull - static PType row(@NotNull Collection fields) { + public static PType row(@NotNull Collection fields) { return new PTypeRow(fields); } /** * @return a PartiQL row type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. */ @NotNull - static PType row(@NotNull Field... fields) { + @SuppressWarnings("unused") + public static PType row(@NotNull Field... fields) { return new PTypeRow(Arrays.asList(fields)); } @@ -660,17 +700,17 @@ static PType row(@NotNull Field... fields) { * @return a PartiQL struct type */ @NotNull - static PType struct() { - return new PTypePrimitive(Kind.STRUCT); + public static PType struct() { + return new PTypePrimitive(STRUCT); } /** * @return a PartiQL unknown type - * @deprecated this API is experimental and is subject to modification/deletion without prior notice. */ @NotNull - static PType unknown() { - return new PTypePrimitive(Kind.UNKNOWN); + @SuppressWarnings("unused") + public static PType unknown() { + return new PTypePrimitive(UNKNOWN); } /** @@ -678,7 +718,8 @@ static PType unknown() { * @return a PartiQL variant type. */ @NotNull - static PType variant(String encoding) { + @SuppressWarnings("unused") + public static PType variant(String encoding) { return new PTypeVariant(encoding); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeCollection.java b/partiql-types/src/main/java/org/partiql/types/PTypeCollection.java index ce1df809d..3cd4c8816 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeCollection.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeCollection.java @@ -4,16 +4,13 @@ import java.util.Objects; -class PTypeCollection implements PType { +class PTypeCollection extends PType { @NotNull final PType _typeParam; - @NotNull - final Kind _kind; - - PTypeCollection(@NotNull Kind base, @NotNull PType typeParam) { - _kind = base; + PTypeCollection(int code, @NotNull PType typeParam) { + super(code); _typeParam = typeParam; } @@ -23,26 +20,20 @@ public PType getTypeParameter() { return _typeParam; } - @NotNull - @Override - public Kind getKind() { - return _kind; - } - @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - return ((PType) o).getKind() == this._kind && ((PType) o).getTypeParameter().equals(_typeParam); + return ((PType) o).code() == this.code() && ((PType) o).getTypeParameter().equals(_typeParam); } @Override public String toString() { - return _kind.name() + "(" + _typeParam + ")"; + return name() + "(" + _typeParam + ")"; } @Override public int hashCode() { - return Objects.hash(_kind, _typeParam); + return Objects.hash(code(), _typeParam); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeDecimal.java b/partiql-types/src/main/java/org/partiql/types/PTypeDecimal.java index 805fc33d2..12beb62a7 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeDecimal.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeDecimal.java @@ -1,25 +1,20 @@ package org.partiql.types; -import org.jetbrains.annotations.NotNull; - import java.util.Objects; -class PTypeDecimal implements PType { +/** + * Relevant to only {@link PType#DECIMAL} and {@link PType#NUMERIC}. + */ +class PTypeDecimal extends PType { final int _precision; final int _scale; - PTypeDecimal(int precision, int scale) { + PTypeDecimal(int code, int precision, int scale) { + super(code); _precision = precision; _scale = scale; } - @NotNull - @Override - public Kind getKind() { - return Kind.DECIMAL; - } - - @Override public int getPrecision() { return _precision; } @@ -33,16 +28,16 @@ public int getScale() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - return ((PType) o).getKind() == Kind.DECIMAL && _precision == ((PType) o).getPrecision() && _scale == ((PType) o).getScale(); + return ((PType) o).code() == code() && _precision == ((PType) o).getPrecision() && _scale == ((PType) o).getScale(); } @Override public String toString() { - return Kind.DECIMAL.name() + "(" + _precision + ", " + _scale + ")"; + return name() + "(" + _precision + ", " + _scale + ")"; } @Override public int hashCode() { - return Objects.hash(Kind.DECIMAL, _precision, _scale); + return Objects.hash(PType.DECIMAL, _precision, _scale); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypePrimitive.java b/partiql-types/src/main/java/org/partiql/types/PTypePrimitive.java index ea92bb213..3497595f7 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypePrimitive.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypePrimitive.java @@ -1,38 +1,27 @@ package org.partiql.types; -import org.jetbrains.annotations.NotNull; - import java.util.Objects; -class PTypePrimitive implements PType { - - @NotNull - final Kind _kind; +class PTypePrimitive extends PType { - PTypePrimitive(@NotNull Kind type) { - _kind = type; - } - - @NotNull - @Override - public Kind getKind() { - return _kind; + PTypePrimitive(int code) { + super(code); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - return _kind == ((PType) o).getKind(); + return code() == ((PType) o).code(); } @Override public String toString() { - return _kind.name(); + return name(); } @Override public int hashCode() { - return Objects.hashCode(_kind); + return Objects.hashCode(code()); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeRow.java b/partiql-types/src/main/java/org/partiql/types/PTypeRow.java index 419b3b87c..82393b7cf 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeRow.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeRow.java @@ -8,22 +8,17 @@ import java.util.stream.Collectors; /** - * Applicable to {@link PType.Kind#ROW}. + * Applicable to {@link PType#ROW}. */ -class PTypeRow implements PType { +class PTypeRow extends PType { final Collection _fields; PTypeRow(@NotNull Collection fields) { + super(PType.ROW); _fields = fields; } - @NotNull - @Override - public Kind getKind() { - return Kind.ROW; - } - @NotNull @Override public Collection getFields() { @@ -34,7 +29,7 @@ public Collection getFields() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - if (Kind.ROW != ((PType) o).getKind()) { + if (PType.ROW != ((PType) o).code()) { return false; } Collection otherFields = ((PType) o).getFields(); @@ -58,11 +53,11 @@ public boolean equals(Object o) { public String toString() { Collection fieldStringList = _fields.stream().map((f) -> f.getName() + ": " + f.getType()).collect(Collectors.toList()); String fieldStrings = String.join(", ", fieldStringList); - return Kind.ROW.name() + "(" + fieldStrings + ")"; + return "ROW(" + fieldStrings + ")"; } @Override public int hashCode() { - return Objects.hash(Kind.ROW, _fields); + return Objects.hash(code(), _fields); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java b/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java index b636bf2e7..c8ac2a8d2 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeVariant.java @@ -1,19 +1,12 @@ package org.partiql.types; -import org.jetbrains.annotations.NotNull; - -class PTypeVariant implements PType { +class PTypeVariant extends PType { + // TODO: Use this somehow private final String encoding; public PTypeVariant(String encoding) { + super(VARIANT); this.encoding = encoding; } - - @NotNull - @Override - public Kind getKind() { - return Kind.VARIANT; - } - } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeWithMaxLength.java b/partiql-types/src/main/java/org/partiql/types/PTypeWithMaxLength.java index 7c6704422..fb97228de 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeWithMaxLength.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeWithMaxLength.java @@ -1,26 +1,16 @@ package org.partiql.types; -import org.jetbrains.annotations.NotNull; - import java.util.Objects; -class PTypeWithMaxLength implements PType { +class PTypeWithMaxLength extends PType { final int _maxLength; - final Kind _kind; - - PTypeWithMaxLength(@NotNull Kind type, int maxLength) { - _kind = type; + PTypeWithMaxLength(int code, int maxLength) { + super(code); _maxLength = maxLength; } - @NotNull - @Override - public Kind getKind() { - return _kind; - } - @Override public int getLength() { return _maxLength; @@ -30,16 +20,16 @@ public int getLength() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - return _kind == ((PType) o).getKind() && _maxLength == ((PType) o).getLength(); + return code() == ((PType) o).code() && _maxLength == ((PType) o).getLength(); } @Override public String toString() { - return _kind.name() + "(" + _maxLength + ")"; + return name() + "(" + _maxLength + ")"; } @Override public int hashCode() { - return Objects.hash(_kind, _maxLength); + return Objects.hash(code(), _maxLength); } } diff --git a/partiql-types/src/main/java/org/partiql/types/PTypeWithPrecisionOnly.java b/partiql-types/src/main/java/org/partiql/types/PTypeWithPrecisionOnly.java index 05b94dc77..4a1916601 100644 --- a/partiql-types/src/main/java/org/partiql/types/PTypeWithPrecisionOnly.java +++ b/partiql-types/src/main/java/org/partiql/types/PTypeWithPrecisionOnly.java @@ -1,28 +1,16 @@ package org.partiql.types; -import org.jetbrains.annotations.NotNull; - import java.util.Objects; -class PTypeWithPrecisionOnly implements PType { +class PTypeWithPrecisionOnly extends PType { final int _precision; - @NotNull - final Kind _kind; - - PTypeWithPrecisionOnly(@NotNull Kind base, int precision) { + PTypeWithPrecisionOnly(int code, int precision) { + super(code); _precision = precision; - _kind = base; - } - - @NotNull - @Override - public Kind getKind() { - return _kind; } - @Override public int getPrecision() { return _precision; } @@ -31,16 +19,16 @@ public int getPrecision() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PType)) return false; - return _kind == ((PType) o).getKind() && _precision == ((PType) o).getPrecision(); + return code() == ((PType) o).code() && _precision == ((PType) o).getPrecision(); } @Override public String toString() { - return _kind.name() + "(" + _precision + ")"; + return name() + "(" + _precision + ")"; } @Override public int hashCode() { - return Objects.hash(_kind, _precision); + return Objects.hash(code(), _precision); } } diff --git a/partiql-types/src/testFixtures/kotlin/org/partiql/types/FromStaticType.kt b/partiql-types/src/testFixtures/kotlin/org/partiql/types/FromStaticType.kt index e006a2878..b7fa411be 100644 --- a/partiql-types/src/testFixtures/kotlin/org/partiql/types/FromStaticType.kt +++ b/partiql-types/src/testFixtures/kotlin/org/partiql/types/FromStaticType.kt @@ -36,7 +36,7 @@ fun fromStaticType(type: StaticType): PType { } else if (type is DecimalType) { val precScale = type.precisionScaleConstraint if (precScale is DecimalType.PrecisionScaleConstraint.Unconstrained) { - return PType.decimal() + return PType.decimal(38, 0) } else if (precScale is DecimalType.PrecisionScaleConstraint.Constrained) { val precisionScaleConstraint = precScale return PType.decimal(precisionScaleConstraint.precision, precisionScaleConstraint.scale) @@ -54,7 +54,7 @@ fun fromStaticType(type: StaticType): PType { } else if (cons == IntType.IntRangeConstraint.LONG) { PType.bigint() } else if (cons == IntType.IntRangeConstraint.UNCONSTRAINED) { - PType.numeric() + PType.numeric(38, 0) } else { throw IllegalStateException() }