Breaking Changes
1.0.0-rc-4
If H2 version 2.4.240+ is detected,
datetime()column type will now map to typeTIMESTAMP(9)in the following modes: Regular, MySQL, and MariaDB. For earlier versions,datetime()continues to map to the originalDATETIME(9)type. This has been done to avoid thrown exceptions following stricter type changes enforced by this database version and should pose no issue with Exposed built-in schema migration methods, as these H2 modes were treating theDATETIMEtype as aTIMESTAMPtype.If
sqlite-jdbcdriver version 3.50.2.0+ is being used, there might be a change in the SQL statements generated by schema migration methods, or in the results of their associated schema validation methods. Statements that potentiallyDROPunmapped columns may now be generated bySchemaUtilsandMigrationUtilsmethods. This driver release includes changed boolean values of its metadata propertiessupportsAlterTableWithAddColumnandsupportsAlterTableWithDropColumn, which Exposed checks automatically. This means that schema migration methods may actually return any additional valid statements that are needed to align the database table with the Exposed table object, such asALTER TABLE ADD COLUMN,ALTER TABLE DROP COLUMN, andALTER TABLE RENAME COLUMN. Please consider checking the generated SQL list in this case before running.The field
Transaction.idwas renamed toTransaction.transactionIdto avoid collisions and shadowing with user's code.
1.0.0-rc-3
Removed APIs
TransactionManagerApi.bindTransactionToThread()- removed from interface and all implementationsThreadLocalTransactionManagerclass - fully removed (was already deprecated with error level)CoreTransactionManagerobject - replaced with top-level functionscurrentTransaction(),currentTransactionOrNull()TransactionManager.resetCurrent(manager)- removed from companion objectTransactionManager.isInitialized()- removed from companion objectExperimental suspended transaction functions with
CoroutineContextparameter - removed from JDBC module
Changed Method Signatures
transaction(),inTopLevelTransaction(),suspendTransaction(),inTopLevelSuspendTransaction()- isolation and readOnly parameters now nullable (Int?,Boolean?)Database.transactionManager- changed fromDatabase?.transactionManagertoDatabase.transactionManager(non-nullable receiver)R2dbcDatabase.transactionManager- changed fromR2dbcDatabase?.transactionManagertoR2dbcDatabase.transactionManager(non-nullable receiver)TransactionManager.newTransaction()- readOnly parameter changed fromBooleantoBoolean?
Changed Behavior
Transaction manager resolution: Now resolves from current transaction → current database instead of thread-local; throws
IllegalStateExceptionif unavailableTransactionManager.manager: Now throws if no transaction manager found (previously returnedNotInitializedTransactionManager)TransactionManager.defaultDatabase: Can now benull; useTransactionManager.primaryDatabasefor default-or-last-created behaviorTransaction context management: Internal architecture changed from thread-local to stack-based with coroutine context elements
1.0.0-rc-2
The
transaction(),inTopLevelTransaction(),suspendTransaction(), andinTopLevelSuspendTransaction()functions now havedbas the first parameter instead oftransactionIsolation, and thetransactionIsolationandreadOnlyparameters now have default values derived from the database's transaction manager configuration.R2dbcTransaction.globalInterceptorsproperty now stores a collection ofGlobalSuspendStatementInterceptorinstances. Any loadedGlobalStatementInterceptorimplementations are automatically wrapped to be compatible with the new interceptor type, so no changes need to be made to how any existing custom interceptors are declared in theresourcesfolder.
1.0.0-rc-1
exposed-migrationartifact has been replaced withexposed-migration-coreto hold core common schema migration functionality across both available drivers. New driver-specific artifacts have been added to support both JDBC and R2DBC, resulting in a need to adjust your dependency block:
This also means that the import path pattern of the dependencies have been updated accordingly:
See the migration guide for full details on migration dependencies.
The interface
ISqlExpressionBuilder(and all its methods) has been deprecated, along with its implementation objects,SqlExpressionBuilderandUpsertSqlExpressionBuilder. All methods previously restricted to this interface should now be replaced with their new equivalent top-level functions. This will require the addition of new import statements iforg.jetbrains.exposed.v1.core.*is not already present. This means that any higher-order function that used either of the objects as the receiver (or argument) have been changed to no longer rely on these objects. In such cases, expression builder methods in the function parameter blocks will now be unresolved unless the appropriate import is added. See the migration guide for full details onSqlExpressionBuilderimports and higher-order functions.We refactored the datetime modules by extracting common logic to the core module, where each datetime column type now extends a base class (e.g.,
JavaLocalDateColumnTypeextendsLocalDateColumnType,JavaLocalDateTimeColumnTypeextendsLocalDateTimeColumnType, etc.), split theDateColumnTypefromexposed-jodatimeintoJodaLocalDateColumnType(formerlytime: false) andJodaLocalDateTimeColumnType(formerlytime: true), and renamedLocalTimeColumnTypetoJodaLocalTimeColumnType. These changes would affect only those who use these classes directly for custom functions or custom column types. Creating columns via extension functions should not be affected.The common
exposed-coredatetime API mentioned above relies onkotlinx.datetimefeatures that are only compatible with kotlin-stdlib 2.1.20+. Attempting to build with a datetime module dependency using an older Kotlin version may lead toNoClassDefFoundErrorand will require bumping the Kotlin version.Levels of deprecated API have been bumped. See PR #2588 and Migration Guide for full details.
Parameter
supportsSelectForUpdatefromDatabaseDialectwas deprecated and should not be used. The parameter was moved toJdbcExposedDatabaseMetadata/R2dbcExposedDatabaseMetadataclasses. It could be used with a call toTransactionManager.current().db.supportsSelectForUpdatenow.R2dbcPreparedStatementApi.executeUpdate()no longer returns a value. It was previously defined as returning an integer of the affected row count, as per the JDBC variant, but it always returned a value of zero due to the nature of R2DBC result processing. If you wish to still retrieve the affected row count manually after callingexecuteUpdate()(and have no further need of the statement results after), this can be achieved by callingR2dbcPreparedStatementApi.getResultRow()?.rowsUpdated()?.singleOrNull().R2DBCRow, which is the R2DBC implementation ofRowApimeant to wrap elements of a statement's result, has been renamed toR2dbcRow.R2dbcTransactionInterface.connectionproperty has been replaced with a suspend function of the same name:
suspendTransaction()overloads that accepts aCoroutineContext?parameter have been deprecated in favor of overloads whose parameters and behavior are more inline with JDBCtransaction(). A manual context can be passed to the methods usingwithContext(), for example. Similarly,suspendTransactionAsync()that returnedDeferredhas also been deprecated in favor of callingasync()directly with a standardsuspendTransaction().The
R2dbcDatabase.connect()overload that accepts a Stringurlparameter has had the type of itsdatabaseConfigparameter changed to accept aR2dbcDatabaseConfig.Builderargument directly. This is instead of a function parameter with the builder as its receiver, which brings it more inline with the corresponding JDBCDatabase.connect()variant:
1.0.0-beta-5
Migration of kotlinx-datetime from version 6 to version 7. The only package affected is
exposed-kotlin-datetime.KotlinInstantColumnType, andTable.timestamp(name: String)are parametrized withkotlin.time.Instantclass now. If you need to usekotlinx.datetime.Instantwith Exposed, you have to replace usages ofKotlinInstantColumnTypeandTable.timestamp(name: String)withXKotlinInstantColumnTypeandTable.xTimestamp(name: String)respectively, also theCurrentTimestampconstant should be changed withXCurrentTimestamp,CustomTimeStampFunctionwithXCustomTimeStampFunction.The newly introduced
IStatementBuilderinterface has been renamed and deprecated in favor ofStatementBuilder, which contains all the original and unchanged methods. It's associated functionbuildStatement()no longer accepts the deprecated interface as the receiver of itsbodyparameter; the parameter expects the newStatementBuilderinstead. The same parameter type change applies to the functionexplain().Support for H2 versions earlier than 2.0.202 (namely 1.4.200 and earlier) has now been fully phased out. In addition,
H2Dialect.H2MajorVersion.Oneis now deprecated andH2Dialect-specific properties, likemajorVersionandisSecondVersion, now throw an exception if H2 version 1.x.x is detected. Moving forward, new features will no longer be tested on H2 version 1.0.0+, so support for those versions will not be guaranteed. Depending on the built-in support from these older H2 versions, Exposed API may still mostly be compatible, but may now throw syntax or unsupported exceptions when generating certain SQL clauses.Casewas split intoCase()andValueCase()to representcase when <condition> then <result> endandcase <value0> when <value1> then <result> endrespectively. Thevalueparameter from theCaseclass was removed, so if it was used directly withvalueit should be replaced with eithercase(value)orValueCase(value). ClassesCaseWhenandCaseWhenElsealso were changed, both of them extendBaseCaseWhenclass now, and could be used as expression (CaseWhenwas not extendingExpressionbefore). AlsoCaseWhenElseexpect a list of cases in primary constructor instead of instance ofCaseWhen.
1.0.0-beta-4
ThreadLocalMaphas been restricted to internal use, based on its current limited usage in already internal classes. It, along withMappedTransactionContext, has been moved into the subpackage:org.jetbrains.exposed.v1.r2dbc.transactions.mtc.addLogger()has been converted into aTransactionmethod (instead of an extension method ofJdbcTransactionandR2dbcTransaction), so its logic can remain common withinexposed-core. Any explicit imports, likeimport org.jetbrains.exposed.v1.jdbc.addLogger, will no longer compile and should be removed.
1.0.0-beta-3
exposed-coreinterfacePreparedStatementApihas a newset()method that will require an override if implemented. This method accepts a third argument for the column type associated with the value being bound to the statement, and is meant to replace the existingoperator fun set(index: Int, value: Any), which is now deprecated.exposed-coreinterfacePreparedStatementApihas a newsetArray()method that will require an override if implemented. This method accepts the actualArrayColumnTypeassociated with the array value being bound to the statement as the second argument, instead of a string representation of the type. It is intended to replace the existingsetArray(index: Int, type: String, array: Array<*>), which is now deprecated.Classes
BatchInsertStatementandBaseBatchInsertStatementwere joined into one open classBatchInsertStatement. The usages ofBaseBatchInsertStatementcould be safely replaced withBatchInsertStatement.The
typeparameter in theTypeMapper::getValue()method is now optional. The method signature has been updated tofun <T> getValue(row: Row, type: Class<T>?, ...): ValueContainer<T?>.
1.0.0-beta-1
The 1.0.0-beta-1 release introduces support for R2DBC and includes breaking changes to import paths.
On the way to Exposed 1.0, several changes were made to package names. There are two key changes in package naming: unique prefixes for every module and artifact, and adding a v1 prefix to all packages.
With the unique prefix on every module, it would be easier to differentiate which dependency a particular class, function, or other element comes from. This becomes more important as the number of packages grows larger.
The unique v1 prefix for the whole version will help users who have transient dependencies to the 0.x version of Exposed. It's expected that every major release could change that prefix.
Updated JDBC imports
Imports of the exposed-jdbc package previously under org.jetbrains.exposed.sql.* are now located under org.jetbrains.exposed.v1.jdbc.*. The table below shows example changes:
0.61.0 | 1.0.0-beta-1 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Updated core imports
Imports of the exposed-core package previously under org.jetbrains.exposed.sql.* are now located under org.jetbrains.exposed.v1.core.*. The table below shows example changes:
0.61.0 | 1.0.0-beta-1 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Updated DAO imports
Classes related to entity IDs, such as EntityID, CompositeEntityID, and other ID-related types, are now located in the org.jetbrains.exposed.v1.core.dao.id package.
The rest of the DAO types retain their original structure, but their imports now include the v1 namespace:
0.61.0 | 1.0.0-beta-1 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0.60.0
In H2, the
timestamp()column now maps to data typeTIMESTAMP(9)instead ofDATETIME(9).The names of the CHECK constraints created for the
ushort()anduinteger()columns have been modified for consistency. Check this pull request for details regarding this change.
0.59.0
[PostgreSQL]
MigrationUtils.statementsRequiredForDatabaseMigration(*tables)used to potentially returnDROPstatements for any database sequence not mapped to an Exposed table object. Now it only checks against database sequences that have a relational dependency on any of the specified tables (for example, any sequence automatically associated with aSERIALcolumn registered toIdTable). An unbound sequence created manually via theCREATE SEQUENCEcommand will no longer be checked and will not generate aDROPstatement.In H2 Oracle, the
long()column now maps to data typeBIGINTinstead ofNUMBER(19). In Oracle, using the long column in a table now also creates a CHECK constraint to ensure that no out-of-range values are inserted. Exposed does not ensure this behaviour for SQLite. If you want to do that, please use the following CHECK constraint:
In MariaDB, the
timestamp()column now maps to data typeTIMESTAMPinstead ofDATETIME.
0.57.0
Insert, Upsert, and Replace statements will no longer implicitly send all default values (except for client-side default values) in every SQL request. This change will reduce the amount of data Exposed sends to the database and make Exposed rely more on the database's default values. However, this may uncover previously hidden issues related to actual database default values, which were masked by Exposed's insert/upsert statements. Also from
InsertStatementwas removed protected methodisColumnValuePreferredFromResultSet()and methodvaluesAndDefaults()was marked as deprecated.Let's say you have a table with columns that have default values, and you use an insert statement like this:
object TestTable : IntIdTable("test") { val number = integer("number").default(100) val expression = integer("exp") .defaultExpression(intLiteral(100) + intLiteral(200)) } TestTable.insert { }This insert statement would generate the following SQL in the H2 database:
-- For versions before 0.57.0 INSERT INTO TEST ("number", "exp") VALUES (100, (100 + 200)) -- Starting from version 0.57.0 INSERT INTO TEST DEFAULT VALUESThe
OptionalReferrersclass is now deprecated as it is a complete duplicate of theReferrersclass; therefore, the latter should be used instead.
0.56.0
If the
distinctparameter ofgroupConcat()is set totrue, when using Oracle or SQL Server, this will now fail early with anUnsupportedByDialectException. Previously, the setting would be ignored and SQL function generation would not include aDISTINCTclause.In Oracle and H2 Oracle, the
ubyte()column now maps to data typeNUMBER(3)instead ofNUMBER(4).In Oracle and H2 Oracle, the
ushort()column now maps to data typeNUMBER(5)instead ofNUMBER(6).In Oracle and H2 Oracle, the
uinteger()column now maps to data typeNUMBER(10)instead ofNUMBER(13).In Oracle and H2 Oracle, the
integer()column now maps to data typeNUMBER(10)andINTEGERrespectively, instead ofNUMBER(12). In Oracle and SQLite, using the integer column in a table now also creates a CHECK constraint to ensure that no out-of-range values are inserted.ArrayColumnTypenow supports multidimensional arrays and includes an additional generic parameter. If it was previously used for one-dimensional arrays with the parameterTlikeArrayColumnType<T>, it should now be defined asArrayColumnType<T, List<T>>. For instance,ArrayColumnType<Int>should now beArrayColumnType<Int, List<Int>>.EntityIDandCompositeIDno longer implementComparablethemselves, to allow their wrapped identity values to be of a type that is not necessarilyComparable, likekotlin.uuid.Uuid.Any use of an entity's
idwith Kotlin comparison operators orcompareTo()will now require that the wrapped value be used directly:entity1.id < entity2.idwill need to becomeentity1.id.value < entity2.id.value. Any use of an entity'sidwith an Exposed function that is also type restricted toComparable(for example,avg()) will also require defining a new function. In this event, please also leave a comment on YouTrack with a use case so the original function signature can be potentially reassessed.
0.55.0
The
DeleteStatementpropertytableis now deprecated in favor oftargetsSet, which holds aColumnSetthat may be aTableorJoin. This enables the use of the newJoin.delete()function, which performs a delete operation on a specific table from the join relation. The original statement class constructor has also been deprecated in favor of the constructor that acceptstargetsSet, as well as another additional parametertargetTables(for specifying which table from the join relation, if applicable, to delete from).The
DeleteStatementpropertyoffsetwas not being used and is now deprecated, as are the extension functions that have anoffsetparameter.deleteWhere()anddeleteIgnoreWhere(), as well as the original statement class constructor, no longer accept an argument foroffset.SizedIterable.limit(n, offset)is now deprecated in favor of 2 independent methods,limit()andoffset(). In supporting databases, this allows the generation of an OFFSET clause in the SELECT statement without any LIMIT clause. Any custom implementations of theSizedIterableinterface with alimit()override will now show a warning that the declaration overrides a deprecated member. This override should be split into an implementation of the 2 new members instead.The original
FunctionProvider.queryLimit()is also being deprecated in favor ofqueryLimitAndOffset(), which takes a nullablesizeparameter to allow exclusion of the LIMIT clause. This latter deprecation only affects extensions of theFunctionProviderclass when creating a customVendorDialectclass.In Oracle, the
shortcolumn now maps to data typeNUMBER(5)instead ofSMALLINTbecauseSMALLINTis stored asNUMBER(38)in the database and takes up unnecessary storage. In Oracle and SQLite, using theshortcolumn in a table now also creates a check constraint to ensure that no out-of-range values are inserted.In Oracle, the
bytecolumn now maps to data typeNUMBER(3)instead ofSMALLINTbecauseSMALLINTis stored asNUMBER(38)in the database and takes up unnecessary storage. In SQL Server, thebytecolumn now maps to data typeSMALLINTinstead ofTINYINTbecauseTINYINTallows values from 0 to 255. In SQL Server, SQLite, Oracle, PostgreSQL, and H2 PostgreSQL, using thebytecolumn in a table now also creates a check constraint to ensure that no out-of-range values are inserted.The transformation of a nullable column (
Column<Unwrapped?>.transform()) requires handling null values. This enables conversions fromnullto a non-nullable value, and vice versa.In H2 the definition of json column with default value changed from
myColumn JSON DEFAULT '{"key": "value"}'tomyColumn JSON DEFAULT JSON '{"key": "value"}'
0.54.0
All objects that are part of the sealed class
ForUpdateOptionare now converted todata object.The
onUpdateparameter inupsert(),upsertReturning(), andbatchUpsert()will no longer accept a list of column-value pairs as an argument. The parameter now takes a lambda block with anUpdateStatementas its argument, so that column-value assignments for the UPDATE clause can be set in a similar way toupdate(). This enables the use ofinsertValue(column)in expressions to specify that the same value to be inserted into a column should be used when updating.
The function
statementsRequiredForDatabaseMigrationhas been moved fromSchemaUtilstoMigrationUtilsin theexposed-migrationmodule.A nested transaction (with
useNestedTransactions = true) that throws any exception will now rollback any commits since the last savepoint. This ensures that the nested transaction is properly configured to act in the exact same way as a top-level transaction orinTopLevelTransaction().An inner transaction (with
useNestedTransactions = false) that throws any exception will also rollback any commits since the last savepoint. This ensures that any exception propagated from the inner transaction to the outer transaction will not be swallowed if caught by some exception handler wrapping the inner transaction, and any inner commits will not be saved. In version 0.55.0, this change will be reduced so that only inner transactions that throw anSQLExceptionfrom the database will trigger such a rollback.
0.53.0
DAO Entity Transformation Changes
Parameter Renaming:
transform()andmemoizedTransform()now usewrapandunwrapinstead oftoColumnandtoReal.// Old: var name by EmployeeTable.name.transform(toColumn = { it.uppercase() }, toReal = { it.lowercase() }) // New: var name by EmployeeTable.name.transform(wrap = { it.uppercase() }, unwrap = { it.lowercase() })Class Renaming:
ColumnWithTransformis nowEntityFieldWithTransform, consolidating properties into a singletransformer.EntityFieldWithTransform(column, object : ColumnTransformer<String, Int> { override fun unwrap(value: Int): String = value.toString() override fun wrap(value: String): Int = value.toInt() })Entity transformation via DAO is deprecated and should be replaced with DSL transformation.
val tester = object : Table() { val value = integer("value") .transform(wrap = { ... }, unwrap = { ... }) }
0.51.0
The
exposed-spring-boot-startermodule no longer provides the entire spring-boot-starter-data-jdbc module. It now provides just the spring-boot-starter-jdbc. If there was a reliance on this transitive dependency, please directly include a dependency on Spring Data JDBC in your build files.ulongcolumn type is now NUMERIC(20) instead of BIGINT for H2 (excluding H2_PSQL), SQLite, and SQL Server to allow storing the full range ofULong, includingULong.MAX_VALUE.
0.50.0
The
Transactionclass propertyrepetitionAttemptsis being deprecated in favor ofmaxAttempts. Additionally, the propertyminRepetitionDelayshould be replaced withminRetryDelay, andmaxRepetitionDelaywithmaxRetryDelay. These changes also affect the default variants of these properties inDatabaseConfig.The property
maxAttemptsrepresents the maximum amount of attempts to perform a transaction block. Setting it, or the now deprecatedrepetitionAttempts, to a value less than 1 now throws anIllegalArgumentException.IColumnTypeandColumnTypenow expect a type argument.IColumnType.valueFromDB()also no longer has a default implementation, so an override for this method must be provided in any custom column type implementation. Check this pull request for details regarding this change.
0.49.0
For SQLite database, Exposed now requires bumping the SQLite JDBC driver version to a minimum of 3.45.0.0.
0.48.0
In
nonNullValueToStringforKotlinInstantColumnTypeandJavaDateColumnType, the formatted String for MySQL did not match the format received from the metadata whenisFractionDateTimeSupportedis true, so a new formatter specific to that is now used.In
nonNullValueToStringforKotlinLocalDateTimeColumnType, the formatted String for MySQL did not match the format received from the metadata whenisFractionDateTimeSupportedis true, so a new formatter specific to MySQL is now used.In
nonNullValueToStringforDateColumnType,JavaLocalDateTimeColumnType,JavaLocalTimeColumnType,JavaInstantColumnType,KotlinLocalDateTimeColumnType,KotlinLocalTimeColumnType, andKotlinInstantColumnType, the correct formatter for MySQL is used when the version (below 5.6) does not support fractional seconds.In
nonNullValueToStringforDateColumnTypeandDateTimeWithTimeZoneColumnType, the formatters used are changed to reflect the fact that Joda-Time stores date/time values only down to the millisecond (up to SSS and not SSSSSS).Functions
anyFrom(array)andallFrom(array)now useArrayColumnTypeto process the provided array argument when query building.ArrayColumnTyperequires a base column type to process contents correctly, and Exposed attempts to resolve the best match internally based on the array content type. A specific column type argument should be provided to the function parameterdelegateTypeif the content requires either an unsupported or custom column type, or a column type not defined in theexposed-coremodule.exposed-cryptmodule now uses Spring Security Crypto 6.+, which requires Java 17 as a minimum version.
0.47.0
The function
SchemaUtils.checkExcessiveIndicesis used to check both excessive indices and excessive foreign key constraints. It now has a different behavior and deals with excessive indices only. Also, its return type is nowList<Index>instead ofUnit. A new function,SchemaUtils.checkExcessiveForeignKeyConstraints, deals with excessive foreign key constraints and has a return typeList<ForeignKeyConstraint>.
0.46.0
When an Exposed table object is created with a keyword identifier (a table or column name) it now retains the exact case used before being automatically quoted in generated SQL. This primarily affects H2 and Oracle, both of which support folding identifiers to uppercase, and PostgresSQL, which folds identifiers to a lower case.
If
preserveKeywordCasing = truehad been previously set inDatabaseConfigto remove logged warnings about any keyword identifiers, this can now be removed as the property istrueby default.To temporarily opt out of this behavior and to not keep the defined casing of keyword identifiers, please set
preserveKeywordCasing = falseinDatabaseConfig:
0.44.0
SpringTransactionManagerno longer extendsDataSourceTransactionManager; instead, it directly extendsAbstractPlatformTransactionManagerwhile retaining the previous basic functionality. The class also no longer implements the Exposed interfaceTransactionManager, as transaction operations are instead delegated to Spring. These changes ensure that Exposed's underlying transaction management no longer interferes with the expected behavior of Spring's transaction management, for example, when using nested transactions or with@Transactionalelements likepropagationorisolation.If integration still requires a
DataSourceTransactionManager, please add two bean declarations to the configuration: one forSpringTransactionManagerand one forDataSourceTransactionManager. Then define a composite transaction manager that combines these two managers.If
TransactionManagerfunctions were being invoked by aSpringTransactionManagerinstance, please replace these calls with the appropriate Spring annotation or, if necessary, by using the companion object ofTransactionManagerdirectly (for example,TransactionManager.currentOrNull()).spring-transactionandexposed-spring-boot-startermodules now use Spring Framework 6.0 and Spring Boot 3.0, which require Java 17 as a minimum version.A table that is created with a keyword identifier (a table or column name) now logs a warning that the identifier's case may be lost when it is automatically quoted in generated SQL. This primarily affects H2 and Oracle, both of which support folding identifiers to uppercase, and PostgreSQL, which folds identifiers to a lower case.
To remove these warnings and to ensure that the keyword identifier sent to the database matches the exact case used in the Exposed table object, please set
preserveKeywordCasing = trueinDatabaseConfig:
0.43.0
In all databases except MySQL, MariaDB, and SQL Server, the
ubyte()column now maps to data typeSMALLINTinstead ofTINYINT, which allows the full range ofUBytevalues to be inserted without any overflow. Registering the column on a table also creates a check constraint that restricts inserted data to the range between 0 andUByte.MAX_VALUE. If a column that only uses 1 byte of storage is needed, but without allowing any non-negative values to be inserted, please use a signedbyte()column instead with a manually created check constraint:
In all databases except MySQL and MariaDB, the
uint()column now maps to data typeBIGINTinstead ofINT, which allows the full range ofUIntvalues to be inserted without any overflow. Registering the column on a table also creates a check constraint that restricts inserted data to the range between 0 andUInt.MAX_VALUE. If a column that only uses 4 bytes of storage is needed, but without allowing any non-negative values to be inserted, please use a signedinteger()column instead with a manually created check constraint:
0.42.0
SQLite The table column created using
date()now uses TEXT datatype instead of DATE (which the database mapped internally to NUMERIC type). This applies to the specificDateColumnTypein all 3 date/time modules and meansLocalDatecomparisons can now be done directly without conversions.H2, PostgreSQL Using
replace()now throws an exception as the REPLACE command is not supported by these databases. Ifreplace()was being used to perform an insert or update operation, all usages should instead be switched toupsert(). See documentation for UPSERT detailsOperator classes
existsandnotExistshave been renamed toExistsandNotExists. The functionsexists()andnotExists()have been introduced to return an instance of their respectively-named classes and to avoid unresolved reference issues. Any usages of these classes should be renamed to their capitalized forms.customEnumeration()now registers aCustomEnumerationColumnTypeto allow referencing by another column. The signature ofcustomEnumeration()has not changed and table columns initialized using it are still of typeColumn<DataClass>.Transaction.suspendedTransaction()has been renamed toTransaction.withSuspendTransaction(). Please runEdit -> Find -> Replace in files...twice withsuspendedTransaction(andsuspendedTransactionas the search options, to ensure that both variants are replaced without affectingsuspendedTransactionAsync()(if used in code).The
repetitionAttemptsparameter intransaction()has been removed and replaced with a mutable property in theTransactionclass. Please remove any arguments for this parameter and assign values to the property directly:
In all databases except MySQL and MariaDB, the
ushort()column now maps to data typeINTinstead ofSMALLINT, which allows the full range ofUShortvalues to be inserted without any overflow. Registering the column on a table also creates a check constraint that restricts inserted data to the range between 0 andUShort.MAX_VALUE. If a column that only uses 2 bytes of storage is needed, but without allowing any non-negative values to be inserted, please use a signedshort()column instead with a manually created check constraint: