Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Defines spi.datetime classes #1656

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ 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.INTERVAL_DT
import org.partiql.types.PType.INTERVAL_YM
import org.partiql.types.PType.NUMERIC
import org.partiql.types.PType.REAL
import org.partiql.types.PType.SMALLINT
Expand All @@ -29,10 +31,12 @@ 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
import java.math.RoundingMode
import java.time.LocalDate
import java.time.LocalTime
import java.time.ZoneOffset

/**
* Represent the cast operation. This casts an input [Datum] to the target [PType] (returning a potentially new [Datum]).
Expand Down Expand Up @@ -102,9 +106,11 @@ internal object CastTable {
registerString()
registerBag()
registerList()
registerTimestamp()
registerDate()
registerTime()
registerTimestamp()
registerIntervalYM()
registerIntervalDT()
}

private fun String.pad(): String {
Expand Down Expand Up @@ -440,57 +446,49 @@ internal object CastTable {
register(ARRAY, ARRAY) { x, _ -> x }
}

/**
* TODO: Flush this out.
*/
private fun registerTimestamp() {
// WITHOUT TZ
register(TIMESTAMP, VARCHAR) { x, t -> Datum.varchar(x.timestamp.toString(), t.length) }
register(TIMESTAMP, CHAR) { x, t -> Datum.character(x.timestamp.toString(), t.length) }
register(TIMESTAMP, CLOB) { x, t -> Datum.clob(x.timestamp.toString().toByteArray(), t.length) }
register(TIMESTAMP, STRING) { x, _ -> Datum.string(x.timestamp.toString()) }
register(TIMESTAMP, TIMESTAMP) { x, _ -> Datum.timestamp(x.timestamp) }
register(TIMESTAMP, TIMESTAMPZ) { x, _ -> Datum.timestamp(x.timestamp) }
register(TIMESTAMP, TIME) { x, _ -> Datum.time(x.timestamp.toTime()) }
register(TIMESTAMP, DATE) { x, _ -> Datum.date(x.timestamp.toDate()) }
// WITH TZ
register(TIMESTAMPZ, VARCHAR) { x, t -> Datum.varchar(x.timestamp.toString(), t.length) }
register(TIMESTAMPZ, CHAR) { x, t -> Datum.character(x.timestamp.toString(), t.length) }
register(TIMESTAMPZ, CLOB) { x, t -> Datum.clob(x.timestamp.toString().toByteArray(), t.length) }
register(TIMESTAMPZ, STRING) { x, _ -> Datum.string(x.timestamp.toString()) }
register(TIMESTAMPZ, TIMESTAMP) { x, _ -> Datum.timestamp(x.timestamp) }
register(TIMESTAMPZ, TIMESTAMPZ) { x, _ -> Datum.timestamp(x.timestamp) }
register(TIMESTAMPZ, TIME) { x, _ -> Datum.time(x.timestamp.toTime()) }
register(TIMESTAMPZ, DATE) { x, _ -> Datum.date(x.timestamp.toDate()) }
}
private fun registerDate() {
register(DATE, VARCHAR) { x, t -> Datum.varchar(x.date.toString(), t.length) }
register(DATE, CHAR) { x, t -> Datum.character(x.date.toString(), t.length) }
register(DATE, CLOB) { x, t -> Datum.clob(x.date.toString().toByteArray(), t.length) }
register(DATE, STRING) { x, _ -> Datum.string(x.date.toString()) }
register(DATE, DATE) { x, _ -> Datum.date(x.date) }
register(DATE, TIMESTAMP) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(x.date, DateTimeValue.time(0, 0, 0))) }
register(DATE, TIMESTAMPZ) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(x.date, DateTimeValue.time(0, 0, 0))) }
register(DATE, STRING) { x, _ -> Datum.string(x.localDate.toString()) }
register(DATE, DATE) { x, _ -> Datum.date(x.localDate) }
register(DATE, TIMESTAMP) { x, _ -> Datum.timestamp(x.localDate.atTime(LocalTime.MIN), 0) }
register(DATE, TIMESTAMPZ) { x, _ -> Datum.timestampz(x.localDate.atTime(LocalTime.MIN).atOffset(ZoneOffset.UTC), 0) }
}

