Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLDelight: [SQLITE_ERROR] SQL error or missing database (table already exists)

I am trying to build a small POC with JetpackCompose Desktop and SQLDelight. I want that the data is persisted even after the application is restarted (not only in memory as all the tutorial examples I encountered show), so I tried this:

// ArticlesLocalDataSource.kt

class ArticlesLocalDataSource {
    private val database: TestDb

    init {
        val driver: SqlDriver = JdbcSqliteDriver(url = "jdbc:sqlite:database.db")
        TestDb.Schema.create(driver)

        database = TestDb(driver)
    }

    // ...
}

When I run the application for the first time this works, i.e: a database.db file in the project root is created and the data is stored successfully.

However, when I try to run the application a second time, then it crashes immediately with:

Exception in thread "main" org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (table ArticleEntity already exists)
    at org.sqlite.core.DB.newSQLException(DB.java:1012)
    at org.sqlite.core.DB.newSQLException(DB.java:1024)
    at org.sqlite.core.DB.throwex(DB.java:989)
    at org.sqlite.core.NativeDB.prepare_utf8(Native Method)
    at org.sqlite.core.NativeDB.prepare(NativeDB.java:134)
    at org.sqlite.core.DB.prepare(DB.java:257)
    at org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:45)
    at org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30)
    at org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:25)
    at org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:35)
    at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:241)
    at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:205)
    at com.squareup.sqldelight.sqlite.driver.JdbcDriver.execute(JdbcDriver.kt:109)
    at com.squareup.sqldelight.db.SqlDriver$DefaultImpls.execute$default(SqlDriver.kt:52)
    at com.vgrec.TestPlus.TestDbImpl$Schema.create(TestDbImpl.kt:33)
    at com.vgrec.data.local.ArticlesLocalDataSource.<init>(ArticlesLocalDataSource.kt:20)

I understand that it's crashing because there's an attempt to create the database again, but the database already exists. What is not clear to me, is how do I connect to the DB if a DB already exists?

For completeness, here's the build file:

// build.gradle


plugins {
    kotlin("jvm") version "1.6.10"
    id("org.jetbrains.compose") version "1.1.0"

    // ...
    id("com.squareup.sqldelight") version "1.5.3"
    
}

sqldelight {
    database("TestDb") {
        packageName = "com.test"
    }
}

dependencies {
    implementation(compose.desktop.currentOs)
    // ..
    implementation("com.squareup.sqldelight:sqlite-driver:1.5.4")
    implementation("com.squareup.sqldelight:coroutines-extensions-jvm:1.5.4")
}
like image 392
VCODE Avatar asked Oct 11 '25 09:10

VCODE


2 Answers

OK, so in the end I decided to just check if the database file exists and invoke the creation only if it does not exist.

Something like this:

init {
  val driver: SqlDriver = JdbcSqliteDriver("jdbc:sqlite:database.db")

  if (!File("database.db").exists()) {
      TestDb.Schema.create(driver)
  }

  // ...
 
}

From first glance this seems to work as expected, but I am not sure this is the recommended approach as I am very new to SQLDelight, so other suggestions are welcome.

like image 189
VCODE Avatar answered Oct 14 '25 13:10

VCODE


May be it's too late, but may be helpful for someone other in future, you can add check while creating table in your table.sq file. For example

CREATE TABLE IF NOT EXISTS productEntity()
like image 22
Abdul Mateen Avatar answered Oct 14 '25 15:10

Abdul Mateen