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

commonMain.com.ctrip.sqllin.dsl.DatabaseScope.kt Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
/*
 * Copyright (C) 2023 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

import com.ctrip.sqllin.driver.DatabaseConnection
import com.ctrip.sqllin.dsl.sql.Table
import com.ctrip.sqllin.dsl.sql.X
import com.ctrip.sqllin.dsl.sql.clause.*
import com.ctrip.sqllin.dsl.sql.operation.Delete
import com.ctrip.sqllin.dsl.sql.operation.Insert
import com.ctrip.sqllin.dsl.sql.operation.Select
import com.ctrip.sqllin.dsl.sql.operation.Update
import com.ctrip.sqllin.dsl.sql.statement.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.modules.EmptySerializersModule
import kotlinx.serialization.serializer
import kotlin.concurrent.Volatile

/**
 * The database scope, it's used to restrict the scope that write DSL SQL statements
 * @author yaqiao
 */

@Suppress("UNCHECKED_CAST")
public class DatabaseScope internal constructor(
    private val databaseConnection: DatabaseConnection,
    private val enableSimpleSQLLog: Boolean,
) {

    /**
     * Transaction.
     */

    @Volatile
    private var transactionStatementsGroup: TransactionStatementsGroup? = null

    private inline val isInTransaction
        get() = transactionStatementsGroup != null

    public fun beginTransaction(): Boolean {
        if (isInTransaction)
            return false
        transactionStatementsGroup = TransactionStatementsGroup(databaseConnection, enableSimpleSQLLog)
        executiveEngine.addStatement(transactionStatementsGroup!!)
        return true
    }

    public fun endTransaction() {
        transactionStatementsGroup = null
    }

    public inline fun  transaction(block: DatabaseScope.() -> T): T {
        beginTransaction()
        try {
            return block()
        } finally {
            endTransaction()
        }
    }

    /**
     * SQL execute.
     */

    private val executiveEngine = DatabaseExecuteEngine(enableSimpleSQLLog)

    private fun addStatement(statement: SingleStatement) {
        if (isInTransaction)
            transactionStatementsGroup!!.addStatement(statement)
        else
            executiveEngine.addStatement(statement)
    }

    private fun  addSelectStatement(statement: SelectStatement) {
        if (unionSelectStatementGroupStack.isNotEmpty())
            (unionSelectStatementGroupStack.last() as UnionSelectStatementGroup).addSelectStatement(statement)
        else
            addStatement(statement)
    }

    internal fun executeAllStatements() = executiveEngine.executeAllStatement()

    /**
     * Insert.
     */

    public infix fun  Table.INSERT(entities: Iterable) {
        val statement = Insert.insert(this, databaseConnection, entities)
        addStatement(statement)
    }

    public infix fun  Table.INSERT(entity: T): Unit =
        INSERT(listOf(entity))

    /**
     * Update.
     */

    public infix fun  Table.UPDATE(clause: SetClause): UpdateStatementWithoutWhereClause =
        transactionStatementsGroup?.let {
            val statement = Update.update(this, databaseConnection, it, clause)
            it addStatement statement
            statement
        } ?: Update.update(this, databaseConnection, executiveEngine, clause).also {
            executiveEngine addStatement it
        }

    /**
     * Delete.
     */

    public infix fun Table<*>.DELETE(x: X) {
        val statement = Delete.deleteAllEntities(this, databaseConnection)
        addStatement(statement)
    }

    public infix fun  Table.DELETE(clause: WhereClause) {
        val statement = Delete.delete(this, databaseConnection, clause)
        addStatement(statement)
    }

    /**
     * Select.
     */

    /**
     * Select with no any clause.
     */
    public inline infix fun  Table.SELECT(x: X): FinalSelectStatement =
        select(kSerializer(), false)

    public inline infix fun  Table.SELECT_DISTINCT(x: X): FinalSelectStatement =
        select(kSerializer(), true)

    public fun  Table.select(serializer: KSerializer, isDistinct: Boolean): FinalSelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }

    /**
     * Receive the 'WHERE' clause.
     */
    public inline infix fun  Table.SELECT(clause: WhereClause): WhereSelectStatement =
        select(kSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: WhereClause): WhereSelectStatement =
        select(kSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: WhereClause, isDistinct: Boolean): WhereSelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, clause, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }

    /**
     * Receive the 'ORDER BY' clause.
     */
    public inline infix fun  Table.SELECT(clause: OrderByClause): OrderBySelectStatement =
        select(kSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: OrderByClause): OrderBySelectStatement =
        select(kSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: OrderByClause, isDistinct: Boolean): OrderBySelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, clause, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }

    /**
     * Receive the 'LIMIT' clause.
     */
    public inline infix fun  Table.SELECT(clause: LimitClause): LimitSelectStatement =
        select(kSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: LimitClause): LimitSelectStatement =
        select(kSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: LimitClause, isDistinct: Boolean): LimitSelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, clause, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }

    /**
     * Receive the 'GROUP BY' clause.
     */
    public inline infix fun  Table.SELECT(clause: GroupByClause): GroupBySelectStatement =
        select(kSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: GroupByClause): GroupBySelectStatement =
        select(kSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: GroupByClause, isDistinct: Boolean): GroupBySelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, clause, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }

    public inline fun  getKSerializer(): KSerializer = EmptySerializersModule().serializer()

    /**
     * The 'UNION' clause of Select.
     */

    private val unionSelectStatementGroupStack by lazy { ArrayDeque>() }

    private fun getSelectStatementGroup(): StatementContainer = unionSelectStatementGroupStack.lastOrNull() ?: transactionStatementsGroup ?: executiveEngine

    public inline fun  Table.UNION(block: Table.(Table) -> Unit): FinalSelectStatement {
        beginUnion()
        var selectStatement: SelectStatement? = null
        try {
            block(this)
            selectStatement = createUnionSelectStatement(false)
            return selectStatement
        } finally {
            endUnion(selectStatement)
        }
    }

    public inline fun  Table.UNION_ALL(block: Table.(Table) -> Unit): FinalSelectStatement {
        beginUnion()
        var selectStatement: SelectStatement? = null
        try {
            block(this)
            selectStatement = createUnionSelectStatement(true)
            return selectStatement
        } finally {
            endUnion(selectStatement)
        }
    }

    public fun  beginUnion() {
        unionSelectStatementGroupStack.add(UnionSelectStatementGroup())
    }

    public fun  createUnionSelectStatement(isUnionAll: Boolean): FinalSelectStatement {
        check(unionSelectStatementGroupStack.isNotEmpty()) { "Please invoke the 'beginUnion' before you invoke this function!!!" }
        return (unionSelectStatementGroupStack.last() as UnionSelectStatementGroup).unionStatements(isUnionAll)
    }

    public fun  endUnion(selectStatement: SelectStatement?) {
        unionSelectStatementGroupStack.removeLast()
        selectStatement?.let { addSelectStatement(it) }
    }

    /**
     * Receive the 'JOIN' clause.
     */

    public inline infix fun  Table.SELECT(clause: JoinClause): JoinStatementWithoutCondition =
        select(getKSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: JoinClause): JoinStatementWithoutCondition =
        select(getKSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: JoinClause, isDistinct: Boolean): JoinStatementWithoutCondition {
        val container = getSelectStatementGroup()
        return Select.select(this, clause, isDistinct, serializer, databaseConnection, container, ::addSelectStatement)
    }

    /**
     * Receive the natural join clause(includes 'NATURAL LEFT OUTER JOIN' and 'NATURAL INNER JOIN').
     */

    public inline infix fun  Table.SELECT(clause: NaturalJoinClause): JoinSelectStatement =
        select(getKSerializer(), clause, false)

    public inline infix fun  Table.SELECT_DISTINCT(clause: NaturalJoinClause): JoinSelectStatement =
        select(getKSerializer(), clause, true)

    public fun  Table.select(serializer: KSerializer, clause: NaturalJoinClause, isDistinct: Boolean): JoinSelectStatement {
        val container = getSelectStatementGroup()
        val statement = Select.select(this, clause, isDistinct, serializer, databaseConnection, container)
        addSelectStatement(statement)
        return statement
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy