Skip to content

Commit

Permalink
Allow to apply groupConcat on expressions (#486)
Browse files Browse the repository at this point in the history
* Allow to apply groupConcat on expressions
* Migrate deprecated function to Expression as well
  • Loading branch information
Edvinas01 authored and Tapac committed Feb 11, 2019
1 parent 6e9e17c commit 49b88b5
Show file tree
Hide file tree
Showing 8 changed files with 15 additions and 13 deletions.
10 changes: 6 additions & 4 deletions src/main/kotlin/org/jetbrains/exposed/sql/Function.kt
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,12 @@ class CaseWhenElse<T, R:T> (val caseWhen: CaseWhen<T>, val elseResult: Expressio
}
}

class GroupConcat(val expr: Column<*>,
val separator: String?,
val distinct: Boolean,
vararg val orderBy: Pair<Expression<*>, SortOrder>): Function<String?>(VarCharColumnType()) {
class GroupConcat<T : String?>(
val expr: Expression<T>,
val separator: String?,
val distinct: Boolean,
vararg val orderBy: Pair<Expression<*>, SortOrder>
): Function<T>(VarCharColumnType()) {
override fun toSQL(queryBuilder: QueryBuilder): String
= currentDialect.functionProvider.groupConcat(this, queryBuilder)
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ fun<T:String?> Expression<T>.upperCase() : Function<T> = UpperCase(this)

@Deprecated("Use groupConcat function with SortOrder enum", ReplaceWith("groupConcat()"), level = DeprecationLevel.ERROR)
@JvmName("groupConcatDeprecated")
fun <T:Any?> Column<T>.groupConcat(separator: String?, distinct: Boolean = false, vararg orderBy: Pair<Expression<*>,Boolean>): GroupConcat =
fun <T : String?> Expression<T>.groupConcat(separator: String?, distinct: Boolean = false, vararg orderBy: Pair<Expression<*>,Boolean>): GroupConcat<T> =
GroupConcat(this, separator, distinct, *orderBy.map { it.first to if (it.second) SortOrder.ASC else SortOrder.DESC }.toTypedArray())

fun <T:Any?> Column<T>.groupConcat(separator: String? = null, distinct: Boolean = false, orderBy: Pair<Expression<*>,SortOrder>): GroupConcat =
fun <T : String?> Expression<T>.groupConcat(separator: String? = null, distinct: Boolean = false, orderBy: Pair<Expression<*>,SortOrder>): GroupConcat<T> =
GroupConcat(this, separator, distinct, orderBy)

fun <T:Any?> Column<T>.groupConcat(separator: String? = null, distinct: Boolean = false, orderBy: Array<Pair<Expression<*>,SortOrder>> = emptyArray()): GroupConcat =
fun <T : String?> Expression<T>.groupConcat(separator: String? = null, distinct: Boolean = false, orderBy: Array<Pair<Expression<*>,SortOrder>> = emptyArray()): GroupConcat<T> =
GroupConcat(this, separator, distinct, *orderBy)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ abstract class FunctionProvider {

open fun queryLimit(size: Int, offset: Int, alreadyOrdered: Boolean) = "LIMIT $size" + if (offset > 0) " OFFSET $offset" else ""

open fun groupConcat(expr: GroupConcat, queryBuilder: QueryBuilder) = buildString {
open fun <T : String?> groupConcat(expr: GroupConcat<T>, queryBuilder: QueryBuilder) = buildString {
append("GROUP_CONCAT(")
if (expr.distinct)
append("DISTINCT ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ internal object OracleFunctionProvider : FunctionProvider() {
override fun queryLimit(size: Int, offset: Int, alreadyOrdered: Boolean)
= (if (offset > 0) " OFFSET $offset ROWS" else "") + " FETCH FIRST $size ROWS ONLY"

override fun groupConcat(expr: GroupConcat, queryBuilder: QueryBuilder): String = buildString {
override fun <T : String?> groupConcat(expr: GroupConcat<T>, queryBuilder: QueryBuilder): String = buildString {
if (expr.orderBy.size != 1)
TransactionManager.current().throwUnsupportedException("LISTAGG requires single order by clause")
append("LISTAGG(")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal object PostgreSQLFunctionProvider : FunctionProvider() {

private const val onConflictIgnore = "ON CONFLICT DO NOTHING"

override fun groupConcat(expr: GroupConcat, queryBuilder: QueryBuilder): String {
override fun <T : String?> groupConcat(expr: GroupConcat<T>, queryBuilder: QueryBuilder): String {
val tr = TransactionManager.current()
return when {
expr.orderBy.isNotEmpty() -> tr.throwUnsupportedException("PostgreSQL doesn't support ORDER BY in STRING_AGG.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal object SQLServerFunctionProvider : FunctionProvider() {
return if (limit != null) def.replaceFirst("DELETE", "DELETE TOP($limit)") else def
}

override fun groupConcat(expr: GroupConcat, queryBuilder: QueryBuilder): String {
override fun <T : String?> groupConcat(expr: GroupConcat<T>, queryBuilder: QueryBuilder): String {
val tr = TransactionManager.current()
return when {
expr.separator == null ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal object SQLiteFunctionProvider : FunctionProvider() {
return super.update(targets, columnsAndValues, limit, where, transaction)
}

override fun groupConcat(expr: GroupConcat, queryBuilder: QueryBuilder): String {
override fun <T: String?> groupConcat(expr: GroupConcat<T>, queryBuilder: QueryBuilder): String {
val tr = TransactionManager.current()
return when {
expr.orderBy.isNotEmpty() -> tr.throwUnsupportedException("SQLite doesn't support ORDER BY in GROUP_CONCAT.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ class DMLTests : DatabaseTestsBase() {
@Test
fun testGroupConcat() {
withCitiesAndUsers(listOf(TestDB.SQLITE)) { cities, users, _ ->
fun GroupConcat.checkExcept(vararg dialects: KClass<out DatabaseDialect>, assert: (Map<String, String?>) ->Unit) {
fun <T : String?> GroupConcat<T>.checkExcept(vararg dialects: KClass<out DatabaseDialect>, assert: (Map<String, String?>) ->Unit) {
try {
val result = cities.leftJoin(users)
.slice(cities.name, this)
Expand Down

0 comments on commit 49b88b5

Please sign in to comment.