private fun registerTime() {
// WITHOUT TZ
register(TIME, VARCHAR) { x, t -> Datum.varchar(x.time.toString(), t.length) }
register(TIME, CHAR) { x, t -> Datum.character(x.time.toString(), t.length) }
register(TIME, CLOB) { x, t -> Datum.clob(x.time.toString().toByteArray(), t.length) }
register(TIME, STRING) { x, _ -> Datum.string(x.time.toString()) }
register(TIME, TIME) { x, _ -> Datum.time(x.time) }
register(TIME, TIMESTAMP) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(DateTimeValue.date(1970, 1, 1), x.time)) }
register(TIME, TIMESTAMPZ) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(DateTimeValue.date(1970, 1, 1), x.time)) }
register(TIME, STRING) { x, _ -> Datum.string(x.localTime.toString()) }
register(TIME, TIME) { x, t -> Datum.time(x.localTime, t.precision) }
register(TIME, TIMESTAMP) { x, t -> Datum.timestamp(x.localTime.atDate(LocalDate.now()), t.precision) }
register(TIME, TIMESTAMPZ) { x, t -> Datum.timestampz(x.localTime.atDate(LocalDate.now()).atOffset(ZoneOffset.UTC), t.precision) }
// WITH TZ
register(TIMEZ, STRING) { x, _ -> Datum.string(x.offsetTime.toString()) }
register(TIMEZ, TIME) { x, t -> Datum.time(x.localTime, t.precision) }
register(TIMEZ, TIMESTAMP) { x, t -> Datum.timestamp(x.localTime.atDate(LocalDate.now()), t.precision) }
register(TIMEZ, TIMESTAMPZ) { x, t -> Datum.timestampz(x.offsetTime.atDate(LocalDate.now()), t.precision) }
}

private fun registerTimestamp() {
// WITHOUT TZ
register(TIMESTAMP, STRING) { x, _ -> Datum.string(x.localDateTime.toString()) }
register(TIMESTAMP, TIMESTAMP) { x, t -> Datum.timestamp(x.localDateTime, t.precision) }
register(TIMESTAMP, TIMESTAMPZ) { x, t -> Datum.timestampz(x.localDateTime.atOffset(ZoneOffset.UTC), t.precision) }
register(TIMESTAMP, TIME) { x, t -> Datum.time(x.localTime, t.precision) }
register(TIMESTAMP, DATE) { x, _ -> Datum.date(x.localDate) }
// WITH TZ
register(TIMEZ, VARCHAR) { x, t -> Datum.varchar(x.time.toString(), t.length) }
register(TIMEZ, CHAR) { x, t -> Datum.character(x.time.toString(), t.length) }
register(TIMEZ, CLOB) { x, t -> Datum.clob(x.time.toString().toByteArray(), t.length) }
register(TIMEZ, STRING) { x, _ -> Datum.string(x.time.toString()) }
register(TIMEZ, TIME) { x, _ -> Datum.time(x.time) }
register(TIMEZ, TIMESTAMP) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(DateTimeValue.date(1970, 1, 1), x.time)) }
register(TIMEZ, TIMESTAMPZ) { x, _ -> Datum.timestamp(DateTimeValue.timestamp(DateTimeValue.date(1970, 1, 1), x.time)) }
register(TIMESTAMPZ, STRING) { x, _ -> Datum.string(x.localDateTime.toString()) }
register(TIMESTAMPZ, TIMESTAMP) { x, t -> Datum.timestamp(x.localDateTime, t.precision) }
register(TIMESTAMPZ, TIMESTAMPZ) { x, t -> Datum.timestampz(x.offsetDateTime, t.precision) }
register(TIMESTAMPZ, TIME) { x, t -> Datum.time(x.localTime, t.precision) }
register(TIMESTAMPZ, DATE) { x, _ -> Datum.date(x.localDate) }
}

private fun registerIntervalYM() {
register(INTERVAL_YM, STRING) { x, _ -> Datum.string(x.period.toString()) }
register(INTERVAL_YM, INTERVAL_YM) { x, t -> Datum.interval(x.period, t.precision) }
}

private fun registerIntervalDT() {
register(INTERVAL_DT, STRING) { x, _ -> Datum.string(x.duration.toString()) }
register(INTERVAL_DT, INTERVAL_DT) { x, t -> Datum.interval(x.duration, t.precision) }
}

