From 939c68e12c7e86880048b6315dbf160c7c52980d Mon Sep 17 00:00:00 2001 From: solonovamax Date: Thu, 9 Jan 2025 02:09:44 -0500 Subject: [PATCH 1/3] feat: EXPOSED-681 Add support for GREATEST and LEAST functions Adds support for GREATEST(X, Y) and LEAST(X, Y) functions. In SQLite, these are named MAX(X, Y) and MIN(X, Y), respectively. (because you just had to be different, huh sqlite?) Signed-off-by: solonovamax --- exposed-core/api/exposed-core.api | 28 +++++++++++++++++++ .../kotlin/org/jetbrains/exposed/sql/Op.kt | 24 ++++++++++++++++ .../exposed/sql/SQLExpressionBuilder.kt | 20 +++++++++++++ .../exposed/sql/vendors/FunctionProvider.kt | 22 +++++++++++++++ .../exposed/sql/vendors/SQLiteDialect.kt | 8 ++++++ 5 files changed, 102 insertions(+) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 30280279f2..d11611bc31 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -1049,6 +1049,13 @@ public final class org/jetbrains/exposed/sql/GreaterOp : org/jetbrains/exposed/s public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V } +public final class org/jetbrains/exposed/sql/GreatestOp : org/jetbrains/exposed/sql/Op { + public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V + public final fun getExpr1 ()Lorg/jetbrains/exposed/sql/Expression; + public final fun getExpr2 ()Lorg/jetbrains/exposed/sql/Expression; + public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V +} + public final class org/jetbrains/exposed/sql/GroupConcat : org/jetbrains/exposed/sql/Function { public fun (Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Z[Lkotlin/Pair;)V public final fun getDistinct ()Z @@ -1140,6 +1147,8 @@ public abstract interface class org/jetbrains/exposed/sql/ISqlExpressionBuilder public abstract fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public abstract fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public abstract fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; + public abstract fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; + public abstract fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; public abstract fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public abstract fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public abstract fun inList (Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -1168,6 +1177,8 @@ public abstract interface class org/jetbrains/exposed/sql/ISqlExpressionBuilder public abstract fun lag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lag; public abstract fun lastValue (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public abstract fun lead (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; + public abstract fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; + public abstract fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; public abstract fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public abstract fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public abstract fun less (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -1274,6 +1285,8 @@ public final class org/jetbrains/exposed/sql/ISqlExpressionBuilder$DefaultImpls public static fun greaterEq (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public static fun greaterEq (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public static fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; + public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; + public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; public static fun hasFlag (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public static fun hasFlag (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public static fun inList (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -1304,6 +1317,8 @@ public final class org/jetbrains/exposed/sql/ISqlExpressionBuilder$DefaultImpls public static fun lastValue (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public static fun lead (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; public static synthetic fun lead$default (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Lead; + public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; + public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -1555,6 +1570,13 @@ public final class org/jetbrains/exposed/sql/Lead : org/jetbrains/exposed/sql/Wi public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V } +public final class org/jetbrains/exposed/sql/LeastOp : org/jetbrains/exposed/sql/Op { + public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V + public final fun getExpr1 ()Lorg/jetbrains/exposed/sql/Expression; + public final fun getExpr2 ()Lorg/jetbrains/exposed/sql/Expression; + public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V +} + public final class org/jetbrains/exposed/sql/LessEqOp : org/jetbrains/exposed/sql/ComparisonOp { public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V } @@ -2354,6 +2376,8 @@ public final class org/jetbrains/exposed/sql/SqlExpressionBuilder : org/jetbrain public fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; + public fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; + public fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; public fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public fun inList (Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -2382,6 +2406,8 @@ public final class org/jetbrains/exposed/sql/SqlExpressionBuilder : org/jetbrain public fun lag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lag; public fun lastValue (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public fun lead (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; + public fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; + public fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; public fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public fun less (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -4038,6 +4064,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/FunctionProvider { public fun delete (ZLorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/Integer;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; public fun explain (ZLjava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; public fun getDEFAULT_VALUE_EXPRESSION ()Ljava/lang/String; + public fun greatest (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun groupConcat (Lorg/jetbrains/exposed/sql/GroupConcat;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun hour (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun insert (ZLorg/jetbrains/exposed/sql/Table;Ljava/util/List;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; @@ -4045,6 +4072,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/FunctionProvider { public fun jsonContains (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun jsonExists (Lorg/jetbrains/exposed/sql/Expression;[Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun jsonExtract (Lorg/jetbrains/exposed/sql/Expression;[Ljava/lang/String;ZLorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V + public fun least (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun locate (Lorg/jetbrains/exposed/sql/QueryBuilder;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;)V public fun match (Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/vendors/FunctionProvider$MatchMode;)Lorg/jetbrains/exposed/sql/Op; public static synthetic fun match$default (Lorg/jetbrains/exposed/sql/vendors/FunctionProvider;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/vendors/FunctionProvider$MatchMode;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Op; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt index 7cb136c30c..4d0dc52fe5 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt @@ -299,6 +299,30 @@ class IsDistinctFromOp( } } +/** + * Represents an SQL operator that returns the greatest (maximum) of [expr1] and [expr2]. + */ +class GreatestOp( + val expr1: Expression, + val expr2: Expression, +) : Op() { + override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { + currentDialect.functionProvider.greatest(expr1, expr2, queryBuilder) + } +} + +/** + * Represents an SQL operator that returns the least (minimum) of [expr1] and [expr2]. + */ +class LeastOp( + val expr1: Expression, + val expr2: Expression, +) : Op() { + override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { + currentDialect.functionProvider.least(expr1, expr2, queryBuilder) + } +} + // Mathematical Operators /** diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt index 6a4cbc708f..8bd7992f1b 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt @@ -579,6 +579,26 @@ interface ISqlExpressionBuilder { other: ExpressionWithColumnType ): IsDistinctFromOp = IsDistinctFromOp(this, other) + /** + * The greatest (maximum) of this expression and [t]. + */ + infix fun ExpressionWithColumnType.greatest(t: T): GreatestOp = GreatestOp(this, wrap(t)) + + /** + * The greatest (maximum) of this expression and [other]. + */ + infix fun ExpressionWithColumnType.greatest(other: Expression): GreatestOp = GreatestOp(this, other) + + /** + * The least (minimum) of this expression and [t]. + */ + infix fun ExpressionWithColumnType.least(t: T): LeastOp = LeastOp(this, wrap(t)) + + /** + * The least (minimum) of this expression and [other]. + */ + infix fun ExpressionWithColumnType.least(other: Expression): LeastOp = LeastOp(this, other) + // Mathematical Operators /** Adds the [t] value to this expression. */ diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt index 82aec9a53e..601eb7ba3e 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt @@ -34,6 +34,28 @@ abstract class FunctionProvider { */ open fun random(seed: Int?): String = "RANDOM(${seed?.toString().orEmpty()})" + /** + * SQL function that returns the greatest (maximum) of two values. + * + * @param expr1 The first value. + * @param expr2 The second value. + * @param queryBuilder Query builder to append the SQL function to. + */ + open fun greatest(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder): Unit = queryBuilder { + append("GREATEST(", expr1, ", ", expr2, ")") + } + + /** + * SQL function that returns the least (minimum) of two values. + * + * @param expr1 The first value. + * @param expr2 The second value. + * @param queryBuilder Query builder to append the SQL function to. + */ + open fun least(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder): Unit = queryBuilder { + append("LEAST(", expr1, ", ", expr2, ")") + } + // String functions /** diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt index 7108ea701e..ad000b1cb9 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt @@ -25,6 +25,14 @@ internal object SQLiteDataTypeProvider : DataTypeProvider() { @Suppress("TooManyFunctions") internal object SQLiteFunctionProvider : FunctionProvider() { + override fun greatest(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder) = queryBuilder { + append("MAX(", expr1, ", ", expr2, ")") + } + + override fun least(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder) = queryBuilder { + append("MIN(", expr1, ", ", expr2, ")") + } + override fun charLength(expr: Expression, queryBuilder: QueryBuilder) = queryBuilder { append("LENGTH(", expr, ")") } From 53f4e4cf68abd14571ab8085eb499cb2a9dfba07 Mon Sep 17 00:00:00 2001 From: solonovamax Date: Thu, 9 Jan 2025 15:01:03 -0500 Subject: [PATCH 2/3] feat: Apply suggested changes - Inherit from Function instead of Op - Make both functions accept varargs - Don't use an infix function for the expression builder Signed-off-by: solonovamax --- exposed-core/api/exposed-core.api | 38 +++++++------- .../org/jetbrains/exposed/sql/Function.kt | 38 ++++++++++++++ .../kotlin/org/jetbrains/exposed/sql/Op.kt | 24 --------- .../exposed/sql/SQLExpressionBuilder.kt | 49 ++++++++++++++++--- .../exposed/sql/vendors/FunctionProvider.kt | 18 ++++--- .../exposed/sql/vendors/SQLiteDialect.kt | 12 +++-- 6 files changed, 117 insertions(+), 62 deletions(-) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index d11611bc31..1cea18e0eb 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -1049,10 +1049,11 @@ public final class org/jetbrains/exposed/sql/GreaterOp : org/jetbrains/exposed/s public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V } -public final class org/jetbrains/exposed/sql/GreatestOp : org/jetbrains/exposed/sql/Op { - public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V +public final class org/jetbrains/exposed/sql/Greatest : org/jetbrains/exposed/sql/Function { + public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/IColumnType;[Lorg/jetbrains/exposed/sql/Expression;)V public final fun getExpr1 ()Lorg/jetbrains/exposed/sql/Expression; public final fun getExpr2 ()Lorg/jetbrains/exposed/sql/Expression; + public final fun getOthers ()[Lorg/jetbrains/exposed/sql/Expression; public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V } @@ -1147,8 +1148,8 @@ public abstract interface class org/jetbrains/exposed/sql/ISqlExpressionBuilder public abstract fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public abstract fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public abstract fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; - public abstract fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; - public abstract fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; + public abstract fun greatest (Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; + public abstract fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; public abstract fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public abstract fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public abstract fun inList (Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -1177,8 +1178,8 @@ public abstract interface class org/jetbrains/exposed/sql/ISqlExpressionBuilder public abstract fun lag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lag; public abstract fun lastValue (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public abstract fun lead (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; - public abstract fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; - public abstract fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; + public abstract fun least (Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; + public abstract fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; public abstract fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public abstract fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public abstract fun less (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -1285,8 +1286,8 @@ public final class org/jetbrains/exposed/sql/ISqlExpressionBuilder$DefaultImpls public static fun greaterEq (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public static fun greaterEq (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public static fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; - public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; - public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; + public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; + public static fun greatest (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; public static fun hasFlag (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public static fun hasFlag (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public static fun inList (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -1317,8 +1318,8 @@ public final class org/jetbrains/exposed/sql/ISqlExpressionBuilder$DefaultImpls public static fun lastValue (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public static fun lead (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; public static synthetic fun lead$default (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Lead; - public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; - public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; + public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; + public static fun least (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public static fun less (Lorg/jetbrains/exposed/sql/ISqlExpressionBuilder;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -1570,10 +1571,11 @@ public final class org/jetbrains/exposed/sql/Lead : org/jetbrains/exposed/sql/Wi public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V } -public final class org/jetbrains/exposed/sql/LeastOp : org/jetbrains/exposed/sql/Op { - public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)V +public final class org/jetbrains/exposed/sql/Least : org/jetbrains/exposed/sql/Function { + public fun (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/IColumnType;[Lorg/jetbrains/exposed/sql/Expression;)V public final fun getExpr1 ()Lorg/jetbrains/exposed/sql/Expression; public final fun getExpr2 ()Lorg/jetbrains/exposed/sql/Expression; + public final fun getOthers ()[Lorg/jetbrains/exposed/sql/Expression; public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V } @@ -2376,8 +2378,8 @@ public final class org/jetbrains/exposed/sql/SqlExpressionBuilder : org/jetbrain public fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public fun greaterEq (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreaterEqOp; public fun greaterEqEntityID (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/GreaterEqOp; - public fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/GreatestOp; - public fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/GreatestOp; + public fun greatest (Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; + public fun greatest (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Greatest; public fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/EqOp; public fun hasFlag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/EqOp; public fun inList (Ljava/util/List;Ljava/lang/Iterable;)Lorg/jetbrains/exposed/sql/ops/InListOrNotInListBaseOp; @@ -2406,8 +2408,8 @@ public final class org/jetbrains/exposed/sql/SqlExpressionBuilder : org/jetbrain public fun lag (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lag; public fun lastValue (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LastValue; public fun lead (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/Lead; - public fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Object;)Lorg/jetbrains/exposed/sql/LeastOp; - public fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LeastOp; + public fun least (Ljava/lang/Object;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; + public fun least (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Lorg/jetbrains/exposed/sql/Expression;[Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/Least; public fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;)Lorg/jetbrains/exposed/sql/LessOp; public fun less (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;)Lorg/jetbrains/exposed/sql/LessOp; public fun less (Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;Ljava/lang/Comparable;)Lorg/jetbrains/exposed/sql/LessOp; @@ -4064,7 +4066,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/FunctionProvider { public fun delete (ZLorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/Integer;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; public fun explain (ZLjava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; public fun getDEFAULT_VALUE_EXPRESSION ()Ljava/lang/String; - public fun greatest (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V + public fun greatest (Lorg/jetbrains/exposed/sql/QueryBuilder;[Lorg/jetbrains/exposed/sql/Expression;)V public fun groupConcat (Lorg/jetbrains/exposed/sql/GroupConcat;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun hour (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun insert (ZLorg/jetbrains/exposed/sql/Table;Ljava/util/List;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; @@ -4072,7 +4074,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/FunctionProvider { public fun jsonContains (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun jsonExists (Lorg/jetbrains/exposed/sql/Expression;[Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V public fun jsonExtract (Lorg/jetbrains/exposed/sql/Expression;[Ljava/lang/String;ZLorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/QueryBuilder;)V - public fun least (Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/QueryBuilder;)V + public fun least (Lorg/jetbrains/exposed/sql/QueryBuilder;[Lorg/jetbrains/exposed/sql/Expression;)V public fun locate (Lorg/jetbrains/exposed/sql/QueryBuilder;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;)V public fun match (Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/vendors/FunctionProvider$MatchMode;)Lorg/jetbrains/exposed/sql/Op; public static synthetic fun match$default (Lorg/jetbrains/exposed/sql/vendors/FunctionProvider;Lorg/jetbrains/exposed/sql/Expression;Ljava/lang/String;Lorg/jetbrains/exposed/sql/vendors/FunctionProvider$MatchMode;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Op; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Function.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Function.kt index c8e5ccd091..40cfee0eb2 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Function.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Function.kt @@ -65,6 +65,44 @@ class Random( } } +/** + * Represents an SQL operator that returns the greatest (maximum, largest + * value) of [expr1], [expr2], and [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. + */ +class Greatest( + val expr1: Expression, + val expr2: Expression, + columnType: IColumnType, + vararg val others: Expression +) : Function(columnType) { + override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { + currentDialect.functionProvider.greatest(queryBuilder, expr1, expr2, *others) + } +} + +/** + * Represents an SQL operator that returns the least (minimum, smallest + * value) of [expr1], [expr2], and [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. + */ +class Least( + val expr1: Expression, + val expr2: Expression, + columnType: IColumnType, + vararg val others: Expression +) : Function(columnType) { + override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { + currentDialect.functionProvider.least(queryBuilder, expr1, expr2, *others) + } +} + // String Functions /** diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt index 4d0dc52fe5..7cb136c30c 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt @@ -299,30 +299,6 @@ class IsDistinctFromOp( } } -/** - * Represents an SQL operator that returns the greatest (maximum) of [expr1] and [expr2]. - */ -class GreatestOp( - val expr1: Expression, - val expr2: Expression, -) : Op() { - override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { - currentDialect.functionProvider.greatest(expr1, expr2, queryBuilder) - } -} - -/** - * Represents an SQL operator that returns the least (minimum) of [expr1] and [expr2]. - */ -class LeastOp( - val expr1: Expression, - val expr2: Expression, -) : Op() { - override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = queryBuilder { - currentDialect.functionProvider.least(expr1, expr2, queryBuilder) - } -} - // Mathematical Operators /** diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt index 8bd7992f1b..3d176d480f 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SQLExpressionBuilder.kt @@ -580,24 +580,57 @@ interface ISqlExpressionBuilder { ): IsDistinctFromOp = IsDistinctFromOp(this, other) /** - * The greatest (maximum) of this expression and [t]. + * The greatest (maximum, largest value) of [expr1], [expr2], and [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. */ - infix fun ExpressionWithColumnType.greatest(t: T): GreatestOp = GreatestOp(this, wrap(t)) + fun greatest( + expr1: ExpressionWithColumnType, + expr2: Expression, + vararg others: Expression, + ): Greatest = Greatest(expr1, expr2, expr1.columnType, *others) /** - * The greatest (maximum) of this expression and [other]. + * The greatest (maximum, largest value) of [literal], [expr1], and + * [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. */ - infix fun ExpressionWithColumnType.greatest(other: Expression): GreatestOp = GreatestOp(this, other) + fun greatest( + literal: T, + expr1: ExpressionWithColumnType, + vararg others: Expression, + ): Greatest = Greatest(expr1.wrap(literal), expr1, expr1.columnType, *others) /** - * The least (minimum) of this expression and [t]. + * The least (minimum, smallest value) of [expr1], [expr2], and [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. */ - infix fun ExpressionWithColumnType.least(t: T): LeastOp = LeastOp(this, wrap(t)) + fun least( + expr1: ExpressionWithColumnType, + expr2: Expression, + vararg others: Expression, + ): Least = Least(expr1, expr2, expr1.columnType, *others) /** - * The least (minimum) of this expression and [other]. + * The least (minimum, smallest value) of [literal], [expr1], and [others]. + * + * **Note:** The semantics of this function when applied to null values + * or values of multiple types depends on the vendor. Please check the + * documentation for your respective database. */ - infix fun ExpressionWithColumnType.least(other: Expression): LeastOp = LeastOp(this, other) + fun least( + literal: T, + expr1: ExpressionWithColumnType, + vararg others: Expression, + ): Least = Least(expr1.wrap(literal), expr1, expr1.columnType, *others) // Mathematical Operators diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt index 601eb7ba3e..b6e083d4d5 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/FunctionProvider.kt @@ -37,23 +37,25 @@ abstract class FunctionProvider { /** * SQL function that returns the greatest (maximum) of two values. * - * @param expr1 The first value. - * @param expr2 The second value. * @param queryBuilder Query builder to append the SQL function to. + * @param expr The expressions to compare. */ - open fun greatest(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder): Unit = queryBuilder { - append("GREATEST(", expr1, ", ", expr2, ")") + open fun greatest(queryBuilder: QueryBuilder, vararg expr: Expression): Unit = queryBuilder { + append("GREATEST(") + expr.appendTo { +it } + append(")") } /** * SQL function that returns the least (minimum) of two values. * - * @param expr1 The first value. - * @param expr2 The second value. * @param queryBuilder Query builder to append the SQL function to. + * @param expr The expressions to compare. */ - open fun least(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder): Unit = queryBuilder { - append("LEAST(", expr1, ", ", expr2, ")") + open fun least(queryBuilder: QueryBuilder, vararg expr: Expression): Unit = queryBuilder { + append("LEAST(") + expr.appendTo { +it } + append(")") } // String functions diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt index ad000b1cb9..99596697ae 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt @@ -25,12 +25,16 @@ internal object SQLiteDataTypeProvider : DataTypeProvider() { @Suppress("TooManyFunctions") internal object SQLiteFunctionProvider : FunctionProvider() { - override fun greatest(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder) = queryBuilder { - append("MAX(", expr1, ", ", expr2, ")") + override fun greatest(queryBuilder: QueryBuilder, vararg expr: Expression) = queryBuilder { + append("MAX(") + expr.appendTo { +it } + append(")") } - override fun least(expr1: Expression, expr2: Expression, queryBuilder: QueryBuilder) = queryBuilder { - append("MIN(", expr1, ", ", expr2, ")") + override fun least(queryBuilder: QueryBuilder, vararg expr: Expression) = queryBuilder { + append("MIN(") + expr.appendTo { +it } + append(")") } override fun charLength(expr: Expression, queryBuilder: QueryBuilder) = queryBuilder { From c23adc07a6c93cc3282a902fc1f21a19bb964784 Mon Sep 17 00:00:00 2001 From: solonovamax Date: Thu, 9 Jan 2025 21:46:05 -0500 Subject: [PATCH 3/3] fea: Add test cases for LEAST and GREATEST functions Signed-off-by: solonovamax --- .../tests/shared/functions/FunctionsTests.kt | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/FunctionsTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/FunctionsTests.kt index d716a482cf..ba503cb0ff 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/FunctionsTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/FunctionsTests.kt @@ -4,6 +4,8 @@ import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.coalesce import org.jetbrains.exposed.sql.SqlExpressionBuilder.concat +import org.jetbrains.exposed.sql.SqlExpressionBuilder.greatest +import org.jetbrains.exposed.sql.SqlExpressionBuilder.least import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.TestDB import org.jetbrains.exposed.sql.tests.currentDialectTest @@ -379,6 +381,112 @@ class FunctionsTests : DatabaseTestsBase() { } } + val nullIgnoredDatabases = TestDB.ALL_SQLSERVER_LIKE + TestDB.ALL_POSTGRES_LIKE + TestDB.ALL_H2_V1 + + @Test + fun testGreatestLeastFunction01() { + val table = object : IntIdTable("test_comparison_table") { + val intColumn = integer("int_column") + val intColumn2 = integer("int_column2") + val intColumnNullable = integer("int_column_nullable").nullable() + + val doubleColumn = double("double_column") + val doubleColumn2 = double("double_column2") + val doubleColumnNullable = double("double_column_nullable").nullable() + } + withTables(table) { db -> + table.insert { + it[intColumn] = 1 + it[intColumn2] = 2 + it[intColumnNullable] = 3 + + it[doubleColumn] = 1.0 + it[doubleColumn2] = 2.0 + it[doubleColumnNullable] = 3.0 + } + table.insert { + it[intColumn] = 6 + it[intColumn2] = 5 + it[intColumnNullable] = 4 + + it[doubleColumn] = 6.0 + it[doubleColumn2] = 5.0 + it[doubleColumnNullable] = 4.0 + } + table.insert { + it[intColumn] = 3 + it[intColumn2] = 2 + + it[doubleColumn] = 3.0 + it[doubleColumn2] = 2.0 + } + + val greatestInt = greatest(table.intColumn, table.intColumn2, table.intColumnNullable) + val greatestDouble = greatest(table.doubleColumn, table.doubleColumn2, table.doubleColumnNullable) + val leastInt = least(table.intColumn, table.intColumn2, table.intColumnNullable) + val leastDouble = least(table.doubleColumn, table.doubleColumn2, table.doubleColumnNullable) + + val result = table.select(greatestInt, greatestDouble, leastInt, leastDouble).where { table.id.eq(1) }.single() + assertEquals(3, result[greatestInt]) + assertEquals(3.0, result[greatestDouble]) + assertEquals(1, result[leastInt]) + assertEquals(1.0, result[leastDouble]) + + val result2 = table.select(greatestInt, greatestDouble, leastInt, leastDouble).where { table.id.eq(2) }.single() + assertEquals(6, result2[greatestInt]) + assertEquals(6.0, result2[greatestDouble]) + assertEquals(4, result2[leastInt]) + assertEquals(4.0, result2[leastDouble]) + + val result3 = table.select(greatestInt, greatestDouble, leastInt, leastDouble).where { table.id.eq(3) }.single() + if (db in nullIgnoredDatabases) { + assertEquals(3, result3[greatestInt]) + assertEquals(3.0, result3[greatestDouble]) + assertEquals(2, result3[leastInt]) + assertEquals(2.0, result3[leastDouble]) + } else { + assertNull(result3[greatestInt]) + assertNull(result3[greatestDouble]) + assertNull(result3[leastInt]) + assertNull(result3[leastDouble]) + } + } + } + + @Test + fun testGreatestLeastFunction02() { + val table = object : IntIdTable("test_comparison_table") { + val intColumn = integer("int_column") + } + withTables(table) { db -> + table.insert { + it[intColumn] = 1 + } + + val greatestExpression = greatest(table.intColumn, intLiteral(999), Op.nullOp(), intParam(56666)) + val greatestLiteralsMix = greatest(10, table.intColumn) + val greatestLiteralsOnly = greatest(3, intLiteral(5)) + val leastExpression = least(table.intColumn, intLiteral(999), Op.nullOp(), intParam(56666)) + val leastLiteralsMix = least(0, table.intColumn) + val leastLiteralsOnly = least(3, intLiteral(5)) + + val result = table.select(greatestExpression, greatestLiteralsMix, greatestLiteralsOnly, leastExpression, leastLiteralsMix, leastLiteralsOnly) + .where { table.id.eq(1) }.single() + if (db in nullIgnoredDatabases) + assertEquals(56666, result[greatestExpression]) + else + assertEquals(null, result[greatestExpression]) + assertEquals(10, result[greatestLiteralsMix]) + assertEquals(5, result[greatestLiteralsOnly]) + if (db in nullIgnoredDatabases) + assertEquals(1, result[leastExpression]) + else + assertEquals(null, result[leastExpression]) + assertEquals(0, result[leastLiteralsMix]) + assertEquals(3, result[leastLiteralsOnly]) + } + } + @Test fun testRegexp01() { withCitiesAndUsers(TestDB.ALL_SQLSERVER_LIKE + TestDB.SQLITE) { _, users, _ ->