diff --git a/src/main/kotlin/kestrel/KestrelException.kt b/src/main/kotlin/kestrel/KestrelException.kt new file mode 100644 index 0000000..395b125 --- /dev/null +++ b/src/main/kotlin/kestrel/KestrelException.kt @@ -0,0 +1,16 @@ +package kestrel + +open class KestrelException(message: String) : RuntimeException(message) + +class LexException( + message: String, + val line: Int, + val column: Int, + val incomplete: Boolean = false +) : KestrelException("$message at line $line, column $column") + +class ParseException( + message: String, + val line: Int, + val column: Int +) : KestrelException("$message at line $line, column $column") diff --git a/src/main/kotlin/kestrel/storage/Row.kt b/src/main/kotlin/kestrel/storage/Row.kt new file mode 100644 index 0000000..90fca45 --- /dev/null +++ b/src/main/kotlin/kestrel/storage/Row.kt @@ -0,0 +1,3 @@ +package kestrel.storage + +data class Row(val values: List) diff --git a/src/main/kotlin/kestrel/storage/Table.kt b/src/main/kotlin/kestrel/storage/Table.kt new file mode 100644 index 0000000..c94be9e --- /dev/null +++ b/src/main/kotlin/kestrel/storage/Table.kt @@ -0,0 +1,7 @@ +package kestrel.storage + +import kestrel.catalog.TableSchema + +class Table(val schema: TableSchema) { + val rows: MutableList = mutableListOf() +} diff --git a/src/main/kotlin/kestrel/storage/Value.kt b/src/main/kotlin/kestrel/storage/Value.kt new file mode 100644 index 0000000..da9aeb2 --- /dev/null +++ b/src/main/kotlin/kestrel/storage/Value.kt @@ -0,0 +1,52 @@ +package kestrel.storage + +enum class ColumnType { + Integer, Text, Boolean, Real; + + val displayName: String + get() = when (this) { + Integer -> "INTEGER" + Text -> "TEXT" + Boolean -> "BOOLEAN" + Real -> "REAL" + } + + companion object { + fun fromKeyword(keyword: String): ColumnType? = when (keyword.uppercase()) { + "INTEGER" -> Integer + "TEXT" -> Text + "BOOLEAN" -> Boolean + "REAL" -> Real + else -> null + } + } +} + +sealed class Value { + abstract val type: ColumnType? + + data class IntegerValue(val value: Long) : Value() { + override val type get() = ColumnType.Integer + } + + data class RealValue(val value: Double) : Value() { + override val type get() = ColumnType.Real + } + + data class TextValue(val value: String) : Value() { + override val type get() = ColumnType.Text + } + + data class BooleanValue(val value: Boolean) : Value() { + override val type get() = ColumnType.Boolean + } + + object NullValue : Value() { + override val type: ColumnType? get() = null + } + + val isNull: Boolean get() = this is NullValue +} + +val Value.typeName: String + get() = type?.displayName ?: "NULL" diff --git a/src/main/kotlin/kestrel/storage/ValueOrdering.kt b/src/main/kotlin/kestrel/storage/ValueOrdering.kt new file mode 100644 index 0000000..f7fb461 --- /dev/null +++ b/src/main/kotlin/kestrel/storage/ValueOrdering.kt @@ -0,0 +1,30 @@ +package kestrel.storage + +object ValueOrdering : Comparator { + override fun compare(left: Value, right: Value): Int = when { + left is Value.NullValue && right is Value.NullValue -> 0 + left is Value.NullValue -> -1 + right is Value.NullValue -> 1 + left is Value.IntegerValue && right is Value.IntegerValue -> left.value.compareTo(right.value) + isNumeric(left) && isNumeric(right) -> asDouble(left).compareTo(asDouble(right)) + left is Value.TextValue && right is Value.TextValue -> left.value.compareTo(right.value) + left is Value.BooleanValue && right is Value.BooleanValue -> left.value.compareTo(right.value) + else -> rank(left).compareTo(rank(right)) + } + + private fun isNumeric(value: Value): Boolean = value is Value.IntegerValue || value is Value.RealValue + + private fun asDouble(value: Value): Double = when (value) { + is Value.IntegerValue -> value.value.toDouble() + is Value.RealValue -> value.value + else -> 0.0 + } + + private fun rank(value: Value): Int = when (value) { + is Value.NullValue -> 0 + is Value.BooleanValue -> 1 + is Value.IntegerValue -> 2 + is Value.RealValue -> 2 + is Value.TextValue -> 3 + } +}