diff --git a/partiql-ast/api/partiql-ast.api b/partiql-ast/api/partiql-ast.api index 99902f50ad..6e22c9cb18 100644 --- a/partiql-ast/api/partiql-ast.api +++ b/partiql-ast/api/partiql-ast.api @@ -72,15 +72,6 @@ public final class org/partiql/ast/Ast { public static final fun identifierChain (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/IdentifierChain;)Lorg/partiql/ast/IdentifierChain; public static final fun let (Ljava/util/List;)Lorg/partiql/ast/Let; public static final fun letBinding (Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/Identifier;)Lorg/partiql/ast/Let$Binding; - public static final fun literalBool (Z)Lorg/partiql/ast/literal/LiteralBool; - public static final fun literalDecimal (Ljava/math/BigDecimal;)Lorg/partiql/ast/literal/LiteralDecimal; - public static final fun literalFloat (Ljava/lang/String;)Lorg/partiql/ast/literal/LiteralDouble; - public static final fun literalInt (I)Lorg/partiql/ast/literal/LiteralInt; - public static final fun literalLong (J)Lorg/partiql/ast/literal/LiteralLong; - public static final fun literalMissing ()Lorg/partiql/ast/literal/LiteralMissing; - public static final fun literalNull ()Lorg/partiql/ast/literal/LiteralNull; - public static final fun literalString (Ljava/lang/String;)Lorg/partiql/ast/literal/LiteralString; - public static final fun literalTypedString (Lorg/partiql/ast/DataType;Ljava/lang/String;)Lorg/partiql/ast/literal/LiteralTypedString; public static final fun orderBy (Ljava/util/List;)Lorg/partiql/ast/OrderBy; public static final fun query (Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/Query; public static final fun queryBodySFW (Lorg/partiql/ast/Select;Lorg/partiql/ast/Exclude;Lorg/partiql/ast/From;Lorg/partiql/ast/Let;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/GroupBy;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/QueryBody$SFW; @@ -2396,58 +2387,52 @@ public abstract class org/partiql/ast/literal/Literal { public abstract fun getText ()Ljava/lang/String; } -public class org/partiql/ast/literal/LiteralBool : org/partiql/ast/literal/Literal { - public field value Z - public fun (Z)V - protected fun canEqual (Ljava/lang/Object;)Z - public fun equals (Ljava/lang/Object;)Z - public fun getText ()Ljava/lang/String; - public fun hashCode ()I -} - -public class org/partiql/ast/literal/LiteralDecimal : org/partiql/ast/literal/Literal { - public field value Ljava/math/BigDecimal; - public fun (Ljava/math/BigDecimal;)V +public class org/partiql/ast/literal/LiteralApprox : org/partiql/ast/literal/Literal { protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z + public fun getDouble ()D public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litApprox (D)Lorg/partiql/ast/literal/LiteralApprox; + public static fun litApprox (F)Lorg/partiql/ast/literal/LiteralApprox; + public static fun litApprox (Ljava/math/BigDecimal;)Lorg/partiql/ast/literal/LiteralApprox; + public static fun litApprox (Ljava/math/BigDecimal;I)Lorg/partiql/ast/literal/LiteralApprox; } -public class org/partiql/ast/literal/LiteralDouble : org/partiql/ast/literal/Literal { - public field text Ljava/lang/String; - public field value D - public fun (Ljava/lang/String;)V +public class org/partiql/ast/literal/LiteralBool : org/partiql/ast/literal/Literal { + public field value Z protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litBool (Z)Lorg/partiql/ast/literal/LiteralBool; } -public class org/partiql/ast/literal/LiteralInt : org/partiql/ast/literal/Literal { - public field value I - public fun (I)V +public class org/partiql/ast/literal/LiteralExact : org/partiql/ast/literal/Literal { protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z + public fun getDecimal ()Ljava/math/BigDecimal; public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litExact (Ljava/math/BigDecimal;)Lorg/partiql/ast/literal/LiteralExact; } -public class org/partiql/ast/literal/LiteralLong : org/partiql/ast/literal/Literal { - public field value J - public fun (J)V +public class org/partiql/ast/literal/LiteralInteger : org/partiql/ast/literal/Literal { protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z + public fun getInteger ()J public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litInt (I)Lorg/partiql/ast/literal/LiteralInteger; + public static fun litInt (J)Lorg/partiql/ast/literal/LiteralInteger; } public class org/partiql/ast/literal/LiteralMissing : org/partiql/ast/literal/Literal { - public fun ()V protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litMissing ()Lorg/partiql/ast/literal/LiteralMissing; } public class org/partiql/ast/literal/LiteralNull : org/partiql/ast/literal/Literal { @@ -2456,25 +2441,26 @@ public class org/partiql/ast/literal/LiteralNull : org/partiql/ast/literal/Liter public fun equals (Ljava/lang/Object;)Z public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litNull ()Lorg/partiql/ast/literal/LiteralNull; } public class org/partiql/ast/literal/LiteralString : org/partiql/ast/literal/Literal { public field value Ljava/lang/String; - public fun (Ljava/lang/String;)V protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litString (Ljava/lang/String;)Lorg/partiql/ast/literal/LiteralString; } public class org/partiql/ast/literal/LiteralTypedString : org/partiql/ast/literal/Literal { public field type Lorg/partiql/ast/DataType; public field value Ljava/lang/String; - public fun (Lorg/partiql/ast/DataType;Ljava/lang/String;)V protected fun canEqual (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z public fun getText ()Ljava/lang/String; public fun hashCode ()I + public static fun litTypedString (Lorg/partiql/ast/DataType;Ljava/lang/String;)Lorg/partiql/ast/literal/LiteralTypedString; } public abstract class org/partiql/ast/sql/SqlBlock { diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralApprox.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralApprox.java new file mode 100644 index 0000000000..73ed9a2c81 --- /dev/null +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralApprox.java @@ -0,0 +1,52 @@ +package org.partiql.ast.literal; + +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; + +import java.math.BigDecimal; + +/** + * TODO docs + */ +@EqualsAndHashCode(callSuper = false) +public class LiteralApprox extends Literal { + @NotNull + private final BigDecimal mantissa; + + private final int exponent; + + private LiteralApprox(@NotNull BigDecimal mantissa, int exponent) { + this.mantissa = mantissa; + this.exponent = exponent; + } + + @NotNull + public static LiteralApprox litApprox(BigDecimal mantissa, int exponent) { + return new LiteralApprox(mantissa, exponent); + } + + @NotNull + public static LiteralApprox litApprox(BigDecimal value) { + return new LiteralApprox(value, 0); + } + + @NotNull + public static LiteralApprox litApprox(float value) { + return litApprox(BigDecimal.valueOf(value)); + } + + @NotNull + public static LiteralApprox litApprox(double value) { + return litApprox(BigDecimal.valueOf(value)); + } + + public double getDouble() { + return mantissa.scaleByPowerOfTen(exponent).doubleValue(); + } + + @NotNull + @Override + public String getText() { + return mantissa + "E" + exponent; + } +} diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralBool.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralBool.java index 5dcc83ea4d..07084c153c 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralBool.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralBool.java @@ -10,10 +10,15 @@ public class LiteralBool extends Literal { public boolean value; - public LiteralBool(boolean value) { + private LiteralBool(boolean value) { this.value = value; } + @NotNull + public static LiteralBool litBool(boolean value) { + return new LiteralBool(value); + } + @NotNull @Override public String getText() { diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDouble.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDouble.java deleted file mode 100644 index ad79eb48e6..0000000000 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDouble.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.partiql.ast.literal; - -import lombok.EqualsAndHashCode; -import org.jetbrains.annotations.NotNull; - -/** - * TODO docs - */ -@EqualsAndHashCode(callSuper = false) -public class LiteralDouble extends Literal { - public double value; - - @NotNull - public String text; - - public LiteralDouble(@NotNull String text) { - this.text = text; - this.value = Double.parseDouble(text); - } - - @NotNull - @Override - public String getText() { - return text; - } -} diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDecimal.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralExact.java similarity index 50% rename from partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDecimal.java rename to partiql-ast/src/main/java/org/partiql/ast/literal/LiteralExact.java index c66ad19ce1..22c78c50c3 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralDecimal.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralExact.java @@ -9,14 +9,24 @@ * TODO DOCS */ @EqualsAndHashCode(callSuper = false) -public class LiteralDecimal extends Literal { +public class LiteralExact extends Literal { @NotNull - public BigDecimal value; + private final BigDecimal value; - public LiteralDecimal(@NotNull BigDecimal value) { + private LiteralExact(@NotNull BigDecimal value) { this.value = value; } + @NotNull + public static LiteralExact litExact(BigDecimal value) { + return new LiteralExact(value); + } + + @NotNull + public BigDecimal getDecimal() { + return value; + } + @NotNull @Override public String getText() { diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInt.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInt.java deleted file mode 100644 index fa0da3308d..0000000000 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInt.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.partiql.ast.literal; - -import lombok.EqualsAndHashCode; -import org.jetbrains.annotations.NotNull; - -/** - * TODO docs - */ -@EqualsAndHashCode(callSuper = false) -public class LiteralInt extends Literal { - public int value; - - public LiteralInt(int value) { - this.value = value; - } - - @NotNull - @Override - public String getText() { - return Integer.toString(value); - } -} diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInteger.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInteger.java new file mode 100644 index 0000000000..c917240c12 --- /dev/null +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralInteger.java @@ -0,0 +1,36 @@ +package org.partiql.ast.literal; + +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; + +/** + * TODO docs + */ +@EqualsAndHashCode(callSuper = false) +public class LiteralInteger extends Literal { + private final long value; + + private LiteralInteger(long value) { + this.value = value; + } + + @NotNull + public static LiteralInteger litInt(long value) { + return new LiteralInteger(value); + } + + @NotNull + public static LiteralInteger litInt(int value) { + return new LiteralInteger(value); + } + + public long getInteger() { + return value; + } + + @NotNull + @Override + public String getText() { + return Long.toString(value); + } +} diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralLong.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralLong.java deleted file mode 100644 index 2441d5b77f..0000000000 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralLong.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.partiql.ast.literal; - -import lombok.EqualsAndHashCode; -import org.jetbrains.annotations.NotNull; - -/** - * TODO docs - */ -@EqualsAndHashCode(callSuper = false) -public class LiteralLong extends Literal { - public long value; - - public LiteralLong(long value) { - this.value = value; - } - - @NotNull - @Override - public String getText() { - return Long.toString(value); - } -} diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralMissing.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralMissing.java index b94eac55f8..dd53260bf4 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralMissing.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralMissing.java @@ -8,7 +8,12 @@ */ @EqualsAndHashCode(callSuper = false) public class LiteralMissing extends Literal { - public LiteralMissing() {} + private LiteralMissing() {} + + @NotNull + public static LiteralMissing litMissing() { + return new LiteralMissing(); + } @NotNull @Override diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralNull.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralNull.java index 3a3add573f..25826cb251 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralNull.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralNull.java @@ -10,6 +10,11 @@ public class LiteralNull extends Literal { public LiteralNull() {} + @NotNull + public static LiteralNull litNull() { + return new LiteralNull(); + } + @NotNull @Override public String getText() { diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralString.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralString.java index f2a01932a5..a2bb04c441 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralString.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralString.java @@ -11,10 +11,15 @@ public class LiteralString extends Literal { @NotNull public String value; - public LiteralString(@NotNull String value) { + private LiteralString(@NotNull String value) { this.value = value; } + @NotNull + public static LiteralString litString(@NotNull String value) { + return new LiteralString(value); + } + @NotNull @Override public String getText() { diff --git a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralTypedString.java b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralTypedString.java index f904312786..f31f997fa1 100644 --- a/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralTypedString.java +++ b/partiql-ast/src/main/java/org/partiql/ast/literal/LiteralTypedString.java @@ -16,11 +16,16 @@ public class LiteralTypedString extends Literal { @NotNull public String value; - public LiteralTypedString(@NotNull DataType type, @NotNull String value) { + private LiteralTypedString(@NotNull DataType type, @NotNull String value) { this.type = type; this.value = value; } + @NotNull + public static LiteralTypedString litTypedString(@NotNull DataType type, @NotNull String value) { + return new LiteralTypedString(type, value); + } + @NotNull @Override public String getText() { diff --git a/partiql-ast/src/main/kotlin/org/partiql/ast/Ast.kt b/partiql-ast/src/main/kotlin/org/partiql/ast/Ast.kt index b574cb08bc..6567c23167 100644 --- a/partiql-ast/src/main/kotlin/org/partiql/ast/Ast.kt +++ b/partiql-ast/src/main/kotlin/org/partiql/ast/Ast.kt @@ -48,16 +48,6 @@ import org.partiql.ast.graph.GraphQuantifier import org.partiql.ast.graph.GraphRestrictor import org.partiql.ast.graph.GraphSelector import org.partiql.ast.literal.Literal -import org.partiql.ast.literal.LiteralBool -import org.partiql.ast.literal.LiteralDecimal -import org.partiql.ast.literal.LiteralDouble -import org.partiql.ast.literal.LiteralInt -import org.partiql.ast.literal.LiteralLong -import org.partiql.ast.literal.LiteralMissing -import org.partiql.ast.literal.LiteralNull -import org.partiql.ast.literal.LiteralString -import org.partiql.ast.literal.LiteralTypedString -import java.math.BigDecimal // TODO docs for all factory methods // Also consider defaults for nullable. Need to look more into backwards compatibility. @@ -363,52 +353,6 @@ public object Ast { return GraphSelector.ShortestKGroup(k) } - // Literal - @JvmStatic - public fun literalBool(value: Boolean): LiteralBool { - return LiteralBool(value) - } - - @JvmStatic - public fun literalDecimal(value: BigDecimal): LiteralDecimal { - return LiteralDecimal(value) - } - - @JvmStatic - public fun literalFloat(text: String): LiteralDouble { - return LiteralDouble(text) - } - - @JvmStatic - public fun literalInt(value: Int): LiteralInt { - return LiteralInt(value) - } - - @JvmStatic - public fun literalLong(value: Long): LiteralLong { - return LiteralLong(value) - } - - @JvmStatic - public fun literalNull(): LiteralNull { - return LiteralNull() - } - - @JvmStatic - public fun literalMissing(): LiteralMissing { - return LiteralMissing() - } - - @JvmStatic - public fun literalString(value: String): LiteralString { - return LiteralString(value) - } - - @JvmStatic - public fun literalTypedString(type: DataType, value: String): LiteralTypedString { - return LiteralTypedString(type, value) - } - // Other @JvmStatic public fun exclude(excludePaths: List): Exclude { diff --git a/partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt b/partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt index 81d4bb4dcc..1ce701785b 100644 --- a/partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt +++ b/partiql-ast/src/test/kotlin/org/partiql/ast/sql/SqlDialectTest.kt @@ -61,15 +61,6 @@ import org.partiql.ast.Ast.groupByKey import org.partiql.ast.Ast.identifier import org.partiql.ast.Ast.identifierChain import org.partiql.ast.Ast.letBinding -import org.partiql.ast.Ast.literalBool -import org.partiql.ast.Ast.literalDecimal -import org.partiql.ast.Ast.literalFloat -import org.partiql.ast.Ast.literalInt -import org.partiql.ast.Ast.literalLong -import org.partiql.ast.Ast.literalMissing -import org.partiql.ast.Ast.literalNull -import org.partiql.ast.Ast.literalString -import org.partiql.ast.Ast.literalTypedString import org.partiql.ast.Ast.orderBy import org.partiql.ast.Ast.queryBodySFW import org.partiql.ast.Ast.queryBodySetOp @@ -103,6 +94,14 @@ import org.partiql.ast.SetQuantifier import org.partiql.ast.expr.Expr import org.partiql.ast.expr.Scope import org.partiql.ast.expr.TrimSpec +import org.partiql.ast.literal.LiteralApprox.litApprox +import org.partiql.ast.literal.LiteralBool.litBool +import org.partiql.ast.literal.LiteralExact.litExact +import org.partiql.ast.literal.LiteralInteger.litInt +import org.partiql.ast.literal.LiteralMissing.litMissing +import org.partiql.ast.literal.LiteralNull.litNull +import org.partiql.ast.literal.LiteralString.litString +import org.partiql.ast.literal.LiteralTypedString.litTypedString import java.math.BigDecimal import kotlin.test.assertFails @@ -233,7 +232,7 @@ class SqlDialectTest { companion object { - private val NULL = exprLit(literalNull()) + private val NULL = exprLit(litNull()) @JvmStatic fun types() = listOf( @@ -406,49 +405,49 @@ class SqlDialectTest { @JvmStatic fun exprLitCases() = listOf( expect( - "NULL", exprLit(literalNull()) + "NULL", exprLit(litNull()) ), expect( - "MISSING", exprLit(literalMissing()) + "MISSING", exprLit(litMissing()) ), expect( - "true", exprLit(literalBool(true)) + "true", exprLit(litBool(true)) ), expect( - "1", exprLit(literalInt(1)) + "1", exprLit(litInt(1)) ), expect( - "2", exprLit(literalInt(2)) + "2", exprLit(litInt(2)) ), expect( - "3", exprLit(literalInt(3)) + "3", exprLit(litInt(3)) ), expect( - "4", exprLit(literalLong(4)) + "4", exprLit(litInt(4)) ), expect( - "5", exprLit(literalDecimal(BigDecimal.valueOf(5))) + "5", exprLit(litExact(BigDecimal.valueOf(5))) ), - expect("1.1e0", exprLit(literalFloat("1.1e0"))), - expect("1.2e0", exprLit(literalFloat("1.2e0"))), - expect("1.2345E-5", exprLit(literalFloat("1.2345E-5"))), + expect("1.1E0", exprLit(litApprox(1.1))), + expect("1.2E0", exprLit(litApprox(1.2))), + expect("1.2345E-5", exprLit(litApprox(BigDecimal.valueOf(1.2345), -5))), expect( - "1.3", exprLit(literalDecimal(BigDecimal.valueOf(1.3))) + "1.3", exprLit(litExact(BigDecimal.valueOf(1.3))) ), expect( - """'hello'""", exprLit(literalString("hello")) + """'hello'""", exprLit(litString("hello")) ), expect( """hello""", id("hello") ), expect( - "DATE '0001-02-03'", exprLit(literalTypedString(DataType.DATE(), "0001-02-03")) + "DATE '0001-02-03'", exprLit(litTypedString(DataType.DATE(), "0001-02-03")) ), expect( - "TIME '01:02:03.456-00:30'", exprLit(literalTypedString(DataType.TIME(), "01:02:03.456-00:30")) + "TIME '01:02:03.456-00:30'", exprLit(litTypedString(DataType.TIME(), "01:02:03.456-00:30")) ), expect( - "TIMESTAMP '0001-02-03 04:05:06.78-00:30'", exprLit(literalTypedString(DataType.TIMESTAMP(), "0001-02-03 04:05:06.78-00:30")) + "TIMESTAMP '0001-02-03 04:05:06.78-00:30'", exprLit(litTypedString(DataType.TIMESTAMP(), "0001-02-03 04:05:06.78-00:30")) ), // expect("""{{ '''Hello''' '''World''' }}""") { @@ -681,7 +680,7 @@ class SqlDialectTest { next = exprPathStepElement( element = exprOperator( symbol = "+", - lhs = exprLit(literalInt(1)), + lhs = exprLit(litInt(1)), rhs = exprVarRef( identifierChain = idChain(id("a")), scope = Scope.DEFAULT() @@ -698,7 +697,7 @@ class SqlDialectTest { identifierChain = idChain(id("x")), scope = Scope.DEFAULT() ), - next = exprPathStepElement(exprLit(literalString("y")), next = null) + next = exprPathStepElement(exprLit(litString("y")), next = null) ) ), ) @@ -709,7 +708,7 @@ class SqlDialectTest { "foo(1)", exprCall( function = idChain(id("foo")), - args = listOf(exprLit(literalInt(1))), + args = listOf(exprLit(litInt(1))), setq = null ) ), @@ -718,8 +717,8 @@ class SqlDialectTest { exprCall( function = idChain(id("foo")), args = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)), + exprLit(litInt(1)), + exprLit(litInt(2)), ), setq = null ) @@ -731,7 +730,7 @@ class SqlDialectTest { root = id("foo"), next = idChain(id("bar")) ), - args = listOf(exprLit(literalInt(1))), + args = listOf(exprLit(litInt(1))), setq = null ) ), @@ -743,8 +742,8 @@ class SqlDialectTest { next = idChain(id("bar")) ), args = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)) + exprLit(litInt(1)), + exprLit(litInt(2)) ), setq = null ) @@ -830,9 +829,9 @@ class SqlDialectTest { "<<1, 2, 3>>", exprBag( values = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)), - exprLit(literalInt(3)) + exprLit(litInt(1)), + exprLit(litInt(2)), + exprLit(litInt(3)) ) ) ), @@ -844,9 +843,9 @@ class SqlDialectTest { "[1, 2, 3]", exprArray( values = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)), - exprLit(literalInt(3)) + exprLit(litInt(1)), + exprLit(litInt(2)), + exprLit(litInt(3)) ) ) ), @@ -866,9 +865,9 @@ class SqlDialectTest { rows = listOf( exprRowValue( values = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)), - exprLit(literalInt(3)) + exprLit(litInt(1)), + exprLit(litInt(2)), + exprLit(litInt(3)) ) ) ) @@ -884,9 +883,9 @@ class SqlDialectTest { "(1, 2, 3)", exprRowValue( values = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)), - exprLit(literalInt(3)) + exprLit(litInt(1)), + exprLit(litInt(2)), + exprLit(litInt(3)) ) ) ), @@ -901,9 +900,9 @@ class SqlDialectTest { // "SEXP (1, 2, 3)", // exprCollection { // type = Expr.Collection.Type.SEXP -// values += exprLit(literalInt(1)) -// values += exprLit(literalInt(2)) -// values += exprLit(literalInt(3)) +// values += exprLit(integer(1)) +// values += exprLit(integer(2)) +// values += exprLit(integer(3)) // } // ), ) @@ -917,7 +916,7 @@ class SqlDialectTest { fields = listOf( exprStructField( name = v("a"), - value = exprLit(literalInt(1)) + value = exprLit(litInt(1)) ) ) ) @@ -928,11 +927,11 @@ class SqlDialectTest { fields = listOf( exprStructField( name = v("a"), - value = exprLit(literalInt(1)) + value = exprLit(litInt(1)) ), exprStructField( name = v("b"), - value = exprLit(literalBool(false)) + value = exprLit(litBool(false)) ) ) ) @@ -1139,7 +1138,7 @@ class SqlDialectTest { exprCall( function = idChain(id("DATE_ADD")), args = listOf( - exprLit(literalString("MINUTE")), + exprLit(litString("MINUTE")), v("x"), v("y") ), @@ -1151,7 +1150,7 @@ class SqlDialectTest { exprCall( function = idChain(id("DATE_DIFF")), args = listOf( - exprLit(literalString("MINUTE")), + exprLit(litString("MINUTE")), v("x"), v("y") ), @@ -1948,7 +1947,7 @@ class SqlDialectTest { select = select("a"), from = table("T") ), - limit = exprLit(literalInt(1)) + limit = exprLit(litInt(1)) ) ), expect( @@ -1958,7 +1957,7 @@ class SqlDialectTest { select = select("a"), from = table("T") ), - offset = exprLit(literalInt(2)) + offset = exprLit(litInt(2)) ) ), expect( @@ -1968,8 +1967,8 @@ class SqlDialectTest { select = select("a"), from = table("T") ), - limit = exprLit(literalInt(1)), - offset = exprLit(literalInt(2)) + limit = exprLit(litInt(1)), + offset = exprLit(litInt(2)) ) ), expect( @@ -2390,7 +2389,7 @@ class SqlDialectTest { ) ) ), - limit = exprLit(literalInt(1)) // LIMIT associated with SQL set op + limit = exprLit(litInt(1)) // LIMIT associated with SQL set op ) ), expect( @@ -2410,7 +2409,7 @@ class SqlDialectTest { select = select("b"), from = table("S"), ), - limit = exprLit(literalInt(1)) // LIMIT associated with rhs SFW query + limit = exprLit(litInt(1)) // LIMIT associated with rhs SFW query ) ) ) @@ -2538,7 +2537,7 @@ class SqlDialectTest { "1 = (SELECT a FROM T)", exprOperator( symbol = "=", - lhs = exprLit(literalInt(1)), + lhs = exprLit(litInt(1)), rhs = qSet( body = sfw( select = select("a"), @@ -2553,8 +2552,8 @@ class SqlDialectTest { symbol = "=", lhs = exprRowValue( values = listOf( - exprLit(literalInt(1)), - exprLit(literalInt(2)) + exprLit(litInt(1)), + exprLit(litInt(2)) ) ), rhs = qSet( diff --git a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt index 7f5a09d851..8a90519b03 100644 --- a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt +++ b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt @@ -100,15 +100,6 @@ import org.partiql.ast.Ast.groupByKey import org.partiql.ast.Ast.identifier import org.partiql.ast.Ast.identifierChain import org.partiql.ast.Ast.letBinding -import org.partiql.ast.Ast.literalBool -import org.partiql.ast.Ast.literalDecimal -import org.partiql.ast.Ast.literalFloat -import org.partiql.ast.Ast.literalInt -import org.partiql.ast.Ast.literalLong -import org.partiql.ast.Ast.literalMissing -import org.partiql.ast.Ast.literalNull -import org.partiql.ast.Ast.literalString -import org.partiql.ast.Ast.literalTypedString import org.partiql.ast.Ast.orderBy import org.partiql.ast.Ast.query import org.partiql.ast.Ast.queryBodySFW @@ -161,6 +152,14 @@ import org.partiql.ast.graph.GraphPattern import org.partiql.ast.graph.GraphQuantifier import org.partiql.ast.graph.GraphRestrictor import org.partiql.ast.graph.GraphSelector +import org.partiql.ast.literal.LiteralApprox.litApprox +import org.partiql.ast.literal.LiteralBool.litBool +import org.partiql.ast.literal.LiteralExact.litExact +import org.partiql.ast.literal.LiteralInteger.litInt +import org.partiql.ast.literal.LiteralMissing.litMissing +import org.partiql.ast.literal.LiteralNull.litNull +import org.partiql.ast.literal.LiteralString.litString +import org.partiql.ast.literal.LiteralTypedString.litTypedString import org.partiql.parser.PartiQLLexerException import org.partiql.parser.PartiQLParser import org.partiql.parser.PartiQLParserException @@ -210,7 +209,7 @@ internal class PartiQLParserDefault : PartiQLParser { ctx.errorListener.report(error) val locations = SourceLocations() return PartiQLParser.Result( - mutableListOf(org.partiql.ast.Query(exprLit(literalNull()))) as List, + mutableListOf(org.partiql.ast.Query(exprLit(litNull()))) as List, locations ) } @@ -453,8 +452,8 @@ internal class PartiQLParserDefault : PartiQLParser { } explain( options = mapOf( - "type" to (type?.let { literalString(it) } ?: literalNull()), - "format" to (format?.let { literalString(it) } ?: literalNull()) + "type" to (type?.let { litString(it) } ?: litNull()), + "format" to (format?.let { litString(it) } ?: litNull()) ), statement = visit(ctx.statement()) as Statement, ) @@ -1764,12 +1763,16 @@ internal class PartiQLParserDefault : PartiQLParser { } catch (e: NumberFormatException) { throw error(ctx, "Invalid decimal literal", e) } - exprLit(literalDecimal(decimal)) + exprLit(litExact(decimal)) } override fun visitLiteralFloat(ctx: GeneratedParser.LiteralFloatContext) = translate(ctx) { val v = ctx.LITERAL_FLOAT().text.trim() - exprLit(literalFloat(v)) + val parts = v.split(Regex("[eE]")) + assert(parts.size == 2) + val mantissa = parts[0].trim() + val exponent = parts[1].trim() + exprLit(litApprox(BigDecimal(mantissa, MathContext(38, RoundingMode.HALF_EVEN)), exponent.toInt())) } override fun visitArray(ctx: GeneratedParser.ArrayContext) = translate(ctx) { @@ -1778,19 +1781,19 @@ internal class PartiQLParserDefault : PartiQLParser { } override fun visitLiteralNull(ctx: GeneratedParser.LiteralNullContext) = translate(ctx) { - exprLit(literalNull()) + exprLit(litNull()) } override fun visitLiteralMissing(ctx: GeneratedParser.LiteralMissingContext) = translate(ctx) { - exprLit(literalMissing()) + exprLit(litMissing()) } override fun visitLiteralTrue(ctx: GeneratedParser.LiteralTrueContext) = translate(ctx) { - exprLit(literalBool(value = true)) + exprLit(litBool(true)) } override fun visitLiteralFalse(ctx: GeneratedParser.LiteralFalseContext) = translate(ctx) { - exprLit(literalBool(value = false)) + exprLit(litBool(false)) } override fun visitLiteralIon(ctx: GeneratedParser.LiteralIonContext) = translate(ctx) { @@ -1801,31 +1804,23 @@ internal class PartiQLParserDefault : PartiQLParser { override fun visitLiteralString(ctx: GeneratedParser.LiteralStringContext) = translate(ctx) { val value = ctx.LITERAL_STRING().getStringValue() - exprLit(literalString(value)) + exprLit(litString(value)) } override fun visitLiteralInteger(ctx: GeneratedParser.LiteralIntegerContext) = translate(ctx) { val n = ctx.LITERAL_INTEGER().text - // 1st, try parse as int32 - try { - val v = n.toInt(10) - return@translate exprLit(literalInt((v))) - } catch (ex: NumberFormatException) { - // ignore - } - - // 2nd, try parse as int64 + // 1st, try parse as int64 try { val v = n.toLong(10) - return@translate exprLit(literalLong(v)) + return@translate exprLit(litInt(v)) } catch (ex: NumberFormatException) { // ignore } - // 3rd, try parse as numeric (decimal) + // 2nd, try parse as numeric (decimal) try { val dec = BigDecimal(n, MathContext(38, RoundingMode.HALF_EVEN)) - return@translate exprLit(literalDecimal(dec)) + return@translate exprLit(litExact(dec)) } catch (ex: NumberFormatException) { throw ex } @@ -1837,7 +1832,7 @@ internal class PartiQLParserDefault : PartiQLParser { if (DATE_PATTERN_REGEX.matches(dateString).not()) { throw error(pattern, "Expected DATE string to be of the format yyyy-MM-dd") } - exprLit(literalTypedString(type = DataType.DATE(), dateString)) + exprLit(litTypedString(DataType.DATE(), dateString)) } override fun visitLiteralTime(ctx: GeneratedParser.LiteralTimeContext) = translate(ctx) { @@ -1858,7 +1853,7 @@ internal class PartiQLParserDefault : PartiQLParser { } } } - exprLit(literalTypedString(type = type, timeString)) + exprLit(litTypedString(type, timeString)) } override fun visitLiteralTimestamp(ctx: GeneratedParser.LiteralTimestampContext) = translate(ctx) { @@ -1879,7 +1874,7 @@ internal class PartiQLParserDefault : PartiQLParser { } } } - exprLit(literalTypedString(type = type, timestampString)) + exprLit(litTypedString(type, timestampString)) } override fun visitTuple(ctx: GeneratedParser.TupleContext) = translate(ctx) { diff --git a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserBagOpTests.kt b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserBagOpTests.kt index ea8c04650a..ac45299c79 100644 --- a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserBagOpTests.kt +++ b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserBagOpTests.kt @@ -8,8 +8,6 @@ import org.partiql.ast.Ast.exprStruct import org.partiql.ast.Ast.exprStructField import org.partiql.ast.Ast.from import org.partiql.ast.Ast.fromExpr -import org.partiql.ast.Ast.literalInt -import org.partiql.ast.Ast.literalString import org.partiql.ast.Ast.query import org.partiql.ast.Ast.queryBodySFW import org.partiql.ast.Ast.queryBodySetOp @@ -21,6 +19,8 @@ import org.partiql.ast.SetOpType import org.partiql.ast.SetQuantifier import org.partiql.ast.expr.Expr import org.partiql.ast.expr.ExprQuerySet +import org.partiql.ast.literal.LiteralInteger.litInt +import org.partiql.ast.literal.LiteralString.litString import kotlin.test.assertEquals class PartiQLParserBagOpTests { @@ -41,8 +41,8 @@ class PartiQLParserBagOpTests { exprStruct( fields = mutableListOf( exprStructField( - name = exprLit(literalString("a")), - value = exprLit(literalInt(i)) + name = exprLit(litString("a")), + value = exprLit(litInt(i)) ) ) ) @@ -65,7 +65,7 @@ class PartiQLParserBagOpTests { offset = null ) - private fun createLit(i: Int) = exprLit(literalInt(i)) + private fun createLit(i: Int) = exprLit(litInt(i)) // SQL Union @Test diff --git a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserOperatorTests.kt b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserOperatorTests.kt index 884be4bddd..bb2eaa9f09 100644 --- a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserOperatorTests.kt +++ b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserOperatorTests.kt @@ -3,10 +3,10 @@ package org.partiql.parser.internal import org.junit.jupiter.api.Test import org.partiql.ast.Ast.exprLit import org.partiql.ast.Ast.exprOperator -import org.partiql.ast.Ast.literalInt import org.partiql.ast.Ast.query import org.partiql.ast.AstNode import org.partiql.ast.expr.Expr +import org.partiql.ast.literal.LiteralInteger.litInt import kotlin.test.assertEquals class PartiQLParserOperatorTests { @@ -22,7 +22,7 @@ class PartiQLParserOperatorTests { exprOperator( symbol = "-", lhs = null, - rhs = exprLit(literalInt(2)) + rhs = exprLit(litInt(2)) ) } ) @@ -33,8 +33,8 @@ class PartiQLParserOperatorTests { queryBody { exprOperator( symbol = "<=", - lhs = exprLit(literalInt(1)), - rhs = exprLit(literalInt(2)) + lhs = exprLit(litInt(1)), + rhs = exprLit(litInt(2)) ) } ) @@ -46,7 +46,7 @@ class PartiQLParserOperatorTests { exprOperator( symbol = "==!", lhs = null, - rhs = exprLit(literalInt(2)) + rhs = exprLit(litInt(2)) ) } ) @@ -57,8 +57,8 @@ class PartiQLParserOperatorTests { queryBody { exprOperator( symbol = "==!", - lhs = exprLit(literalInt(1)), - rhs = exprLit(literalInt(2)) + lhs = exprLit(litInt(1)), + rhs = exprLit(litInt(2)) ) } ) diff --git a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserSessionAttributeTests.kt b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserSessionAttributeTests.kt index 266475294f..de31ac8017 100644 --- a/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserSessionAttributeTests.kt +++ b/partiql-parser/src/test/kotlin/org/partiql/parser/internal/PartiQLParserSessionAttributeTests.kt @@ -4,11 +4,11 @@ import org.junit.jupiter.api.Test import org.partiql.ast.Ast.exprLit import org.partiql.ast.Ast.exprOperator import org.partiql.ast.Ast.exprSessionAttribute -import org.partiql.ast.Ast.literalInt import org.partiql.ast.Ast.query import org.partiql.ast.AstNode import org.partiql.ast.expr.Expr import org.partiql.ast.expr.SessionAttribute +import org.partiql.ast.literal.LiteralInteger.litInt import kotlin.test.assertEquals class PartiQLParserSessionAttributeTests { @@ -47,7 +47,7 @@ class PartiQLParserSessionAttributeTests { queryBody { exprOperator( symbol = "=", - lhs = exprLit(literalInt(1)), + lhs = exprLit(litInt(1)), rhs = exprSessionAttribute(SessionAttribute.CURRENT_USER()) ) } diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt index 41311b11af..90a035193d 100644 --- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt +++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/transforms/NormalizeSelect.kt @@ -25,7 +25,6 @@ import org.partiql.ast.Ast.exprStructField import org.partiql.ast.Ast.exprVarRef import org.partiql.ast.Ast.identifier import org.partiql.ast.Ast.identifierChain -import org.partiql.ast.Ast.literalString import org.partiql.ast.Ast.queryBodySFW import org.partiql.ast.Ast.queryBodySetOp import org.partiql.ast.Ast.selectItemExpr @@ -49,6 +48,7 @@ import org.partiql.ast.expr.ExprQuerySet import org.partiql.ast.expr.ExprStruct import org.partiql.ast.expr.ExprVarRef import org.partiql.ast.expr.Scope +import org.partiql.ast.literal.LiteralString.litString import org.partiql.planner.internal.helpers.toBinder /** @@ -317,7 +317,7 @@ internal object NormalizeSelect { val structFields = node.items.map { item -> val itemExpr = item as? SelectItem.Expr ?: error("Expected the projection to be an expression.") exprStructField( - name = exprLit(literalString(itemExpr.asAlias?.symbol!!)), + name = exprLit(litString(itemExpr.asAlias?.symbol!!)), value = item.expr ) } @@ -343,14 +343,14 @@ internal object NormalizeSelect { private fun buildSimpleStruct(expr: Expr, name: String): ExprStruct = exprStruct( fields = listOf( exprStructField( - name = exprLit(literalString(name)), + name = exprLit(litString(name)), value = expr ) ) ) private fun structField(name: String, expr: Expr): ExprStruct.Field = exprStructField( - name = exprLit(literalString(name)), + name = exprLit(litString(name)), value = expr ) 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 3af5083bce..a411b56be0 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 @@ -20,7 +20,6 @@ import org.partiql.ast.Ast.exprLit import org.partiql.ast.Ast.exprVarRef import org.partiql.ast.Ast.identifier import org.partiql.ast.Ast.identifierChain -import org.partiql.ast.Ast.literalInt import org.partiql.ast.AstNode import org.partiql.ast.AstRewriter import org.partiql.ast.AstVisitor @@ -49,6 +48,7 @@ import org.partiql.ast.expr.Expr import org.partiql.ast.expr.ExprCall import org.partiql.ast.expr.ExprQuerySet import org.partiql.ast.expr.Scope +import org.partiql.ast.literal.LiteralInteger.litInt import org.partiql.planner.internal.Env import org.partiql.planner.internal.helpers.toBinder import org.partiql.planner.internal.ir.Rel @@ -439,7 +439,7 @@ internal object RelConverter { relOpAggregateCallUnresolved( name, org.partiql.planner.internal.ir.SetQuantifier.ALL, - args = listOf(exprLit(literalInt(1)).toRex(env)) + args = listOf(exprLit(litInt(1)).toRex(env)) ) } else { val setq = when (expr.setq?.code()) { 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 7aab678b83..369d3673bd 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 @@ -55,11 +55,10 @@ import org.partiql.ast.expr.PathStep import org.partiql.ast.expr.Scope import org.partiql.ast.expr.TrimSpec import org.partiql.ast.literal.Literal +import org.partiql.ast.literal.LiteralApprox import org.partiql.ast.literal.LiteralBool -import org.partiql.ast.literal.LiteralDecimal -import org.partiql.ast.literal.LiteralDouble -import org.partiql.ast.literal.LiteralInt -import org.partiql.ast.literal.LiteralLong +import org.partiql.ast.literal.LiteralExact +import org.partiql.ast.literal.LiteralInteger import org.partiql.ast.literal.LiteralMissing import org.partiql.ast.literal.LiteralNull import org.partiql.ast.literal.LiteralString @@ -97,6 +96,7 @@ import org.partiql.planner.internal.typer.PlanTyper.Companion.toCType import org.partiql.planner.internal.utils.DateTimeUtils import org.partiql.spi.catalog.Identifier import org.partiql.types.PType +import org.partiql.value.DecimalValue import org.partiql.value.PartiQLValue import org.partiql.value.PartiQLValueExperimental import org.partiql.value.boolValue @@ -145,77 +145,54 @@ internal object RexConverter { throw IllegalArgumentException("unsupported rex $node") override fun visitExprLit(node: ExprLit, context: Env): Rex { + val pValue = node.lit.toPartiQLValue() + val type = when (pValue) { + // Specifically handle the lack of an infinite precision/scale + // TODO: PartiQLValue won't be in AST soon + is DecimalValue -> { + when (val decimal = pValue.value) { + null -> PType.decimal() + else -> PType.decimal(decimal.precision(), decimal.scale()) + } + } + else -> pValue.type.toPType() + } val cType = CompilerType( - _delegate = node.lit.toPType(), + _delegate = type, isNullValue = node.lit is LiteralNull, isMissingValue = node.lit is LiteralMissing ) - val op = rexOpLit(node.lit.toPartiQLValue()) + val op = rexOpLit(pValue) return rex(cType, op) } - private fun Literal.toPType(): PType { - return when (this) { - is LiteralNull, is LiteralMissing -> PType.unknown() - is LiteralString -> PType.string() - is LiteralBool -> PType.bool() - is LiteralDecimal -> { - if (this.value.scale() == 0) { - PType.numeric() - } else { - PType.decimal(this.value.precision(), this.value.scale()) - } - } - is LiteralInt -> PType.integer() - is LiteralLong -> PType.bigint() - is LiteralDouble -> PType.doublePrecision() - is LiteralTypedString -> { - val type = this.type - when (type.code()) { - DataType.DATE -> PType.date() - DataType.TIME -> if (type.precision == null) { - PType.time(6) - } else { - PType.time(type.precision) - } - DataType.TIME_WITH_TIME_ZONE -> if (type.precision == null) { - PType.timez(6) - } else { - PType.timez(type.precision) - } - DataType.TIMESTAMP -> if (type.precision == null) { - PType.timestamp(6) - } else { - PType.timestamp(type.precision) - } - DataType.TIMESTAMP_WITH_TIME_ZONE -> if (type.precision == null) { - PType.timestampz(6) - } else { - PType.timestampz(type.precision) - } - else -> error("Unsupported typed literal string: $this") - } - } - else -> error("Unsupported literal: $this") - } - } - private fun Literal.toPartiQLValue(): PartiQLValue { return when (this) { is LiteralNull -> nullValue() is LiteralMissing -> missingValue() is LiteralString -> stringValue(value) is LiteralBool -> boolValue(value) - is LiteralDecimal -> { - if (this.value.scale() == 0) { - intValue(this.value.toBigInteger()) + is LiteralExact -> { + val dec = this.decimal + if (dec.scale() == 0) { + intValue(dec.toBigInteger()) } else { - decimalValue(this.value) + decimalValue(dec) } } - is LiteralInt -> int32Value(this.value) - is LiteralLong -> int64Value(this.value) - is LiteralDouble -> float64Value(this.value) + is LiteralInteger -> { + val n = this.integer + // 1st, try parse as int + try { + val v = n.toInt() + int32Value(v) + } catch (ex: NumberFormatException) { + int64Value(n) + } + } + is LiteralApprox -> { + float64Value(this.double) + } is LiteralTypedString -> { val type = this.type val typedString = this.value diff --git a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/transforms/NormalizeSelectTest.kt b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/transforms/NormalizeSelectTest.kt index 16518cf33d..0c5e05ade7 100644 --- a/partiql-planner/src/test/kotlin/org/partiql/planner/internal/transforms/NormalizeSelectTest.kt +++ b/partiql-planner/src/test/kotlin/org/partiql/planner/internal/transforms/NormalizeSelectTest.kt @@ -10,8 +10,6 @@ import org.partiql.ast.Ast.from import org.partiql.ast.Ast.fromExpr import org.partiql.ast.Ast.identifier import org.partiql.ast.Ast.identifierChain -import org.partiql.ast.Ast.literalInt -import org.partiql.ast.Ast.literalString import org.partiql.ast.Ast.queryBodySFW import org.partiql.ast.Ast.selectItemExpr import org.partiql.ast.Ast.selectList @@ -20,6 +18,8 @@ import org.partiql.ast.FromType import org.partiql.ast.SelectItem import org.partiql.ast.expr.Expr import org.partiql.ast.expr.Scope +import org.partiql.ast.literal.LiteralInteger.litInt +import org.partiql.ast.literal.LiteralString.litString import kotlin.test.assertEquals class NormalizeSelectTest { @@ -172,7 +172,7 @@ class NormalizeSelectTest { constructor = exprStruct( items.map { exprStructField( - name = exprLit(literalString(it.first)), + name = exprLit(litString(it.first)), value = it.second ) } @@ -219,5 +219,5 @@ class NormalizeSelectTest { asAlias = asAlias?.let { identifier(asAlias, isDelimited = false) } ) - private fun lit(value: Int) = exprLit(literalInt(value)) + private fun lit(value: Int) = exprLit(litInt(value)) }