Changing ForeignKey to ForeignRowReference

This commit is contained in:
Andrew Golovashevich 2025-01-02 02:09:27 +03:00
parent bb90e08736
commit 3607030a87
5 changed files with 95 additions and 200 deletions

View File

@ -28,6 +28,8 @@ public interface ColumnType<@Suppress("unused") RuntimeType> {
public interface Builder { public interface Builder {
/** /**
* Type of internal row id. Can't be casted to types like integers or pointers. * Type of internal row id. Can't be casted to types like integers or pointers.
* @param TableUserExtension User's extension type for target table. For static type checking.
* @param table Descriptor of table whose row_id type will be obtained.
*/ */
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
@JvmName("ROW_ID") @JvmName("ROW_ID")
@ -172,9 +174,10 @@ public interface ColumnType<@Suppress("unused") RuntimeType> {
/** /**
* Descriptor of an internal row id type for static type-checking. * Descriptor of an internal row id type for static type-checking.
* @param TargetTableUserWrapper User's extension type for target table. For static type checking.
* @see ColumnType.Builder.ROW_ID * @see ColumnType.Builder.ROW_ID
*/ */
public interface ROW_ID : ColumnType<RowId<*>> public interface ROW_ID<TargetTableUserWrapper: Any> : ColumnType<RowId<TargetTableUserWrapper>>
/** /**
* Descriptor of a boolean type for static type-checking. * Descriptor of a boolean type for static type-checking.

View File

@ -1,118 +0,0 @@
package ru.landgrafhomyak.serdha.api.v0.ddl
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
/**
* Descriptor of a foreign key. Used for schema manipulations.
*
* @param ContainerTableUserExtension Type of [owner table's][ForeignKey.fromTable] user expression for static reporting errors when this descriptor passed to wrong table.
* @param TargetTableUserExtension Type of [target table's][ForeignKey.toTable] user expression for static reporting errors when this descriptor passed to wrong table.
*/
public interface ForeignKey<ContainerTableUserExtension : Any, TargetTableUserExtension : Any> {
/**
* Table that contains this foreign key. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("fromTable")
public val fromTable: Table<ContainerTableUserExtension, *>
/**
* Columns in [ForeignKey.fromTable] which are used to reference row in [ForeignKey.toTable]. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("fromColumns")
public val fromColumns: List<Column<*, *, ContainerTableUserExtension>>
/**
* Table referenced by this foreign key. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("toTable")
public val toTable: Table<TargetTableUserExtension, *>
/**
* Columns in [ForeignKey.toTable] that are identifying row(s). For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("toColumns")
public val toColumns: List<Column<*, *, TargetTableUserExtension>>
/**
* Enum of actions to do when value in any of [ForeignKey.toColumns] in referenced row is changed.
*/
public enum class OnUpdateAction {
/**
* Don't perform any actions in [ForeignKey.fromColumns]. May break reference.
*/
NO_ACTION,
/**
* Forbids changing values in [ForeignKey.toColumns] if there is at least one reference from [ForeignKey.fromTable].
*/
RESTRICT,
/**
* Sets `null` value to all columns in [ForeignKey.fromColumns] if any cell in [ForeignKey.toColumns] in referenced row was changed.
*
* All of [ForeignKey.fromColumns] must be nullable.
*/
SET_NULL,
/**
* Sets default value to all columns in [ForeignKey.fromColumns] if any cell in [ForeignKey.toColumns] in referenced row was changed.
*
* All of [ForeignKey.fromColumns] must have [DefaultConstraint].
*/
SET_DEFAULT,
/**
* Reflects all changes from [ForeignKey.toColumns] to [ForeignKey.fromColumns].
*/
CASCADE
}
/**
* Enum of actions to do when referenced row in [ForeignKey.toTable] deleted.
*/
public enum class OnDeleteAction {
/**
* Don't perform any actions in [ForeignKey.fromColumns]. Breaks reference.
*/
NO_ACTION,
/**
* Forbids deleting row in [ForeignKey.toTable] if there is at least one reference from [ForeignKey.fromTable].
*/
RESTRICT,
/**
* Sets `null` value to all columns in [ForeignKey.fromColumns] if referenced row was deleted.
*
* All of [ForeignKey.fromColumns] must be nullable.
*/
SET_NULL,
/**
* Sets default value to all columns in [ForeignKey.fromColumns] if referenced row was deleted.
*
* All of [ForeignKey.fromColumns] must have [DefaultConstraint].
*/
SET_DEFAULT,
/**
* Deletes all rows in [ForeignKey.fromTable] that are referencing deleted row in [ForeignKey.toTable].
*/
CASCADE
}
public companion object {
@JvmStatic
public val DEFAULT_ON_UPDATE_ACTION: OnUpdateAction
inline get() = OnUpdateAction.CASCADE
@JvmStatic
public val DEFAULT_ON_DELETE_ACTION: OnDeleteAction
inline get() = OnDeleteAction.RESTRICT
}
}

View File

@ -0,0 +1,63 @@
package ru.landgrafhomyak.serdha.api.v0.ddl
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
/**
* Descriptor of a reference to row in another table (== foreign key to `INTEGER PRIMARY KEY AUTOINCREMENT`). Used for schema manipulations.
*
* @param ContainerTableUserExtension Type of [owner table's][ForeignRowReference.fromTable] user expression for static reporting errors when this descriptor passed to wrong table.
* @param TargetTableUserExtension Type of [target table's][ForeignRowReference.toTable] user expression for static reporting errors when this descriptor passed to wrong table.
*/
public interface ForeignRowReference<ContainerTableUserExtension : Any, TargetTableUserExtension : Any> {
/**
* Table that contains references. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("fromTable")
public val fromTable: Table<ContainerTableUserExtension, *>
/**
* Column in [ForeignRowReference.fromTable] which references row in [ForeignRowReference.toTable]. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("fromColumn")
public val fromColumn: Column<RowId<TargetTableUserExtension>, ColumnType.ROW_ID<TargetTableUserExtension>, ContainerTableUserExtension>
/**
* Table referenced by this foreign key. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("toTable")
public val toTable: Table<TargetTableUserExtension, *>
/**
* Row id column in [ForeignRowReference.toTable]. For debugging.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@get:JvmName("toColumn")
public val toColumn: Column<RowId<TargetTableUserExtension>, ColumnType.ROW_ID<TargetTableUserExtension>, TargetTableUserExtension>
/**
* Enum of actions to do when referenced row in [ForeignRowReference.toTable] deleted.
*/
public enum class OnDeleteAction {
/**
* Forbids deleting row in [ForeignRowReference.toTable] if there is at least one reference from [ForeignRowReference.fromTable].
*/
RESTRICT,
/**
* Replaces all references to deleted row in [ForeignRowReference.fromColumn] with `null`.
*
* Type of [ForeignRowReference.fromColumn] must be [nullable][ColumnType.Builder.nullableOf].
*/
SET_NULL,
/**
* Deletes all rows in [ForeignRowReference.fromTable] that are referencing deleted row in [ForeignRowReference.toTable].
*/
CASCADE
}
}

View File

@ -1,7 +1,6 @@
package ru.landgrafhomyak.serdha.api.v0.ddl package ru.landgrafhomyak.serdha.api.v0.ddl
import ru.landgrafhomyak.serdha.api.v0.Expression import ru.landgrafhomyak.serdha.api.v0.Expression
import ru.landgrafhomyak.serdha.api.v0.LowLevelApi
public interface TableCreator<TableUserExtension : Any> { public interface TableCreator<TableUserExtension : Any> {
public val expressionBuilder: Expression.Builder<TableUserExtension> public val expressionBuilder: Expression.Builder<TableUserExtension>
@ -22,64 +21,15 @@ public interface TableCreator<TableUserExtension : Any> {
@Suppress("PropertyName") @Suppress("PropertyName")
public val rowId_uniqueConstraint: UniqueIndex<TableUserExtension> public val rowId_uniqueConstraint: UniqueIndex<TableUserExtension>
@Suppress("FunctionName") public fun <TargetTableUserWrapper : Any> selfRowReference(
@LowLevelApi onDelete: ForeignRowReference.OnDeleteAction,
public fun <TargetTableUserWrapper : Any> _foreignKey( toColumn: Column<RowId<TargetTableUserWrapper>, ColumnType.ROW_ID<TargetTableUserWrapper>, TargetTableUserWrapper>,
fromColumns: Array<Column<*, *, TableUserExtension>>, ): ForeignRowReference<TableUserExtension, TableUserExtension>
toTable: Table<TargetTableUserWrapper, *>,
toColumns: Array<Column<*, *, TargetTableUserWrapper>>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper>
@OptIn(LowLevelApi::class) public fun <TargetTableUserWrapper : Any> foreignRowReference(
public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>> foreignKey( fromColumn: Column<RowId<TargetTableUserWrapper>, ColumnType.ROW_ID<TargetTableUserWrapper>, TableUserExtension>,
fromColumn: Column<*, ColumnType1, TableUserExtension>,
toTable: Table<TargetTableUserWrapper, *>, toTable: Table<TargetTableUserWrapper, *>,
toColumn: Column<*, ColumnType1, TargetTableUserWrapper>, toColumn: Column<RowId<TargetTableUserWrapper>, ColumnType.ROW_ID<TargetTableUserWrapper>, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction, onDelete: ForeignRowReference.OnDeleteAction,
onDelete: ForeignKey.OnDeleteAction, ): ForeignRowReference<TableUserExtension, TargetTableUserWrapper>
): ForeignKey<TableUserExtension, TargetTableUserWrapper> = this._foreignKey(
fromColumns = arrayOf(fromColumn),
toTable = toTable,
toColumns = arrayOf(toColumn),
onUpdate = onUpdate,
onDelete = onDelete
)
@OptIn(LowLevelApi::class)
public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>, ColumnType2 : ColumnType<*>> foreignKey(
fromColumn1: Column<*, ColumnType1, TableUserExtension>,
fromColumn2: Column<*, ColumnType2, TableUserExtension>,
toTable: Table<TargetTableUserWrapper, *>,
toColumn1: Column<*, ColumnType1, TargetTableUserWrapper>,
toColumn2: Column<*, ColumnType2, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper> = this._foreignKey(
fromColumns = arrayOf(fromColumn1, fromColumn2),
toTable = toTable,
toColumns = arrayOf(toColumn1, toColumn2),
onUpdate = onUpdate,
onDelete = onDelete
)
@OptIn(LowLevelApi::class)
public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>, ColumnType2 : ColumnType<*>, ColumnType3 : ColumnType<*>> foreignKey(
fromColumn1: Column<*, ColumnType1, TableUserExtension>,
fromColumn2: Column<*, ColumnType2, TableUserExtension>,
fromColumn3: Column<*, ColumnType3, TableUserExtension>,
toTable: Table<TargetTableUserWrapper, *>,
toColumn1: Column<*, ColumnType1, TargetTableUserWrapper>,
toColumn2: Column<*, ColumnType2, TargetTableUserWrapper>,
toColumn3: Column<*, ColumnType3, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper> = this._foreignKey(
fromColumns = arrayOf(fromColumn1, fromColumn2, fromColumn3),
toTable = toTable,
toColumns = arrayOf(toColumn1, toColumn2, toColumn3),
onUpdate = onUpdate,
onDelete = onDelete
)
} }

View File

@ -30,31 +30,28 @@ public interface TableUpdater<TableNewUserExtension : Any, TableOldUserExtension
public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType>> changeDefaultValue(c: Column<RuntimeType, DatabaseType, TableNewUserExtension>, d: DefaultConstraint<*, *, TableOldUserExtension>): DefaultConstraint<RuntimeType, DatabaseType, TableNewUserExtension> public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType>> changeDefaultValue(c: Column<RuntimeType, DatabaseType, TableNewUserExtension>, d: DefaultConstraint<*, *, TableOldUserExtension>): DefaultConstraint<RuntimeType, DatabaseType, TableNewUserExtension>
public fun deleteDefaultValue(i: DefaultConstraint<*, *, TableOldUserExtension>) public fun deleteDefaultValue(i: DefaultConstraint<*, *, TableOldUserExtension>)
public fun <TargetTableOldUserWrapper : Any, TargetTableNewUserWrapper : Any> keepForeignKeyToUpdatedTable( public fun <TargetTableUserWrapper : Any> keepForeignRowReference(
fk: ForeignKey<TableOldUserExtension, TargetTableOldUserWrapper>, frr: ForeignRowReference<TableOldUserExtension, TargetTableUserWrapper>,
onDelete: ForeignRowReference.OnDeleteAction? = null
): ForeignRowReference<TableNewUserExtension, TargetTableUserWrapper>
public fun <TargetTableOldUserWrapper : Any, TargetTableNewUserWrapper : Any> keepForeignRowReferenceToUpdatedTable(
frr: ForeignRowReference<TableOldUserExtension, TargetTableOldUserWrapper>,
updatedTable: Table<TargetTableNewUserWrapper, TargetTableOldUserWrapper>, updatedTable: Table<TargetTableNewUserWrapper, TargetTableOldUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction? = null, onDelete: ForeignRowReference.OnDeleteAction? = null
onDelete: ForeignKey.OnDeleteAction? = null ): ForeignRowReference<TableNewUserExtension, TargetTableNewUserWrapper>
): ForeignKey<TableNewUserExtension, TargetTableNewUserWrapper>
public fun <TargetTableUserWrapper : Any> keepForeignKey( public fun <TargetTableUserWrapper : Any> renameAndKeepForeignRowReference(
fk: ForeignKey<TableOldUserExtension, TargetTableUserWrapper>, frr: ForeignRowReference<TableOldUserExtension, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction? = null, onDelete: ForeignRowReference.OnDeleteAction? = null
onDelete: ForeignKey.OnDeleteAction? = null ): ForeignRowReference<TableNewUserExtension, TargetTableUserWrapper>
): ForeignKey<TableNewUserExtension, TargetTableUserWrapper>
public fun <TargetTableOldUserWrapper : Any, TargetTableNewUserWrapper : Any> renameAndKeepForeignKeyToUpdatedTable(
fk: ForeignKey<TableOldUserExtension, TargetTableOldUserWrapper>, public fun <TargetTableOldUserWrapper : Any, TargetTableNewUserWrapper : Any> renameAndKeepForeignRowReferenceToUpdatedTable(
frr: ForeignRowReference<TableOldUserExtension, TargetTableOldUserWrapper>,
updatedTable: Table<TargetTableNewUserWrapper, TargetTableOldUserWrapper>, updatedTable: Table<TargetTableNewUserWrapper, TargetTableOldUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction? = null, onDelete: ForeignRowReference.OnDeleteAction? = null
onDelete: ForeignKey.OnDeleteAction? = null ): ForeignRowReference<TableNewUserExtension, TargetTableNewUserWrapper>
): ForeignKey<TableNewUserExtension, TargetTableNewUserWrapper>
public fun <TargetTableUserWrapper : Any> renameAndKeepForeignKey( public fun deleteForeignRowReference(frr: ForeignRowReference<TableOldUserExtension, *>)
fk: ForeignKey<TableOldUserExtension, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction? = null,
onDelete: ForeignKey.OnDeleteAction? = null
): ForeignKey<TableNewUserExtension, TargetTableUserWrapper>
public fun deleteForeignKey(fk: ForeignKey<TableOldUserExtension, *>)
} }