androidkotlinsqliteandroid-room

Room Database Migration didn't properly handle : Caused by: java.lang.IllegalStateException:


Caused by: java.lang.IllegalStateException: Migration didn't properly handle: Expected TableInfo{name='project', columns={venueName=Column{name='venueName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nfcMerchantId=Column{name='nfcMerchantId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nfcPrivateKey=Column{name='nfcPrivateKey', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, endDate=Column{name='endDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, scheduledAnonymisationDate=Column{name='scheduledAnonymisationDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nfcProfileId=Column{name='nfcProfileId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, timeZone=Column{name='timeZone', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, uuid=Column{name='uuid', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, nfcCollectorId=Column{name='nfcCollectorId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, startDate=Column{name='startDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[Index{name='index_project_uuid', unique=false, columns=[uuid], orders=[ASC]}]}

Found TableInfo{name='project', columns={venueName=Column{name='venueName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, endDate=Column{name='endDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, scheduledAnonymisationDate=Column{name='scheduledAnonymisationDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nfcProfileId=Column{name='nfcProfileId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, timeZone=Column{name='timeZone', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, uuid=Column{name='uuid', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, startDate=Column{name='startDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[Index{name='index_project_uuid', unique=false, columns=[uuid], orders=[ASC]}]}

I have upgraded my app on top of the previous version and I got this error when I open the new upgraded version of my app. I have added migration class and added the newly added fields and also I have increased the database version. This is my entity class.

@Entity(
    tableName = "project",
    indices = [Index("uuid")]
)
data class ProjectEntity(
    @PrimaryKey
    val id: String,
    val uuid: String,
    val name: String,
    val startDate: String?,
    val endDate: String?,
    val venueName: String?,
    val timeZone: String?,
    val scheduledAnonymisationDate: String?,
    val nfcCollectorId: String?,
    val nfcMerchantId: String?,
    val nfcPrivateKey: String?,
    val nfcProfileId: String?
)

This is my database class.

@Database(entities = {ProjectEntity.class}, version = 23)
public abstract class RoomDatabaseImpl extends RoomDatabase {
    abstract fun projectDao(): ProjectDao
}

This is my migration class.

internal object Migration18To19 : Migration(18, 19) {
  override fun migrate(database: SupportSQLiteDatabase) {
    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcCollectorId` TEXT")
    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcMerchantId` TEXT")
    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcPrivateKey` TEXT")
    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcProfileId` TEXT")
  }
}

and my current database version is 23.

I have also made few other changes in the other tables and added migration class for all that and incremented the database version accordingly. My current latest migration class is Migration22To23 and version is 23. I am not really sure why I am getting this error. I have also tried debugging logs and got the below details.

45 {
 type=table
 name=project
 tbl_name=project
 rootpage=49
 sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, `nfcCollectorId` TEXT, `nfcMerchantId` TEXT, `nfcPrivateKey` TEXT, `nfcProfileId` TEXT, PRIMARY KEY(`id`))
 }
46 {
 type=index
 name=sqlite_autoindex_project_1
 tbl_name=project
 rootpage=50
 sql=null
 }
47 {
 type=index
 name=index_project_uuid
 tbl_name=project
 rootpage=52
 sql=CREATE INDEX `index_project_uuid` ON `project` (`uuid`)
 }

It seems all the columns are added in 46 migration. But I am not sure why it is not working. I have also found one more information. We initially made nfcCollectorId,nfcMerchantId,nfcPrivateKey,nfcProfileId as not nullable and in between we have changed that as nullable in ProjectEntity. I am not sure that is causing the issue.


Solution

  • Considering that you have picked one Migration (18-19) from many and that that Migration should not be relevant as the version is supposedly moving from 22-23.

    There could be numerous causes.

    Certainly from the evidence, that:-

    are Expected but not Found, it would be the 18-19 Migration that is required. However, 18-19 would fail as the nfcProfileId column has been found unless there is a Migration that Drops the column.

    Could someone help me to solve this issue?

    Perhaps the following could be of use

    You need to get some understanding of what is going on, from what version to what version and whether or not all migrations are being processed and what is changing when those migrations are invoked.

    I would suggest considering the following code that enables such debugging information to be extracted (to replace/amend RoomDatabaseImpl):-

    const val DB_VERSION = 3 /* being a constant allows the value to be used e.g. in preOpenSchemaDump */
    const val DB_NAME = "room_database_impl.db" /* similar */
    const val TAG="DBINFO" /* tag so all debug messages (bar schema dumps) can be easily located */
    @Database(entities = [ProjectEntity::class], version = DB_VERSION)
    abstract class RoomDatabaseImpl: RoomDatabase() {
        abstract fun projectDao(): ProjectDao
    
        companion object {
            private var instance: RoomDatabaseImpl?=null
            fun getInstance(context: Context): RoomDatabaseImpl {
                if (instance==null) {
                    preOpenSchemaDump(context)
                    instance= Room.databaseBuilder(context,RoomDatabaseImpl::class.java, DB_NAME)
                        .allowMainThreadQueries() /* For brevity */
                        .addCallback(CB) /* added for debugging */
                        .addMigrations(Migration1To2,Migration2To3)
                        .build()
                }
                return instance as RoomDatabaseImpl
            }
    
            fun preOpenSchemaDump(context: Context) {
                if (context.getDatabasePath(DB_NAME).exists()) {
                    val db = SQLiteDatabase.openDatabase(
                        context.getDatabasePath(DB_NAME).path,
                        null,
                        SQLiteDatabase.OPEN_READWRITE
                    )
                    Log.d(TAG,"Database Version is ${db.version}: Room version will be ${DB_VERSION}" )
                    dumpSchema("PreOpen invoked", db)
                    db.close()
                } else {
                    Log.d(TAG,"PreOpen Invoked but Database does not exist yet (nothing to dump so skipped)")
                }
            }
    
            internal object Migration2To3 : Migration(2, 3) {
                override fun migrate(database: SupportSQLiteDatabase) {
                    dumpSchema("Before Migration 2 to 3 invoked", database)
                    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcCollectorId` TEXT")
                    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcMerchantId` TEXT")
                    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcPrivateKey` TEXT")
                    //database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcProfileId` TEXT") /* commented out as would fail */
                    dumpSchema("Post Migration 2 to 3 invoked", database)
                }
            }
    
            internal object Migration1To2 : Migration(1, 2) {
                override fun migrate(database: SupportSQLiteDatabase) {
                    dumpSchema("Before Migration 1 to 2 invoked", database)
                    database.execSQL("ALTER TABLE `project` ADD COLUMN `nfcProfileId` TEXT")
                    dumpSchema("Post Migration 1 to 2 invoked", database)
                }
            }
            /* CallBack for logging purposes */
            internal object CB: Callback() {
                override fun onCreate(db: SupportSQLiteDatabase) {
                    super.onCreate(db)
                    dumpSchema("OnCreate Callback initiated",db)
                }
    
                override fun onOpen(db: SupportSQLiteDatabase) {
                    super.onOpen(db)
                    dumpSchema("OnOpen Callback initiated",db)
                }
    
                override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
                    super.onDestructiveMigration(db)
                    dumpSchema("OnDestructiveMigration Callback initiated",db)
                }
            }
            private fun dumpSchema(reason: String, db: SupportSQLiteDatabase, suppressDump: Boolean=false) {
                Log.d(TAG,"$reason - dumping schema to log:-")
                if (!suppressDump) {
                    val csr = db.query("SELECT * FROM sqlite_master")
                    DatabaseUtils.dumpCursor(csr)
                    csr.close()
                }
            }
            private fun dumpSchema(reason: String, db: SQLiteDatabase, suppressDump: Boolean=false) {
                Log.d(TAG,"$reason - dumping schema to log:-")
                if (!suppressDump) {
                    val csr = db.rawQuery("SELECT * FROM sqlite_master", null)
                    DatabaseUtils.dumpCursor(csr)
                    csr.close()
                }
            }
        }
    

    As an example.

    Initially DB_VERSION is 1 and all the nfc.... columns have been commented out and a fresh install is performed. The log includes:-

    2024-04-24 14:12:16.466 D/DBINFO: PreOpen Invoked but Database does not exist yet (nothing to dump so skipped)
    2024-04-24 14:12:16.533 D/DBINFO: OnCreate Callback initiated - dumping schema to log:-
    2024-04-24 14:12:16.533 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@68ac7e0
    2024-04-24 14:12:16.534 I/System.out: 0 {
    2024-04-24 14:12:16.534 I/System.out:    type=table
    2024-04-24 14:12:16.534 I/System.out:    name=android_metadata
    2024-04-24 14:12:16.534 I/System.out:    tbl_name=android_metadata
    2024-04-24 14:12:16.534 I/System.out:    rootpage=3
    2024-04-24 14:12:16.534 I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
    2024-04-24 14:12:16.534 I/System.out: }
    2024-04-24 14:12:16.534 I/System.out: 1 {
    2024-04-24 14:12:16.534 I/System.out:    type=table
    2024-04-24 14:12:16.534 I/System.out:    name=project
    2024-04-24 14:12:16.534 I/System.out:    tbl_name=project
    2024-04-24 14:12:16.534 I/System.out:    rootpage=4
    2024-04-24 14:12:16.534 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, PRIMARY KEY(`id`))
    2024-04-24 14:12:16.535 I/System.out: }
    ....
    2024-04-24 14:12:16.544 D/DBINFO: OnOpen Callback initiated - dumping schema to log:-
    2024-04-24 14:12:16.547 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@a4bf93f
    ....
    

    Then the nfc columns are uncommented and DB_VERSION set to 3 and the App rerun, the log then includes:-

    2024-04-24 14:18:13.256 D/DBINFO: Database Version is 1: Room version will be 3
    2024-04-24 14:18:13.256 D/DBINFO: PreOpen invoked - dumping schema to log:-
    2024-04-24 14:18:13.257 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@aa6612
    ....
    2024-04-24 14:18:13.258 I/System.out: 1 {
    2024-04-24 14:18:13.258 I/System.out:    type=table
    2024-04-24 14:18:13.258 I/System.out:    name=project
    2024-04-24 14:18:13.258 I/System.out:    tbl_name=project
    2024-04-24 14:18:13.258 I/System.out:    rootpage=4
    2024-04-24 14:18:13.258 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:18:13.322 D/DBINFO: Before Migration 1 to 2 invoked - dumping schema to log:-
    2024-04-24 14:18:13.323 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@a4bf93f
    ....
    2024-04-24 14:18:13.323 I/System.out: 1 {
    2024-04-24 14:18:13.323 I/System.out:    type=table
    2024-04-24 14:18:13.323 I/System.out:    name=project
    2024-04-24 14:18:13.323 I/System.out:    tbl_name=project
    2024-04-24 14:18:13.323 I/System.out:    rootpage=4
    2024-04-24 14:18:13.323 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:18:13.334 D/DBINFO: Post Migration 2 to 3 invoked - dumping schema to log:-
    
    2024-04-24 14:18:13.330 D/DBINFO: Before Migration 2 to 3 invoked - dumping schema to log:-
    2024-04-24 14:18:13.330 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8d33755
    ....
    2024-04-24 14:18:13.331 I/System.out: 1 {
    2024-04-24 14:18:13.331 I/System.out:    type=table
    2024-04-24 14:18:13.331 I/System.out:    name=project
    2024-04-24 14:18:13.331 I/System.out:    tbl_name=project
    2024-04-24 14:18:13.331 I/System.out:    rootpage=4
    2024-04-24 14:18:13.331 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, `nfcProfileId` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:18:13.334 D/DBINFO: Post Migration 2 to 3 invoked - dumping schema to log:-
    2024-04-24 14:18:13.334 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@d88a56a
    ....
    2024-04-24 14:18:13.335 I/System.out: 1 {
    2024-04-24 14:18:13.335 I/System.out:    type=table
    2024-04-24 14:18:13.335 I/System.out:    name=project
    2024-04-24 14:18:13.336 I/System.out:    tbl_name=project
    2024-04-24 14:18:13.336 I/System.out:    rootpage=4
    2024-04-24 14:18:13.336 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, `nfcProfileId` TEXT, `nfcCollectorId` TEXT, `nfcMerchantId` TEXT, `nfcPrivateKey` TEXT, PRIMARY KEY(`id`))
    

    Now if a deliberate issue is introduced (in 1-2) e.g.

    database.execSQL("ALTER TABLE project ADD COLUMN nfcOOOPS TEXT")

    And then version 1 is installed followed by version 3 as done previously then

    But 3 gets the Expected not Found but not until after both migrations as per the following extracts from the log:-

    2024-04-24 14:34:12.289 D/DBINFO: Database Version is 1: Room version will be 3
    2024-04-24 14:34:12.289 D/DBINFO: PreOpen invoked - dumping schema to log:-
    2024-04-24 14:34:12.289 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@aa6612
    ....
    2024-04-24 14:34:12.290 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:34:12.348 D/DBINFO: Before Migration 1 to 2 invoked - dumping schema to log:-
    2024-04-24 14:34:12.349 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@a4bf93f
    ....
    2024-04-24 14:34:12.353 D/DBINFO: Post Migration 1 to 2 invoked - dumping schema to log:-
    2024-04-24 14:34:12.354 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@e04820c
    ....
    2024-04-24 14:34:12.355 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, `nfcOOOPS` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:34:12.356 D/DBINFO: Before Migration 2 to 3 invoked - dumping schema to log:-
    2024-04-24 14:34:12.357 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8d33755
    ....
    2024-04-24 14:34:12.360 D/DBINFO: Post Migration 2 to 3 invoked - dumping schema to log:-
    2024-04-24 14:34:12.360 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@d88a56a
    ....
    2024-04-24 14:34:12.361 I/System.out:    sql=CREATE TABLE `project` (`id` TEXT NOT NULL, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `startDate` TEXT, `endDate` TEXT, `venueName` TEXT, `timeZone` TEXT, `scheduledAnonymisationDate` TEXT, `nfcOOOPS` TEXT, `nfcCollectorId` TEXT, `nfcMerchantId` TEXT, `nfcPrivateKey` TEXT, PRIMARY KEY(`id`))
    ....
    2024-04-24 14:34:12.947 E/AndroidRuntime: FATAL EXCEPTION: main
        Process: a.a.so78373886multiplemigrations, PID: 16141
        java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so78373886multiplemigrations/a.a.so78373886multiplemigrations.MainActivity}: java.lang.IllegalStateException: Migration didn't properly handle: project(a.a.so78373886multiplemigrations.ProjectEntity).
         Expected:
        TableInfo{name='project', columns={venueName=Column{name='venueName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcMerchantId=Column{name='nfcMerchantId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcPrivateKey=Column{name='nfcPrivateKey', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, endDate=Column{name='endDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, scheduledAnonymisationDate=Column{name='scheduledAnonymisationDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcProfileId=Column{name='nfcProfileId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, timeZone=Column{name='timeZone', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, uuid=Column{name='uuid', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, nfcCollectorId=Column{name='nfcCollectorId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, startDate=Column{name='startDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[], indices=[Index{name='index_project_uuid', unique=false, columns=[uuid], orders=[ASC]'}]}
         Found:
        TableInfo{name='project', columns={id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, uuid=Column{name='uuid', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, startDate=Column{name='startDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, endDate=Column{name='endDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, venueName=Column{name='venueName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, timeZone=Column{name='timeZone', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, scheduledAnonymisationDate=Column{name='scheduledAnonymisationDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcOOOPS=Column{name='nfcOOOPS', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcCollectorId=Column{name='nfcCollectorId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcMerchantId=Column{name='nfcMerchantId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, nfcPrivateKey=Column{name='nfcPrivateKey', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[], indices=[Index{name='index_project_uuid', unique=false, columns=[uuid], orders=[ASC]'}]}