Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add missing KDocs for exposed-core api package #1896

Merged
merged 2 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,68 @@

package org.jetbrains.exposed.sql.statements.api

/** Represents a wrapper for a database connection. */
interface ExposedConnection<OriginalConnection : Any> {
/** Whether the connection has been closed. */
val isClosed: Boolean

/** Saves all changes since the last commit or rollback operation. */
fun commit()

/** Reverts all changes since the last commit or rollback operation. */
fun rollback()

/** Closes the connection and releases any of its database and/or driver resources. */
fun close()

/** Whether the connection is in auto-commit mode. */
var autoCommit: Boolean

/** Whether the connection is in read-only mode. */
var readOnly: Boolean

/** The transaction isolation level of the connection. */
var transactionIsolation: Int

/** The underlying database connection object contained by this wrapper. */
val connection: OriginalConnection

/**
* Returns a precompiled [sql] statement stored as a [PreparedStatementApi] implementation.
*
* To indicate that auto-generated keys should be made available for retrieval, set [returnKeys] to `true`.
*/
fun prepareStatement(sql: String, returnKeys: Boolean): PreparedStatementApi

/**
* Returns a precompiled [sql] statement stored as a [PreparedStatementApi] implementation.
*
* To indicate that auto-generated keys should be made available for retrieval, provide the names of
* the target [columns] that contain the keys to be returned.
*/
fun prepareStatement(sql: String, columns: Array<String>): PreparedStatementApi

/** Sends a collection of SQL strings to the database for execution as a batch statement. */
fun executeInBatch(sqls: List<String>)

/** The name of the connection's catalog. */
var catalog: String

/** The name of the connection's schema. */
var schema: String

/**
* Calls the specified function [body] with an [ExposedDatabaseMetadata] implementation as its receiver and
* returns the retrieved metadata as a result.
*/
fun <T> metadata(body: ExposedDatabaseMetadata.() -> T): T

/** Sets and returns a new savepoint with the specified [name]. */
fun setSavepoint(name: String): ExposedSavepoint

/** Removes the specified [savepoint]. */
fun releaseSavepoint(savepoint: ExposedSavepoint)

/** Reverts all changes since the specified [savepoint] was set. */
fun rollback(savepoint: ExposedSavepoint)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import org.jetbrains.exposed.sql.vendors.currentDialectIfAvailable
import java.io.IOException
import java.io.InputStream

/** Represents a wrapper for an [inputStream] of bytes to be used in binary columns. */
class ExposedBlob(inputStream: InputStream) {
constructor(bytes: ByteArray) : this (bytes.inputStream())

/** The [InputStream] contained by this wrapper. */
var inputStream = inputStream
private set

/** The `ByteArray` returned as a result of reading the contained [InputStream] completely. */
val bytes: ByteArray
get() = inputStream.readBytes().also {
if (inputStream.markSupported()) {
Expand All @@ -35,6 +38,7 @@ class ExposedBlob(inputStream: InputStream) {

override fun hashCode(): Int = bytes.contentHashCode()

/** Returns the hex-encoded string of the contained [InputStream] after being read. */
fun hexString(): String = bytes.toHexString()

/** Returns the hex-encoded string of a ByteArray. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,74 @@ import org.jetbrains.exposed.sql.vendors.PrimaryKeyMetadata
import org.jetbrains.exposed.sql.vendors.SchemaMetadata
import java.math.BigDecimal

/**
* Base class responsible for retrieving and storing information about the JDBC driver and underlying [database].
*/
abstract class ExposedDatabaseMetadata(val database: String) {

/** The connection URL for the database. */
abstract val url: String

/** The version number of the database as a `BigDecimal`. */
abstract val version: BigDecimal

/** The name of the database based on the name of the underlying JDBC driver. */
abstract val databaseDialectName: String

/** The version number of the database product as a `String`. */
abstract val databaseProductVersion: String

/** The default transaction isolation level for the database. */
abstract val defaultIsolationLevel: Int

/** Whether the database supports `ALTER TABLE` with an add column clause. */
abstract val supportsAlterTableWithAddColumn: Boolean

/** Whether the database supports getting multiple result sets from a single execute. */
abstract val supportsMultipleResultSets: Boolean

/** Whether the database supports `SELECT FOR UPDATE` statements. */
abstract val supportsSelectForUpdate: Boolean

@Deprecated(
message = "it's temporary solution which will be replaced in a future releases. Do not use it in your code",
level = DeprecationLevel.ERROR
)
abstract val currentScheme: String

/** Clears and resets any stored information about the database's current schema to default values. */
abstract fun resetCurrentScheme()

/** A mapping of all schema names in the database to a list of all defined table names in each schema. */
abstract val tableNames: Map<String, List<String>>

/** A list of existing schema names. */
abstract val schemaNames: List<String>

/**
* Returns the current schema name and a list of its existing table names, stored as [SchemaMetadata].
*
* A [tableNamesCache] of previously read metadata, if applicable, can be provided to avoid retrieving new metadata.
*/
abstract fun tableNamesByCurrentSchema(tableNamesCache: Map<String, List<String>>?): SchemaMetadata

/** Returns a map with the [ColumnMetadata] of all the defined columns in each of the specified [tables]. */
abstract fun columns(vararg tables: Table): Map<Table, List<ColumnMetadata>>

/** Returns a map with all the defined indices in each of the specified [tables]. */
abstract fun existingIndices(vararg tables: Table): Map<Table, List<Index>>

/** Returns a map with the [PrimaryKeyMetadata] in each of the specified [tables]. */
abstract fun existingPrimaryKeys(vararg tables: Table): Map<Table, PrimaryKeyMetadata?>

/**
* Returns a map with the [ForeignKeyConstraint] of all the defined columns in each of the specified [tables],
* with the table name used as the key.
*/
abstract fun tableConstraints(tables: List<Table>): Map<String, List<ForeignKeyConstraint>>

/** Clears any cached values. */
abstract fun cleanCache()

/** The database-specific and metadata-reliant implementation of [IdentifierManagerApi]. */
abstract val identifierManager: IdentifierManagerApi
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
package org.jetbrains.exposed.sql.statements.api

/**
* Base class representing a savepoint, with the specified [name], which can be referenced during a
* rollback operation to undo any changes made after the point in the transaction.
*/
@Suppress("UnnecessaryAbstractClass")
abstract class ExposedSavepoint(val name: String)
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,50 @@ import org.jetbrains.exposed.sql.vendors.ANSI_SQL_2003_KEYWORDS
import org.jetbrains.exposed.sql.vendors.VENDORS_KEYWORDS
import org.jetbrains.exposed.sql.vendors.currentDialect

/** Base class responsible for the parsing and processing of identifier tokens in SQL command syntax. */
abstract class IdentifierManagerApi {
/** The string used to quote SQL identifiers for the database. */
abstract val quoteString: String

/** Whether the database treats mixed case unquoted identifiers as case-insensitive and stores them in upper case. */
protected abstract val isUpperCaseIdentifiers: Boolean

/** Whether the database treats mixed case quoted identifiers as case-insensitive and stores them in upper case. */
protected abstract val isUpperCaseQuotedIdentifiers: Boolean

/** Whether the database treats mixed case unquoted identifiers as case-insensitive and stores them in lower case. */
protected abstract val isLowerCaseIdentifiers: Boolean

/** Whether the database treats mixed case quoted identifiers as case-insensitive and stores them in lower case. */
protected abstract val isLowerCaseQuotedIdentifiers: Boolean

/** Whether the database treats and stores mixed case unquoted identifiers as case-sensitive. */
protected abstract val supportsMixedIdentifiers: Boolean

/** Whether the database treats and stores mixed case quoted identifiers as case-sensitive. */
protected abstract val supportsMixedQuotedIdentifiers: Boolean

/** Returns all keywords for the database beyond the [ANSI_SQL_2003_KEYWORDS]. */
protected abstract fun dbKeywords(): List<String>
val keywords by lazy { ANSI_SQL_2003_KEYWORDS + VENDORS_KEYWORDS[currentDialect.name].orEmpty() + dbKeywords() }

/** All keywords for the database, including [ANSI_SQL_2003_KEYWORDS] and database-specific keywords. */
val keywords by lazy {
ANSI_SQL_2003_KEYWORDS + VENDORS_KEYWORDS[currentDialect.name].orEmpty() + dbKeywords()
}

/** The database-specific special characters that can be additionally used in unquoted identifiers. */
protected abstract val extraNameCharacters: String

/** The [OracleVersion] of the database, if Oracle is the underlying DBMS; otherwise, [OracleVersion.NonOracle]. */
protected abstract val oracleVersion: OracleVersion

/** The maximum number of characters in a column name allowed by the database. */
protected abstract val maxColumnNameLength: Int

/** Oracle version number classifier. */
protected enum class OracleVersion { Oracle11g, Oracle12_1g, Oracle12plus, NonOracle }

/** The maximum number of characters in an identifier allowed by the database. */
protected val identifierLengthLimit by lazy {
@Suppress("MagicNumber")
when (oracleVersion) {
Expand Down Expand Up @@ -57,6 +85,7 @@ abstract class IdentifierManagerApi {
TransactionManager.currentOrNull()?.db?.config?.preserveKeywordCasing == true
}

/** Returns whether an SQL token should be wrapped in quotations and caches the returned value. */
fun needQuotes(identity: String): Boolean {
return checkedIdentitiesCache.getOrPut(identity.lowercase()) {
!identity.isAlreadyQuoted() && (identity.isAKeyword() || !identity.isIdentifier())
Expand All @@ -65,6 +94,7 @@ abstract class IdentifierManagerApi {

private fun String.isAlreadyQuoted() = startsWith(quoteString) && endsWith(quoteString)

/** Returns whether an [identity] should be wrapped in quotations and caches the returned value. */
fun shouldQuoteIdentifier(identity: String): Boolean = shouldQuoteIdentifiersCache.getOrPut(identity) {
val alreadyQuoted = identity.isAlreadyQuoted()
val alreadyLower = identity == identity.lowercase()
Expand All @@ -81,6 +111,10 @@ abstract class IdentifierManagerApi {
}
}

/**
* Returns an [identity] in a casing appropriate for its identifier status and the database,
* then caches the returned value.
*/
fun inProperCase(identity: String): String = identifiersInProperCaseCache.getOrPut(identity) {
val alreadyQuoted = identity.isAlreadyQuoted()
when {
Expand All @@ -96,6 +130,7 @@ abstract class IdentifierManagerApi {
}
}

/** Returns an SQL token wrapped in quotations, if validated as necessary. */
fun quoteIfNecessary(identity: String): String {
return if (identity.contains('.') && !identity.isAlreadyQuoted()) {
identity.split('.').joinToString(".") { quoteTokenIfNecessary(it) }
Expand All @@ -104,6 +139,7 @@ abstract class IdentifierManagerApi {
}
}

/** Returns an [identity] wrapped in quotations, if validated as necessary. */
fun quoteIdentifierWhenWrongCaseOrNecessary(identity: String): String {
val inProperCase = inProperCase(identity)
return if (shouldQuoteIdentifier(identity) && inProperCase != identity) {
Expand All @@ -113,6 +149,7 @@ abstract class IdentifierManagerApi {
}
}

/** Returns an [identity] wrapped in quotations and containing no more than the maximum [identifierLengthLimit]. */
fun cutIfNecessaryAndQuote(identity: String) = quoteIfNecessary(identity.take(identifierLengthLimit))

private fun quoteTokenIfNecessary(token: String): String = if (needQuotes(token)) quote(token) else token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import java.io.InputStream
import java.sql.PreparedStatement
import java.sql.ResultSet

/** Represents a precompiled SQL statement. */
@Suppress("TooManyFunctions")
interface PreparedStatementApi {

/** The number of result set rows that should be fetched when generated by an executed statement. */
var fetchSize: Int?

/** The number of seconds the JDBC driver will wait for a statement to execute. */
var timeout: Int?

/**
* Sets the value for each column or expression in [args] into the appropriate statement parameter and
* returns the number of parameters filled.
*/
fun fillParameters(args: Iterable<Pair<IColumnType, Any?>>): Int {
args.forEachIndexed { index, (c, v) ->
c.setParameter(this, index + 1, c.valueToDB(v))
Expand All @@ -21,6 +27,7 @@ interface PreparedStatementApi {
return args.count() + 1
}

/** Adds parameters to the statement's batch of SQL commands. */
fun addBatch()

/**
Expand All @@ -46,14 +53,18 @@ interface PreparedStatementApi {
*/
fun executeMultiple(): List<StatementResult>

/** The [ResultSet] object generated by the executed statement, or `null` if none was retrieved. */
val resultSet: ResultSet?

operator fun set(index: Int, value: Any)

/** Sets the statement parameter at the [index] position to SQL NULL, if allowed wih the specified [columnType]. */
fun setNull(index: Int, columnType: IColumnType)

/** Sets the statement parameter at the [index] position to the provided [inputStream]. */
fun setInputStream(index: Int, inputStream: InputStream)

/** Closes the statement, if still open, and releases any of its database and/or driver resources. */
fun closeIfPossible()

/**
Expand All @@ -64,5 +75,6 @@ interface PreparedStatementApi {
*/
fun executeBatch(): List<Int>

/** Cancels the statement, if supported by the database. */
fun cancel()
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData)
}
}

/** Returns a list of existing schema names. */
override val schemaNames: List<String> get() = schemaNames()

/** Returns a list of existing schema names. */
Expand All @@ -132,10 +131,6 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData)
return schemas.map { identifierManager.inProperCase(it) }
}

/**
* Returns the default schema name and a list of its existing table names, as [SchemaMetadata],
* found either by reading metadata or from a cache of previously read metadata.
*/
override fun tableNamesByCurrentSchema(tableNamesCache: Map<String, List<String>>?): SchemaMetadata {
val tablesInSchema = (tableNamesCache ?: tableNames).getValue(currentSchema!!)
return SchemaMetadata(currentSchema!!, tablesInSchema)
Expand Down
Loading