private fun register(source: Int, target: Int, cast: (Datum, PType) -> Datum) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1734,14 +1734,13 @@ internal class PartiQLParserDefault : PartiQLParser {
} catch (ex: IllegalArgumentException) {
throw error(ctx.dt, "Expected one of: ${DatetimeField.codes().joinToString()}", ex)
}
val part = exprLit(stringValue(ctx.dt.text.lowercase()))
val lhs = visitExpr(ctx.expr(0))
val rhs = visitExpr(ctx.expr(1))
// TODO change to not use PartiQLValue -- https://github.com/partiql/partiql-lang-kotlin/issues/1589
val fieldLit = ctx.dt.text.lowercase()
// TODO error on invalid datetime fields like TIMEZONE_HOUR and TIMEZONE_MINUTE
when {
ctx.DATE_ADD() != null -> exprCall(identifierChain(identifier("date_add_$fieldLit", false), null), listOf(lhs, rhs), null)
ctx.DATE_DIFF() != null -> exprCall(identifierChain(identifier("date_diff_$fieldLit", false), null), listOf(lhs, rhs), null)
ctx.DATE_ADD() != null -> exprCall(identifierChain(identifier("date_add", false), null), listOf(part, lhs, rhs), null)
ctx.DATE_DIFF() != null -> exprCall(identifierChain(identifier("date_diff", false), null), listOf(part, lhs, rhs), null)
else -> throw error(ctx, "Expected DATE_ADD or DATE_DIFF")
}
}
Expand Down
23 changes: 16 additions & 7 deletions partiql-spi/api/partiql-spi.api
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ public final class org/partiql/spi/function/Parameter {
public static final field Companion Lorg/partiql/spi/function/Parameter$Companion;
public fun <init> (Ljava/lang/String;Lorg/partiql/types/PType;)V
public static final fun collection (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public static final fun datetime (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public static final fun dynamic (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public final fun getMatch (Lorg/partiql/types/PType;)Lorg/partiql/types/PType;
public final fun getName ()Ljava/lang/String;
Expand All @@ -450,6 +451,7 @@ public final class org/partiql/spi/function/Parameter {

public final class org/partiql/spi/function/Parameter$Companion {
public final fun collection (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public final fun datetime (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public final fun dynamic (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public final fun number (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
public final fun text (Ljava/lang/String;)Lorg/partiql/spi/function/Parameter;
Expand Down Expand Up @@ -478,7 +480,7 @@ public abstract interface class org/partiql/spi/value/Datum : java/lang/Iterable
public static fun clob ([BI)Lorg/partiql/spi/value/Datum;
public static fun comparator ()Ljava/util/Comparator;
public static fun comparator (Z)Ljava/util/Comparator;
public static fun date (Lorg/partiql/value/datetime/Date;)Lorg/partiql/spi/value/Datum;
public static fun date (Ljava/time/LocalDate;)Lorg/partiql/spi/value/Datum;
public static fun decimal (Ljava/math/BigDecimal;)Lorg/partiql/spi/value/Datum;
public static fun decimal (Ljava/math/BigDecimal;II)Lorg/partiql/spi/value/Datum;
public static fun doublePrecision (D)Lorg/partiql/spi/value/Datum;
Expand All @@ -488,20 +490,25 @@ public abstract interface class org/partiql/spi/value/Datum : java/lang/Iterable
public fun getBoolean ()Z
public fun getByte ()B
public fun getBytes ()[B
public fun getDate ()Lorg/partiql/value/datetime/Date;
public fun getDouble ()D
public fun getDuration ()Ljava/time/Duration;
public fun getFields ()Ljava/util/Iterator;
public fun getFloat ()F
public fun getInsensitive (Ljava/lang/String;)Lorg/partiql/spi/value/Datum;
public fun getInt ()I
public fun getInterval ()J
public fun getLocalDate ()Ljava/time/LocalDate;
public fun getLocalDateTime ()Ljava/time/LocalDateTime;
public fun getLocalTime ()Ljava/time/LocalTime;
public fun getLong ()J
public fun getOffsetDateTime ()Ljava/time/OffsetDateTime;
public fun getOffsetTime ()Ljava/time/OffsetTime;
public fun getPeriod ()Ljava/time/Period;
public fun getShort ()S
public fun getString ()Ljava/lang/String;
public fun getTime ()Lorg/partiql/value/datetime/Time;
public fun getTimestamp ()Lorg/partiql/value/datetime/Timestamp;
public abstract fun getType ()Lorg/partiql/types/PType;
public static fun integer (I)Lorg/partiql/spi/value/Datum;
public static fun interval (Ljava/time/Duration;I)Lorg/partiql/spi/value/Datum;
public static fun interval (Ljava/time/Period;I)Lorg/partiql/spi/value/Datum;
public fun isMissing ()Z
public fun isNull ()Z
public fun iterator ()Ljava/util/Iterator;
Expand All @@ -518,8 +525,10 @@ public abstract interface class org/partiql/spi/value/Datum : java/lang/Iterable
public static fun string (Ljava/lang/String;)Lorg/partiql/spi/value/Datum;
public static fun struct ()Lorg/partiql/spi/value/Datum;
public static fun struct (Ljava/lang/Iterable;)Lorg/partiql/spi/value/Datum;
public static fun time (Lorg/partiql/value/datetime/Time;)Lorg/partiql/spi/value/Datum;
public static fun timestamp (Lorg/partiql/value/datetime/Timestamp;)Lorg/partiql/spi/value/Datum;
public static fun time (Ljava/time/LocalTime;I)Lorg/partiql/spi/value/Datum;
public static fun timestamp (Ljava/time/LocalDateTime;I)Lorg/partiql/spi/value/Datum;
public static fun timestampz (Ljava/time/OffsetDateTime;I)Lorg/partiql/spi/value/Datum;
public static fun timez (Ljava/time/OffsetTime;I)Lorg/partiql/spi/value/Datum;
public static fun tinyint (B)Lorg/partiql/spi/value/Datum;
public fun toPartiQLValue ()Lorg/partiql/value/PartiQLValue;
public static fun varchar (Ljava/lang/String;)Lorg/partiql/spi/value/Datum;
Expand Down
Loading
Loading