Skip to content

Commit

Permalink
feat: EXPOSED-654 Allow customizing the check constraint names of col…
Browse files Browse the repository at this point in the history
…umns with check constraints (#2340)
  • Loading branch information
joc-a authored Jan 7, 2025
1 parent 4f594d4 commit ffa3eef
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 21 deletions.
18 changes: 12 additions & 6 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,8 @@ public class org/jetbrains/exposed/sql/Table : org/jetbrains/exposed/sql/ColumnS
public final fun blob (Ljava/lang/String;Z)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun blob$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun bool (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun byte (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun byte (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun byte$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun char (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun char (Ljava/lang/String;ILjava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun char$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;ILjava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
Expand Down Expand Up @@ -2582,7 +2583,8 @@ public class org/jetbrains/exposed/sql/Table : org/jetbrains/exposed/sql/ColumnS
public static synthetic fun index$default (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/Column;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun index$default (Lorg/jetbrains/exposed/sql/Table;Z[Lorg/jetbrains/exposed/sql/Column;ILjava/lang/Object;)V
public fun innerJoin (Lorg/jetbrains/exposed/sql/ColumnSet;)Lorg/jetbrains/exposed/sql/Join;
public final fun integer (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun integer (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun integer$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public fun join (Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/JoinType;Lorg/jetbrains/exposed/sql/Expression;Lorg/jetbrains/exposed/sql/Expression;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Join;
public final fun largeText (Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun largeText$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
Expand Down Expand Up @@ -2618,23 +2620,27 @@ public class org/jetbrains/exposed/sql/Table : org/jetbrains/exposed/sql/ColumnS
public final fun registerCompositeColumn (Lorg/jetbrains/exposed/sql/CompositeColumn;)Lorg/jetbrains/exposed/sql/CompositeColumn;
public final fun replaceColumn (Lorg/jetbrains/exposed/sql/Column;Lorg/jetbrains/exposed/sql/Column;)Lorg/jetbrains/exposed/sql/Column;
public fun rightJoin (Lorg/jetbrains/exposed/sql/ColumnSet;)Lorg/jetbrains/exposed/sql/Join;
public final fun short (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun short (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun short$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun text (Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun text$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun transform (Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Column;
public final fun transform (Lorg/jetbrains/exposed/sql/Column;Lorg/jetbrains/exposed/sql/ColumnTransformer;)Lorg/jetbrains/exposed/sql/Column;
public final fun transformNullable (Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Column;
public final fun transformNullable (Lorg/jetbrains/exposed/sql/Column;Lorg/jetbrains/exposed/sql/ColumnTransformer;)Lorg/jetbrains/exposed/sql/Column;
public final fun ubyte (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun uinteger (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun ubyte (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun ubyte$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun uinteger (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun uinteger$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun ulong (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun uniqueIndex (Ljava/lang/String;[Lorg/jetbrains/exposed/sql/Column;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V
public final fun uniqueIndex (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun uniqueIndex ([Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun uniqueIndex$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;[Lorg/jetbrains/exposed/sql/Column;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun uniqueIndex$default (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/Column;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun uniqueIndex$default (Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public final fun ushort (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun ushort (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun ushort$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
public final fun uuid (Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public final fun varchar (Ljava/lang/String;ILjava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static synthetic fun varchar$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;ILjava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Column;
Expand Down
39 changes: 24 additions & 15 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt
Original file line number Diff line number Diff line change
Expand Up @@ -708,48 +708,57 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {

// Numeric columns

/** Creates a numeric column, with the specified [name], for storing 1-byte integers. */
fun byte(name: String): Column<Byte> = registerColumn(name, ByteColumnType()).apply {
check("${generatedSignedCheckPrefix}byte_${this.unquotedName()}") { it.between(Byte.MIN_VALUE, Byte.MAX_VALUE) }
/** Creates a numeric column, with the specified [name], for storing 1-byte integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*/
fun byte(name: String, checkConstraintName: String? = null): Column<Byte> = registerColumn(name, ByteColumnType()).apply {
check(checkConstraintName ?: "${generatedSignedCheckPrefix}byte_${this.unquotedName()}") { it.between(Byte.MIN_VALUE, Byte.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 1-byte unsigned integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*
* **Note:** If the database being used is not MySQL, MariaDB, or SQL Server, this column will use the
* database's 2-byte integer type with a check constraint that ensures storage of only values
* between 0 and [UByte.MAX_VALUE] inclusive.
*/
fun ubyte(name: String): Column<UByte> = registerColumn(name, UByteColumnType()).apply {
check("${generatedUnsignedCheckPrefix}byte_${this.unquotedName()}") { it.between(0u, UByte.MAX_VALUE) }
fun ubyte(name: String, checkConstraintName: String? = null): Column<UByte> = registerColumn(name, UByteColumnType()).apply {
check(checkConstraintName ?: "${generatedUnsignedCheckPrefix}byte_${this.unquotedName()}") { it.between(0u, UByte.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 2-byte integers. */
fun short(name: String): Column<Short> = registerColumn(name, ShortColumnType()).apply {
check("${generatedSignedCheckPrefix}short_${this.unquotedName()}") { it.between(Short.MIN_VALUE, Short.MAX_VALUE) }
/** Creates a numeric column, with the specified [name], for storing 2-byte integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*/
fun short(name: String, checkConstraintName: String? = null): Column<Short> = registerColumn(name, ShortColumnType()).apply {
check(checkConstraintName ?: "${generatedSignedCheckPrefix}short_${this.unquotedName()}") { it.between(Short.MIN_VALUE, Short.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 2-byte unsigned integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*
* **Note:** If the database being used is not MySQL or MariaDB, this column will use the database's 4-byte
* integer type with a check constraint that ensures storage of only values between 0 and [UShort.MAX_VALUE] inclusive.
*/
fun ushort(name: String): Column<UShort> = registerColumn(name, UShortColumnType()).apply {
check("$generatedUnsignedCheckPrefix${this.unquotedName()}") { it.between(0u, UShort.MAX_VALUE) }
fun ushort(name: String, checkConstraintName: String? = null): Column<UShort> = registerColumn(name, UShortColumnType()).apply {
check(checkConstraintName ?: "$generatedUnsignedCheckPrefix${this.unquotedName()}") { it.between(0u, UShort.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 4-byte integers. */
fun integer(name: String): Column<Int> = registerColumn(name, IntegerColumnType()).apply {
check("${generatedSignedCheckPrefix}integer_${this.unquotedName()}") { it.between(Int.MIN_VALUE, Int.MAX_VALUE) }
/** Creates a numeric column, with the specified [name], for storing 4-byte integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*/
fun integer(name: String, checkConstraintName: String? = null): Column<Int> = registerColumn(name, IntegerColumnType()).apply {
check(checkConstraintName ?: "${generatedSignedCheckPrefix}integer_${this.unquotedName()}") { it.between(Int.MIN_VALUE, Int.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 4-byte unsigned integers.
* An optional [checkConstraintName] can be passed to allow customizing the check constraint name when needed.
*
* **Note:** If the database being used is not MySQL or MariaDB, this column will use the database's
* 8-byte integer type with a check constraint that ensures storage of only values
* between 0 and [UInt.MAX_VALUE] inclusive.
*/
fun uinteger(name: String): Column<UInt> = registerColumn(name, UIntegerColumnType()).apply {
check("$generatedUnsignedCheckPrefix${this.unquotedName()}") { it.between(0u, UInt.MAX_VALUE) }
fun uinteger(name: String, checkConstraintName: String? = null): Column<UInt> = registerColumn(name, UIntegerColumnType()).apply {
check(checkConstraintName ?: "$generatedUnsignedCheckPrefix${this.unquotedName()}") { it.between(0u, UInt.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 8-byte integers. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,35 @@ class NumericColumnTypesTests : DatabaseTestsBase() {
)
}
}

@Test
fun testCustomCheckConstraintName() {
val tester = object : Table("tester") {
val byte = byte("byte_column", checkConstraintName = "custom_byte_check")
val ubyte = ubyte("ubyte_column", checkConstraintName = "custom_ubyte_check")
val short = short("short_column", checkConstraintName = "custom_short_check")
val ushort = ushort("ushort_column", checkConstraintName = "custom_ushort_check")
val integer = integer("integer_column", checkConstraintName = "custom_integer_check")
val uinteger = uinteger("uinteger_column", checkConstraintName = "custom_uinteger_check")
}

withTables(tester) {
assertEquals(
"CREATE TABLE ${addIfNotExistsIfSupported()}${tester.nameInDatabaseCase()} (" +
"${tester.byte.nameInDatabaseCase()} ${tester.byte.columnType} NOT NULL, " +
"${tester.ubyte.nameInDatabaseCase()} ${tester.ubyte.columnType} NOT NULL, " +
"${tester.short.nameInDatabaseCase()} ${tester.short.columnType} NOT NULL, " +
"${tester.ushort.nameInDatabaseCase()} ${tester.ushort.columnType} NOT NULL, " +
"${tester.integer.nameInDatabaseCase()} ${tester.integer.columnType} NOT NULL, " +
"${tester.uinteger.nameInDatabaseCase()} ${tester.uinteger.columnType} NOT NULL, " +
"CONSTRAINT custom_byte_check CHECK (${tester.byte.nameInDatabaseCase()} BETWEEN ${Byte.MIN_VALUE} AND ${Byte.MAX_VALUE}), " +
"CONSTRAINT custom_ubyte_check CHECK (${tester.ubyte.nameInDatabaseCase()} BETWEEN 0 AND ${UByte.MAX_VALUE}), " +
"CONSTRAINT custom_short_check CHECK (${tester.short.nameInDatabaseCase()} BETWEEN ${Short.MIN_VALUE} AND ${Short.MAX_VALUE}), " +
"CONSTRAINT custom_ushort_check CHECK (${tester.ushort.nameInDatabaseCase()} BETWEEN 0 AND ${UShort.MAX_VALUE}), " +
"CONSTRAINT custom_integer_check CHECK (${tester.integer.nameInDatabaseCase()} BETWEEN ${Int.MIN_VALUE} AND ${Int.MAX_VALUE}), " +
"CONSTRAINT custom_uinteger_check CHECK (${tester.uinteger.nameInDatabaseCase()} BETWEEN 0 AND ${UInt.MAX_VALUE}))",
tester.ddl
)
}
}
}

0 comments on commit ffa3eef

Please sign in to comment.