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

commonMain.com.ctrip.sqllin.dsl.sql.statement.SelectStatement.kt Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
/*
 * Copyright (C) 2022 Ctrip.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ctrip.sqllin.dsl.sql.statement

import com.ctrip.sqllin.driver.CommonCursor
import com.ctrip.sqllin.driver.DatabaseConnection
import com.ctrip.sqllin.dsl.sql.Table
import com.ctrip.sqllin.dsl.sql.clause.*
import com.ctrip.sqllin.dsl.sql.compiler.QueryDecoder
import kotlinx.serialization.DeserializationStrategy
import kotlin.concurrent.Volatile

/**
 * Select statement
 * @author yaqiao
 */

public sealed class SelectStatement(
    sqlStr: String,
    internal val deserializer: DeserializationStrategy,
    internal val connection: DatabaseConnection,
    internal val container: StatementContainer,
    final override val parameters: MutableList?,
) : SingleStatement(sqlStr) {

    @Volatile
    private var result: List? = null

    @Volatile
    private var cursor: CommonCursor? = null

    final override fun execute() {
        cursor = connection.query(sqlStr, params)
    }

    @OptIn(ExperimentalStdlibApi::class)
    public fun getResults(): List = result ?: cursor?.use {
        val decoder = QueryDecoder(it)
        result = buildList {
            it.forEachRow {
                add(decoder.decodeSerializableValue(deserializer))
            }
        }
        result!!
    } ?: throw IllegalStateException("You have to call 'execute' function before call 'getResults'!!!")

    protected fun buildSQL(clause: SelectClause): String = buildString {
        append(sqlStr)
        append(clause.clauseStr)
    }

    internal fun  crossJoin(
        table: Table,
        newDeserializer: DeserializationStrategy,
    ): FinalSelectStatement {
        val sql = buildString {
            append(sqlStr)
            append(" CROSS JOIN ")
            append(table.tableName)
        }
        return FinalSelectStatement(sql, newDeserializer, connection, container, parameters)
    }
}

public class WhereSelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToLimit(clause: LimitClause): LimitSelectStatement =
        LimitSelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToOrderBy(clause: OrderByClause): OrderBySelectStatement =
        OrderBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToGroupBy(clause: GroupByClause): GroupBySelectStatement =
        GroupBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)
}

public class JoinSelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToWhere(clause: WhereClause): WhereSelectStatement {
        val clauseParams = clause.selectCondition.parameters
        val params = parameters?.also {
            clauseParams?.let { p ->
                it.addAll(p)
            }
        } ?: clauseParams
        return WhereSelectStatement(buildSQL(clause), deserializer, connection, container, params)
    }

    internal infix fun appendToLimit(clause: LimitClause): LimitSelectStatement =
        LimitSelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToOrderBy(clause: OrderByClause): OrderBySelectStatement =
        OrderBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToGroupBy(clause: GroupByClause): GroupBySelectStatement =
        GroupBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)
}

public class GroupBySelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToOrderBy(clause: OrderByClause): OrderBySelectStatement =
        OrderBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToHaving(clause: HavingClause): HavingSelectStatement {
        val clauseParams = clause.selectCondition.parameters
        val params = parameters?.also {
            clauseParams?.let { p ->
                it.addAll(p)
            }
        } ?: clauseParams
        return HavingSelectStatement(buildSQL(clause), deserializer, connection, container, params)
    }
}

public class HavingSelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToOrderBy(clause: OrderByClause): OrderBySelectStatement =
        OrderBySelectStatement(buildSQL(clause), deserializer, connection, container, parameters)

    internal infix fun appendToLimit(clause: LimitClause): LimitSelectStatement =
        LimitSelectStatement(buildSQL(clause), deserializer, connection, container, parameters)
}

public class OrderBySelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToLimit(clause: LimitClause): LimitSelectStatement =
        LimitSelectStatement(buildSQL(clause), deserializer, connection, container, parameters)
}

public class LimitSelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters) {

    internal infix fun appendToFinal(clause: OffsetClause): FinalSelectStatement =
        FinalSelectStatement(buildSQL(clause), deserializer, connection, container, parameters)
}

public class FinalSelectStatement internal constructor(
    sqlStr: String,
    deserializer: DeserializationStrategy,
    connection: DatabaseConnection,
    container: StatementContainer,
    parameters: MutableList?,
) : SelectStatement(sqlStr, deserializer, connection, container, parameters)