Skip to content

Commit

Permalink
Simplifies PType's APIs (#1658)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedquinn authored Nov 27, 2024
1 parent e76d686 commit 443c3eb
Show file tree
Hide file tree
Showing 113 changed files with 2,003 additions and 1,854 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ internal class StandardCompiler(strategies: List<Strategy>) : 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) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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}.")
}
}
Expand All @@ -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()
}
}
Expand All @@ -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()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ internal class RelOpExclude(
/**
* Entry-point to apply exclusions to an arbitrary [Datum].
*/
private fun Datum.exclude(exclusions: List<Exclusion.Item>): 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<Exclusion.Item>): Datum = when (this.type.code()) {
PType.ROW, PType.STRUCT -> this.structExclude(exclusions)
PType.BAG, PType.ARRAY -> this.collExclude(exclusions)
else -> this
}

Expand Down Expand Up @@ -137,9 +137,9 @@ internal class RelOpExclude(
* (i.e. [PartiQLValueType.LIST] or [PartiQLValueType.BAG].).
*/
private fun newCollValue(type: PType, coll: Iterable<Datum>): 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")
}
}
Expand Down Expand Up @@ -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())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Array<Cast?>>

Expand All @@ -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)
Expand All @@ -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
}
}
Expand All @@ -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("|")
}
Expand All @@ -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(' ')
Expand All @@ -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) {
Expand Down Expand Up @@ -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
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ internal class ExprCallDynamic(
private fun match(args: List<PType>): 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) {
Expand Down Expand Up @@ -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")
}
}
}
Expand Down
Loading

0 comments on commit 443c3eb

Please sign in to comment.