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

com.trendyol.stove.testing.e2e.rdbms.SqlOperations.kt Maven / Gradle / Ivy

package com.trendyol.stove.testing.e2e.rdbms

import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
import io.r2dbc.spi.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.reactive.*

/**
 * An R2DBC abstraction that uses Kotlin coroutines.
 */
@StoveDsl
class SqlOperations(private val connectionFactory: ConnectionFactory) {
    private lateinit var connection: Connection

    /**
     * Opens a connection from the factory.
     */
    suspend fun open() {
        if (isOpen()) {
            return
        }
        connection = this.connectionFactory.create().awaitFirst()
    }

    fun isOpen(): Boolean = this::connection.isInitialized

    suspend fun close() {
        connection.close().awaitFirstOrNull()
    }

    /**
     * Open the connection within a transaction.
     */
    @StoveDsl
    suspend fun  transaction(invoke: suspend Handle.() -> T): T {
        val handle = Handle(connection)
        connection.beginTransaction().awaitFirstOrNull()
        try {
            val ret = invoke(handle)
            connection.commitTransaction().awaitFirstOrNull()
            return ret
        } catch (ex: Exception) {
            connection.rollbackTransaction().awaitFirstOrNull()
            throw ex
        }
    }
}

/**
 * Wrapper for [Connection].
 */
@StoveDsl
class Handle(val connection: Connection) {
    /**
     * Change transaction isolation level.
     */
    @StoveDsl
    fun transactionIsolationLevel(level: IsolationLevel) {
        require(connection.isAutoCommit)
        connection.transactionIsolationLevel = level
    }

    /**
     * Executes an update.
     * @param sql sql statement
     * @param parameters binding parameters
     * @return number of affected rows
     */
    @StoveDsl
    suspend fun execute(
        sql: String,
        vararg parameters: Any
    ) {
        connection.createStatement(sql)
            .let {
                parameters.forEachIndexed { index, param -> it.bind(index, param) }
                it
            }.execute().awaitFirstOrNull()
    }

    /**
     * Creates a select query.
     * @param sql sql statement
     * @return raw r2dbc result
     */
    @StoveDsl
    suspend fun select(sql: String): Result = connection.createStatement(sql).execute().awaitFirst()

    /**
     * Creates a select query.
     * @param sql sql statement
     * @param parameters binding parameters
     * @return query result
     */
    @StoveDsl
    suspend fun select(
        sql: String,
        vararg parameters: Any
    ): Flow {
        val query = this.connection.createStatement(sql)

        parameters.forEachIndexed { index, param ->
            query.bind(index, param)
        }

        return query.execute().awaitFirst().map { t, _ -> t }.asFlow()
    }

    /**
     * Creates a select query that returns [T] given the [rowMapper] function.
     * @param sql sql statement
     * @param parameters binding parameters
     * @param rowMapper row mapping function
     * @return query result
     */
    @StoveDsl
    suspend inline fun  select(
        sql: String,
        noinline rowMapper: (row: Row, rowMetadata: RowMetadata) -> T,
        vararg parameters: Any
    ): Flow {
        val query = this.connection.createStatement(sql)

        parameters.forEachIndexed { index, param ->
            query.bind(index, param)
        }

        return query.execute().awaitFirst().map(rowMapper).asFlow()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy