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 table API #1946

Merged
merged 3 commits into from
Dec 19, 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
20 changes: 20 additions & 0 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Alias.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package org.jetbrains.exposed.sql

/** Represents a temporary SQL identifier, [alias], for a [delegate] table. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could mention if it exists only on Exposed side or also on the Db side

class Alias<out T : Table>(val delegate: T, val alias: String) : Table() {

override val tableName: String get() = alias

/** The table name along with its [alias]. */
val tableNameWithAlias: String = "${delegate.tableName} $alias"

private fun <T : Any?> Column<T>.clone() = Column<T>(this@Alias, name, columnType)

/**
* Returns the original column from the [delegate] table, or `null` if the [column] is not associated
* with this table alias.
*/
fun <R> originalColumn(column: Column<R>): Column<R>? {
@Suppress("UNCHECKED_CAST")
return if (column.table == this) {
Expand Down Expand Up @@ -108,18 +114,32 @@ class QueryAlias(val query: AbstractQuery<*>, val alias: String) : ColumnSet() {
private fun <T : Any?> Column<T>.clone() = Column<T>(table.alias(alias), name, columnType)
}

/**
* Creates a temporary identifier, [alias], for [this] table.
*
* The alias will be used on the database-side if the alias object is used to generate an SQL statement,
* instead of [this] table object.
*
* @sample org.jetbrains.exposed.sql.tests.shared.dml.JoinTests.testJoinWithAlias01
*/
fun <T : Table> T.alias(alias: String) = Alias(this, alias)

/**
* Creates a temporary identifier, [alias], for [this] query.
*
* The alias will be used on the database-side if the alias object is used to generate an SQL statement,
* instead of [this] query object.
*
* @sample org.jetbrains.exposed.sql.tests.shared.AliasesTests.testJoinSubQuery01
*/
fun <T : AbstractQuery<*>> T.alias(alias: String) = QueryAlias(this, alias)

/**
* Creates a temporary identifier, [alias], for [this] expression.
*
* The alias will be used on the database-side if the alias object is used to generate an SQL statement,
* instead of [this] expression object.
*
* @sample org.jetbrains.exposed.sql.tests.shared.AliasesTests.testJoinSubQuery01
*/
fun <T> Expression<T>.alias(alias: String) = ExpressionAlias(this, alias)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Column<T>(
/** Data type of the column. */
override val columnType: IColumnType
) : ExpressionWithColumnType<T>(), DdlAware, Comparable<Column<*>> {
/** The foreign key constraint on this column, or `null` if the column is not referencing. */
var foreignKey: ForeignKeyConstraint? = null

/** Returns the column that this column references. */
Expand All @@ -37,6 +38,7 @@ class Column<T>(
var defaultValueFun: (() -> T)? = null
internal var dbDefaultValue: Expression<T>? = null

/** Returns the default value for this column on the database-side. */
fun defaultValueInDb() = dbDefaultValue

internal var isDatabaseGenerated: Boolean = false
Expand Down Expand Up @@ -82,6 +84,7 @@ class Column<T>(
return listOfNotNull("$alterTablePrefix $columnDefinition", addConstr)
}

/** Returns the SQL statements that modify this column according to differences in the provided [ColumnDiff]. */
fun modifyStatements(columnDiff: ColumnDiff): List<String> = currentDialect.modifyColumn(this, columnDiff)

override fun modifyStatement(): List<String> = currentDialect.modifyColumn(this, ColumnDiff.AllChanged)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ class AutoIncColumnType(
if (delegate is IntegerColumnType) sequence.nextIntVal() else sequence.nextLongVal()
}

/** Returns the name of the sequence used to generate new values for this auto-increment column. */
/** The name of the sequence used to generate new values for this auto-increment column. */
val autoincSeq: String?
get() = _autoincSeq.takeIf { currentDialect.supportsCreateSequence }
?: fallbackSeqName.takeIf { currentDialect.needsSequenceToAutoInc }

val nextValExpression: NextVal<*>? get() = nextValValue.takeIf { autoincSeq != null }
/** The SQL expression that advances the sequence of this auto-increment column. */
val nextValExpression: NextVal<*>?
get() = nextValValue.takeIf { autoincSeq != null }

private fun resolveAutoIncType(columnType: IColumnType): String = when {
columnType is EntityIDColumnType<*> -> resolveAutoIncType(columnType.idColumn.columnType)
Expand Down Expand Up @@ -172,7 +174,13 @@ internal fun IColumnType.rawSqlType(): IColumnType = when {
else -> this
}

class EntityIDColumnType<T : Comparable<T>>(val idColumn: Column<T>) : ColumnType() {
/**
* Identity column type for storing unique [EntityID] values.
*/
class EntityIDColumnType<T : Comparable<T>>(
/** The underlying wrapped column storing the identity values. */
val idColumn: Column<T>
) : ColumnType() {

init {
require(idColumn.table is IdTable<*>) { "EntityId supported only for IdTables" }
Expand Down Expand Up @@ -669,9 +677,13 @@ open class VarCharColumnType(

/**
* Character column for storing strings of arbitrary length using the specified [collate] type.
* [eagerLoading] means what content will be loaded immediately when data loaded from database.
*/
open class TextColumnType(collate: String? = null, val eagerLoading: Boolean = false) : StringColumnType(collate) {
open class TextColumnType(
collate: String? = null,
/** Whether content will be loaded immediately when data is retrieved from the database. */
val eagerLoading: Boolean = false
) : StringColumnType(collate) {
/** The exact SQL type representing this character type. */
open fun preciseType() = currentDialect.dataTypeProvider.textType()

override fun sqlType(): String = buildString {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ abstract class CompositeColumn<T> : Expression<T>() {
internal var nullable: Boolean = false

/**
* Parse values from [compositeValue] and return list of real columns with its values
* Parses the [compositeValue] and returns a list of real columns with their values.
*
* @return key - real column, value - its parsed value
* @return Map of real columns as keys to their parsed values.
*/
abstract fun getRealColumnsWithValues(compositeValue: T): Map<Column<*>, Any?>

/**
* Return list of real columns, wrapped by this composite column
* Returns a list of real columns, wrapped by this composite column.
*/
abstract fun getRealColumns(): List<Column<*>>

/**
* Restore the composite value from its parts loaded from the DB
* Restores the composite value based on its component column values loaded from the database.
*/
abstract fun restoreValueFromParts(parts: Map<Column<*>, Any?>): T

Expand All @@ -31,12 +31,14 @@ abstract class CompositeColumn<T> : Expression<T>() {
}

/**
* Extension of [CompositeColumn] which consists of two columns
* Extension of [CompositeColumn] that consists of two columns, [column1] and [column2].
*/
abstract class BiCompositeColumn<C1, C2, T>(
protected val column1: Column<C1>,
protected val column2: Column<C2>,
/** Transformation that receives the column's composite value and returns the parsed values of the underlying columns. */
val transformFromValue: (T) -> Pair<C1?, C2?>,
/** Transformation that receives the retrieved values of [column1] and [column2] and returns a composite value. */
val transformToValue: (Any?, Any?) -> T
) : CompositeColumn<T>() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,22 @@ interface DdlAware {
}

/**
* Represents reference constraint actions.
* Read [Referential actions](https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-key-referential-actions) from MySQL docs
* or on [StackOverflow](https://stackoverflow.com/a/6720458/813981)
* Represents referential actions used by `ON UPDATE` or `ON DELETE` subclauses of a `FOREIGN KEY` constraint clause.
*/
enum class ReferenceOption {
/** Updates/deletes the referenced parent row, in addition to any rows in the referencing child table. */
CASCADE,

/** Updates/deletes the referenced parent row, and sets the column in the referencing child table to `NULL`. */
SET_NULL,

/** Prevents updating/deleting the referenced parent row. */
RESTRICT,

/** In some, but not all, databases, this action is equivalent to `RESTRICT`. Please check the documentation. */
NO_ACTION,

/** Updates/deletes the referenced parent row, and sets the column in the referencing child table to its default value. */
SET_DEFAULT;

override fun toString(): String = name.replace("_", " ")
Expand All @@ -41,6 +48,7 @@ enum class ReferenceOption {
* Represents a foreign key constraint.
*/
data class ForeignKeyConstraint(
/** Mapping of referenced parent table columns to the foreign key columns in their child tables. */
val references: Map<Column<*>, Column<*>>,
private val onUpdate: ReferenceOption?,
private val onDelete: ReferenceOption?,
Expand All @@ -57,8 +65,10 @@ data class ForeignKeyConstraint(
private val tx: Transaction
get() = TransactionManager.current()

/** The columns of the referencing child table. */
val target: LinkedHashSet<Column<*>> = LinkedHashSet(references.values)

/** The referencing child table. */
val targetTable: Table = target.first().table

/** Name of the child table. */
Expand All @@ -69,8 +79,10 @@ data class ForeignKeyConstraint(
private val targetColumns: String
get() = target.joinToString { tx.identity(it) }

/** The columns of the referenced parent table. */
val from: LinkedHashSet<Column<*>> = LinkedHashSet(references.keys)

/** The referenced parent table. */
val fromTable: Table = from.first().table

/** Name of the parent table. */
Expand All @@ -89,7 +101,7 @@ data class ForeignKeyConstraint(
val deleteRule: ReferenceOption?
get() = onDelete ?: currentDialectIfAvailable?.defaultReferenceOption

/** Custom foreign key name if was provided */
/** Custom foreign key name, if provided. */
val customFkName: String?
get() = name

Expand Down Expand Up @@ -156,6 +168,7 @@ data class ForeignKeyConstraint(
return listOf("ALTER TABLE $fromTableName DROP $constraintType $fkName")
}

/** Returns the child table column that is referencing the provided column in the parent table. */
fun targetOf(from: Column<*>): Column<*>? = references[from]

operator fun plus(other: ForeignKeyConstraint): ForeignKeyConstraint {
Expand Down Expand Up @@ -214,6 +227,7 @@ data class CheckConstraint(
}
}

/** A conditional expression used as a filter when creating a partial index. */
typealias FilterCondition = (SqlExpressionBuilder.() -> Op<Boolean>)?

/**
Expand Down
28 changes: 15 additions & 13 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Sequence.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.currentDialect

/**
* Database Sequence.
* Represents a database sequence.
*
* @param name Name of the sequence.
* @param startWith Beginning of the sequence.
* @param incrementBy Value is added to the current sequence value to create a new value.
* @param minValue Minimum value a sequence can generate.
* @param maxValue Maximum value for the sequence.
* @param cycle Allows the sequence to wrap around when the [maxValue] or [minValue] has been reached by an ascending or descending sequence respectively.
* @param cache Specifies how many sequence numbers are to be preallocated and stored in memory for faster access.
* @param name Name of the sequence.
* @param startWith Beginning of the sequence.
* @param incrementBy Value to be added to the current sequence value when creating a new value.
* @param minValue Minimum value a sequence can generate.
* @param maxValue Maximum value for the sequence.
* @param cycle Allows the sequence to wrap around when the [maxValue] or [minValue] has been reached by
* an ascending or descending sequence respectively.
* @param cache Specifies how many sequence numbers are to be pre-allocated and stored in memory for faster access.
*/
class Sequence(
private val name: String,
Expand All @@ -24,15 +25,15 @@ class Sequence(
val cycle: Boolean? = null,
val cache: Long? = null
) {
/** This name of this sequence in proper database casing. */
val identifier
get() = TransactionManager.current().db.identifierManager.cutIfNecessaryAndQuote(name)

val identifier get() = TransactionManager.current().db.identifierManager.cutIfNecessaryAndQuote(name)

/** The SQL statements that create this sequence. */
val ddl: List<String>
get() = createStatement()

/**
* Returns the SQL command that creates sequence with the specified properties.
*/
/** Returns the SQL statements that create this sequence. */
fun createStatement(): List<String> {
if (!currentDialect.supportsCreateSequence) {
throw UnsupportedByDialectException("The current dialect doesn't support create sequence statement", currentDialect)
Expand All @@ -59,6 +60,7 @@ class Sequence(
return listOf(createSequenceDDL)
}

/** Returns the SQL statements that drop this sequence. */
fun dropStatement(): List<String> {
if (!currentDialect.supportsCreateSequence) {
throw UnsupportedByDialectException("The current dialect doesn't support drop sequence statement", currentDialect)
Expand Down
19 changes: 17 additions & 2 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,15 @@ class Join(
/** Return `true` if the specified [table] is already in this join, `false` otherwise. */
fun alreadyInJoin(table: Table): Boolean = joinParts.any { it.joinPart == table }

/** Represents a component of an existing join relation. */
internal class JoinPart(
/** The column set `JOIN` type. */
val joinType: JoinType,
/** The column set to join to other components of the relation. */
val joinPart: ColumnSet,
/** The [JoinCondition] expressions used to match rows from two joined tables. */
val conditions: List<JoinCondition>,
/** The conditions used to join tables, placed in the `ON` clause. */
val additionalConstraint: (SqlExpressionBuilder.() -> Op<Boolean>)? = null
) {
init {
Expand All @@ -333,6 +338,7 @@ class Join(
) { "Missing join condition on $${this.joinPart}" }
}

/** Appends the SQL representation of this join component to the specified [QueryBuilder]. */
fun describe(transaction: Transaction, builder: QueryBuilder) = with(builder) {
append(" $joinType JOIN ")
val isJoin = joinPart is Join
Expand All @@ -349,6 +355,7 @@ class Join(
}
}

/** Appends the SQL representation of the conditions in the `ON` clause to the specified [QueryBuilder]. */
fun appendConditions(builder: QueryBuilder) = builder {
conditions.appendTo(this, " AND ") { (pkColumn, fkColumn) -> append(pkColumn, " = ", fkColumn) }
if (additionalConstraint != null) {
Expand Down Expand Up @@ -489,6 +496,7 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
type
).also { _columns.addColumn(it) }

/** Adds all wrapped column components of a [CompositeColumn] to the table. */
fun <R, T : CompositeColumn<R>> registerCompositeColumn(column: T): T = column.apply {
getRealColumns().forEach {
_columns.addColumn(
Expand Down Expand Up @@ -545,8 +553,8 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
/**
* Returns the primary key of the table if present, `null` otherwise.
*
* You have to define it explicitly by overriding that val instead or use one of predefined
* table types like [IntIdTable], [LongIdTable], or [UUIDIdTable]
* The primary key can be defined explicitly by overriding the property directly or by using one of the predefined
* table types like `IntIdTable`, `LongIdTable`, or `UUIDIdTable`.
*/
open val primaryKey: PrimaryKey? = null

Expand Down Expand Up @@ -1068,6 +1076,7 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
return replaceColumn(this, newColumn)
}

/** Marks this [CompositeColumn] as nullable. */
@Suppress("UNCHECKED_CAST")
fun <T : Any, C : CompositeColumn<T>> C.nullable(): CompositeColumn<T?> = apply {
nullable = true
Expand Down Expand Up @@ -1390,6 +1399,12 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {

override fun hashCode(): Int = tableName.hashCode()

/**
* Represents a special dummy `DUAL` table that is accessible by all users.
*
* This can be useful when needing to execute queries that do not rely on a specific table object.
* **Note:** `DUAL` tables are only automatically supported by Oracle. Please check the documentation.
*/
object Dual : Table("dual")
}

Expand Down
Loading
Loading