From 6e74f94b712734b9c8a0debf7f4f253567bc8fe3 Mon Sep 17 00:00:00 2001 From: bog-walk <82039410+bog-walk@users.noreply.github.com> Date: Fri, 24 Nov 2023 19:12:47 -0500 Subject: [PATCH] docs: Add missing KDocs for exposed-core api package (#1896) * docs: Add missing KDocs for exposed-core api package Add KDocs to `statements.api` package. --- .../sql/statements/api/ConnectionApi.kt | 40 +++++++++++++++++++ .../exposed/sql/statements/api/ExposedBlob.kt | 4 ++ .../statements/api/ExposedDatabaseMetadata.kt | 36 ++++++++++++++++- .../sql/statements/api/ExposedSavepoint.kt | 4 ++ .../statements/api/IdentifierManagerApi.kt | 39 +++++++++++++++++- .../statements/api/PreparedStatementApi.kt | 14 ++++++- .../jdbc/JdbcDatabaseMetadataImpl.kt | 5 --- 7 files changed, 134 insertions(+), 8 deletions(-) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ConnectionApi.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ConnectionApi.kt index 87ef38be7a..3f9ff28244 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ConnectionApi.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ConnectionApi.kt @@ -2,28 +2,68 @@ package org.jetbrains.exposed.sql.statements.api +/** Represents a wrapper for a database connection. */ interface ExposedConnection { + /** 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): PreparedStatementApi + + /** Sends a collection of SQL strings to the database for execution as a batch statement. */ fun executeInBatch(sqls: List) + /** 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 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) } diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedBlob.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedBlob.kt index 1b05939d60..647cdc96f7 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedBlob.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedBlob.kt @@ -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()) { @@ -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. */ diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt index aaa0b4c26f..2925086865 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt @@ -8,18 +8,32 @@ 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( @@ -27,21 +41,41 @@ abstract class ExposedDatabaseMetadata(val database: String) { 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> + + /** A list of existing schema names. */ abstract val schemaNames: List + /** + * 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>?): 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> + /** Returns a map with all the defined indices in each of the specified [tables]. */ abstract fun existingIndices(vararg tables: Table): Map> + /** Returns a map with the [PrimaryKeyMetadata] in each of the specified [tables]. */ abstract fun existingPrimaryKeys(vararg tables: Table): Map + /** + * 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): Map> + /** Clears any cached values. */ abstract fun cleanCache() + /** The database-specific and metadata-reliant implementation of [IdentifierManagerApi]. */ abstract val identifierManager: IdentifierManagerApi } diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedSavepoint.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedSavepoint.kt index 20b5c6ddc0..1620284f03 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedSavepoint.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedSavepoint.kt @@ -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) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/IdentifierManagerApi.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/IdentifierManagerApi.kt index c200e26c3e..efd5175803 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/IdentifierManagerApi.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/IdentifierManagerApi.kt @@ -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 - 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) { @@ -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()) @@ -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() @@ -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 { @@ -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) } @@ -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) { @@ -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 diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/PreparedStatementApi.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/PreparedStatementApi.kt index f0bf024747..cff6bd460a 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/PreparedStatementApi.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/PreparedStatementApi.kt @@ -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>): Int { args.forEachIndexed { index, (c, v) -> c.setParameter(this, index + 1, c.valueToDB(v)) @@ -21,6 +27,7 @@ interface PreparedStatementApi { return args.count() + 1 } + /** Adds parameters to the statement's batch of SQL commands. */ fun addBatch() /** @@ -46,14 +53,18 @@ interface PreparedStatementApi { */ fun executeMultiple(): List + /** 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() /** @@ -64,5 +75,6 @@ interface PreparedStatementApi { */ fun executeBatch(): List + /** Cancels the statement, if supported by the database. */ fun cancel() } diff --git a/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt b/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt index 12d9086a9b..dbb1446b7d 100644 --- a/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt +++ b/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt @@ -117,7 +117,6 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) } } - /** Returns a list of existing schema names. */ override val schemaNames: List get() = schemaNames() /** Returns a list of existing schema names. */ @@ -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>?): SchemaMetadata { val tablesInSchema = (tableNamesCache ?: tableNames).getValue(currentSchema!!) return SchemaMetadata(currentSchema!!, tablesInSchema)