All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ufoss.kotysa.SqlClientSubQueryImpl.kt Maven / Gradle / Ivy

/*
 * This is free and unencumbered software released into the public domain, following 
 */

package org.ufoss.kotysa

import org.ufoss.kotysa.columns.TsvectorColumn
import org.ufoss.kotysa.postgresql.Tsquery
import java.math.BigDecimal

@Suppress("UNCHECKED_CAST")
internal class SqlClientSubQueryImpl internal constructor() : DefaultSqlClientSelect() {

    internal class Scope internal constructor(
        private val initialProps: DefaultSqlClientCommon.Properties,
    ) : SqlClientSubQuery.Scope {
        internal lateinit var properties: Properties<*>
        private fun  properties(): Properties {
            val props = Properties(initialProps.tables, initialProps.dbAccessType, initialProps.module,
                initialProps.availableColumns)
            props.index = initialProps.index
            properties = props
            return props
        }

        override fun  select(column: Column<*, T>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addSelectColumn(column) }

        override fun  select(table: Table): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addSelectTable(table) }

        override fun  selectCount(column: Column<*, T>?): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addCountColumn(column) }

        override fun  selectDistinct(column: Column<*, T>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addSelectColumn(column, FieldClassifier.DISTINCT) }

        override fun  selectMin(column: MinMaxColumn<*, T>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addSelectColumn(column, FieldClassifier.MIN) }

        override fun  selectMax(column: MinMaxColumn<*, T>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addSelectColumn(column, FieldClassifier.MAX) }

        override fun  selectAvg(column: NumericColumn<*, T>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addAvgColumn(column) }

        override fun selectSum(column: IntColumn<*>): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties()).apply { addLongSumColumn(column) }

        override fun selectTsRankCd(
            tsvectorColumn: TsvectorColumn<*>,
            tsquery: Tsquery,
        ): SqlClientSubQuery.FirstSelect = FirstSelect(properties()).apply { addTsRankCd(tsvectorColumn, tsquery) }

        override fun  select(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.FirstSelect = FirstSelect(properties()).apply { addSelectSubQuery(dsl) }

        override fun  selectCaseWhenExists(
            dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.SelectCaseWhenExistsFirst = SelectCaseWhenExistsFirst(properties(), dsl)

        override fun  selectStarFromSubQuery(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From = FirstSelect(properties()).selectStarFrom(dsl)
    }

    private class SelectCaseWhenExistsFirst(
        private val properties: Properties,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
    ) : SqlClientSubQuery.SelectCaseWhenExistsFirst {
        override fun  then(value: U): SqlClientSubQuery.SelectCaseWhenExistsFirstPart2 =
            SelectCaseWhenExistsFirstPart2(properties as Properties, dsl, value)
    }

    private class SelectCaseWhenExistsFirstPart2(
        private val properties: Properties,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return,
        private val then: U,
    ) : SqlClientSubQuery.SelectCaseWhenExistsFirstPart2 {
        override fun `else`(value: U): SqlClientSubQuery.FirstSelect =
            FirstSelect(properties).apply { addSelectCaseWhenExistsSubQuery(dsl, then, value) }
    }

    private class FirstSelect(override val properties: Properties) : DefaultSqlClientSelect.Select(),
        SqlClientSubQuery.FirstSelect {
        
        private val from: FromTable by lazy {
            FromTable(properties)
        }

        override fun  from(table: Table): SqlClientSubQuery.FromTable =
            addFromTable(table, from as FromTable)

        override fun  from(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From = addFromSubQuery(dsl, from as FromTable)

        override fun from(tsquery: Tsquery): SqlClientSubQuery.From = addFromTsquery(tsquery, from)

        fun  selectStarFrom(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From =
            addFromSubQuery(dsl, from as FromTable, true)

        override fun  and(column: Column<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addSelectColumn(column) }

        override fun  and(table: Table): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addSelectTable(table) }

        override fun  andCount(column: Column<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addCountColumn(column) }

        override fun  andDistinct(column: Column<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.DISTINCT)
            }

        override fun  andMin(column: MinMaxColumn<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MIN)
            }

        override fun  andMax(column: MinMaxColumn<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MAX)
            }

        override fun  andAvg(column: NumericColumn<*, U>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addAvgColumn(column) }

        override fun andSum(column: IntColumn<*>): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addLongSumColumn(column) }

        override fun andTsRankCd(
            tsvectorColumn: TsvectorColumn<*>,
            tsquery: Tsquery,
        ): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply { addTsRankCd(tsvectorColumn, tsquery) }

        override fun  and(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply {
                addSelectSubQuery(dsl)
            }

        override fun  andCaseWhenExists(
            dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.AndCaseWhenExistsSecond = AndCaseWhenExistsSecond(properties, dsl)

        override fun `as`(alias: String): SqlClientSubQuery.FirstSelect = this.apply { aliasLastColumn(alias) }
    }

    private class AndCaseWhenExistsSecond(
        private val properties: Properties,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
    ) : SqlClientSubQuery.AndCaseWhenExistsSecond {
        override fun  then(value: V): SqlClientSubQuery.AndCaseWhenExistsSecondPart2 =
            AndCaseWhenExistsSecondPart2(properties, dsl, value)
    }

    private class AndCaseWhenExistsSecondPart2(
        private val properties: Properties,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return,
        private val then: V,
    ) : SqlClientSubQuery.AndCaseWhenExistsSecondPart2 {
        override fun `else`(value: V): SqlClientSubQuery.SecondSelect =
            SecondSelect(properties as Properties>).apply {
                addSelectCaseWhenExistsSubQuery(dsl, then, value)
            }
    }

    private class SecondSelect(override val properties: Properties>) :
        DefaultSqlClientSelect.Select>(), SqlClientSubQuery.SecondSelect {
        
        private val from: FromTable, *> by lazy {
            FromTable, Any>(properties)
        }

        override fun  from(table: Table): SqlClientSubQuery.FromTable, V> =
            addFromTable(table, from as FromTable, V>)

        override fun  from(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From> = addFromSubQuery(dsl, from as FromTable, V>)

        override fun from(tsquery: Tsquery): SqlClientSubQuery.From> = addFromTsquery(tsquery, from)
        

        override fun  and(column: Column<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addSelectColumn(column) }

        override fun  and(table: Table): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addSelectTable(table) }

        override fun  andCount(column: Column<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addCountColumn(column) }

        override fun  andDistinct(column: Column<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.DISTINCT)
            }

        override fun  andMin(column: MinMaxColumn<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MIN)
            }

        override fun  andMax(column: MinMaxColumn<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MAX)
            }

        override fun  andAvg(column: NumericColumn<*, V>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addAvgColumn(column) }

        override fun andSum(column: IntColumn<*>): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addLongSumColumn(column) }

        override fun andTsRankCd(
            tsvectorColumn: TsvectorColumn<*>,
            tsquery: Tsquery,
        ): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply { addTsRankCd(tsvectorColumn, tsquery) }

        override fun  and(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply {
                addSelectSubQuery(dsl)
            }

        override fun  andCaseWhenExists(
            dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.AndCaseWhenExistsThird = AndCaseWhenExistsThird(properties, dsl)

        override fun `as`(alias: String): SqlClientSubQuery.SecondSelect = this.apply { aliasLastColumn(alias) }
    }

    private class AndCaseWhenExistsThird(
        private val properties: Properties>,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
    ) : SqlClientSubQuery.AndCaseWhenExistsThird {
        override fun  then(value: W): SqlClientSubQuery.AndCaseWhenExistsThirdPart2 =
            AndCaseWhenExistsThirdPart2(properties, dsl, value)
    }

    private class AndCaseWhenExistsThirdPart2(
        private val properties: Properties>,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return,
        private val then: W,
    ) : SqlClientSubQuery.AndCaseWhenExistsThirdPart2 {
        override fun `else`(value: W): SqlClientSubQuery.ThirdSelect =
            ThirdSelect(properties as Properties>).apply {
                addSelectCaseWhenExistsSubQuery(dsl, then, value)
            }
    }

    private class ThirdSelect(override val properties: Properties>) :
        DefaultSqlClientSelect.Select>(), SqlClientSubQuery.ThirdSelect {
        
        private val from: FromTable, *> by lazy {
            FromTable, Any>(properties)
        }

        override fun  from(table: Table): SqlClientSubQuery.FromTable, W> =
            addFromTable(table, from as FromTable, W>)

        override fun  from(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From> =
            addFromSubQuery(dsl, from as FromTable, W>)

        override fun from(tsquery: Tsquery): SqlClientSubQuery.From> = addFromTsquery(tsquery, from)

        override fun  and(column: Column<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addSelectColumn(column) }

        override fun  and(table: Table): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addSelectTable(table) }

        override fun  andCount(column: Column<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addCountColumn(column) }

        override fun  andDistinct(column: Column<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.DISTINCT)
            }

        override fun  andMin(column: MinMaxColumn<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MIN)
            }

        override fun  andMax(column: MinMaxColumn<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply {
                addSelectColumn(column, FieldClassifier.MAX)
            }

        override fun  andAvg(column: NumericColumn<*, W>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addAvgColumn(column) }

        override fun andSum(column: IntColumn<*>): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addLongSumColumn(column) }

        override fun andTsRankCd(
            tsvectorColumn: TsvectorColumn<*>,
            tsquery: Tsquery,
        ): SqlClientSubQuery.Select =
            Select(properties as Properties>).apply { addTsRankCd(tsvectorColumn, tsquery) }

        override fun  and(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.Select = Select(properties as Properties>).apply {
            addSelectSubQuery(dsl)
        }

        override fun  andCaseWhenExists(
            dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.AndCaseWhenExistsLast =
            AndCaseWhenExistsLast(properties as Properties>, dsl)

        override fun `as`(alias: String): SqlClientSubQuery.ThirdSelect = this.apply { aliasLastColumn(alias) }
    }

    private class AndCaseWhenExistsLast(
        private val properties: Properties>,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
    ) : SqlClientSubQuery.AndCaseWhenExistsLast {
        override fun  then(value: U): SqlClientSubQuery.AndCaseWhenExistsLastPart2 =
            AndCaseWhenExistsLastPart2(properties, dsl, value)
    }

    private class AndCaseWhenExistsLastPart2(
        private val properties: Properties>,
        private val dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return,
        private val then: U,
    ) : SqlClientSubQuery.AndCaseWhenExistsLastPart2 {
        override fun `else`(value: U): SqlClientSubQuery.Select =
            Select(properties).apply {
                addSelectCaseWhenExistsSubQuery(dsl, then, value)
            }
    }

    private class Select(override val properties: Properties>) : DefaultSqlClientSelect.Select>(),
        SqlClientSubQuery.Select {
        private val from: FromTable, *> = FromTable, Any>(properties)

        override fun  from(table: Table): SqlClientSubQuery.FromTable, T> =
            addFromTable(table, from as FromTable, T>)

        override fun  from(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From> =
            addFromSubQuery(dsl, from as FromTable, T>)

        override fun from(tsquery: Tsquery): SqlClientSubQuery.From> = addFromTsquery(tsquery, from)

        override fun  and(column: Column<*, T>): SqlClientSubQuery.Select =
            this.apply { addSelectColumn(column) }

        override fun  and(table: Table): SqlClientSubQuery.Select = this.apply { addSelectTable(table) }

        override fun  andCount(column: Column<*, T>): SqlClientSubQuery.Select =
            this.apply { addCountColumn(column) }

        override fun  andDistinct(column: Column<*, T>): SqlClientSubQuery.Select = this.apply {
            addSelectColumn(column, FieldClassifier.DISTINCT)
        }

        override fun  andMin(column: MinMaxColumn<*, T>): SqlClientSubQuery.Select = this.apply {
            addSelectColumn(column, FieldClassifier.MIN)
        }

        override fun  andMax(column: MinMaxColumn<*, T>): SqlClientSubQuery.Select = this.apply {
            addSelectColumn(column, FieldClassifier.MAX)
        }

        override fun  andAvg(column: NumericColumn<*, T>): SqlClientSubQuery.Select = this.apply {
            addAvgColumn(column)
        }

        override fun andSum(column: IntColumn<*>): SqlClientSubQuery.Select = this.apply { addLongSumColumn(column) }

        override fun andTsRankCd(
            tsvectorColumn: TsvectorColumn<*>,
            tsquery: Tsquery,
        ): SqlClientSubQuery.Select = this.apply { addTsRankCd(tsvectorColumn, tsquery) }

        override fun  and(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.Select = this.apply { addSelectSubQuery(dsl) }

        override fun  andCaseWhenExists(
            dsl: SqlClientSubQuery.SingleScope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.AndCaseWhenExistsLast = AndCaseWhenExistsLast(properties, dsl)

        override fun `as`(alias: String): SqlClientSubQuery.Select = this.apply { aliasLastColumn(alias) }
    }

    private class FromTable(
        properties: Properties,
    ) : FromWhereableSubQuery, SqlClientSubQuery.From,
            SqlClientSubQuery.Where, SqlClientSubQuery.LimitOffset,
            SqlClientSubQuery.GroupByPart2>(properties), SqlClientSubQuery.FromTable,
        SqlClientSubQuery.From, GroupBy, SqlClientSubQuery.LimitOffset, Return {
        override val fromTable = this
        override val from = this
        
        override val where by lazy { Where(properties) }
        override val limitOffset by lazy { LimitOffset(properties) }
        override val groupByPart2 by lazy { GroupByPart2(properties) }
        override fun  and(table: Table): SqlClientSubQuery.FromTable =
            addFromTable(table, fromTable as FromTable)

        override fun  and(
            dsl: SqlClientSubQuery.Scope.() -> SqlClientSubQuery.Return
        ): SqlClientSubQuery.From =
            addFromSubQuery(dsl, from as FromTable)

        override fun and(tsquery: Tsquery): SqlClientSubQuery.From = addFromTsquery(tsquery, from)

        override fun `as`(alias: String): SqlClientSubQuery.FromTable =
            from.apply { aliasLastFrom(alias) }
    }

    private class Where(
        override val properties: Properties,
    ) : WhereSubQuery, SqlClientSubQuery.LimitOffset,
            SqlClientSubQuery.GroupByPart2>(), SqlClientSubQuery.Where, GroupBy,
        SqlClientSubQuery.LimitOffset, Return {
        override val where = this
        override val limitOffset by lazy { LimitOffset(properties) }
        override val groupByPart2 by lazy { GroupByPart2(properties) }
    }

    private interface GroupBy : DefaultSqlClientSelect.GroupBy>,
        SqlClientSubQuery.GroupBy

    private class GroupByPart2(
        override val properties: Properties,
    ) : DefaultSqlClientSelect.GroupByPart2>, SqlClientSubQuery.GroupByPart2,
        DefaultSqlClientSelect.LimitOffset>, Return {
        override val limitOffset by lazy { LimitOffset(properties) }
        override val groupByPart2 = this
    }

    private class LimitOffset(
        override val properties: Properties,
    ) : DefaultSqlClientSelect.LimitOffset>, SqlClientSubQuery.LimitOffset,
        Return {
        override val limitOffset = this
    }

    private interface Return : DefaultSqlClientSelect.Return, SqlClientSubQuery.Return {
        override fun sql(parentProperties: DefaultSqlClientCommon.Properties): String {
            // must take care of index
            properties.index = parentProperties.index
            val select = selectSql(true)
            parentProperties.index = properties.index
            return select
        }
    }
}