Sqldelight database schema not generated
Asked Answered
C

5

20

I have a KMM project and want to use SqlDelight library, but when I build the project database schema not generated and table entities also.

actual class DatabaseDriverFactory(private val context: Context) {
    actual fun createDriver(): SqlDriver {
               //Unresolved reference: CoreDb
        return AndroidSqliteDriver(CoreDb.Schema, context, "test.db")
    }
}

I have defined sqldelight folder inside my shared module and also created folder for feature generated kotlin classes as it is configured in gradle.build.kts and also have one *.sq file inside sqldelight folder

sqldelight {
  database("CoreDb") {
    packageName = "com.example.app.core.database"
    sourceFolders = listOf("sqldelight")
    dialect = "sqlite:3.24"
  }
}

When I run generateSqlDelightInterface task I just see those log

> Task :core:generateAndroidDebugCoreDbInterface NO-SOURCE
> Task :core:generateAndroidReleaseCoreDbInterface NO-SOURCE
> Task :core:generateIosMainCoreDbInterface NO-SOURCE
> Task :core:generateMetadataCommonMainCoreDbInterface NO-SOURCE
> Task :core:generateMetadataMainCoreDbInterface NO-SOURCE
> Task :core:generateSqlDelightInterface UP-TO-DATE
can't register checkAndroidModules

BUILD SUCCESSFUL in 311ms
1:40:36 PM: Task execution finished 'generateSqlDelightInterface'.

Here is my full build.gradle.kts

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
  kotlin("multiplatform")
  kotlin("plugin.serialization")
  id("com.android.library")
  id("kotlin-android-extensions")
  id("koin")
  id("com.squareup.sqldelight")
}

repositories {
  gradlePluginPortal()
  google()
  jcenter()
  mavenCentral()
  maven {
    url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
  }
  maven {
    url = uri("https://dl.bintray.com/ekito/koin")
  }
}
kotlin {
  android()

  val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
    if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
      ::iosArm64
    else
      ::iosX64

  iOSTarget("ios") {
    binaries {
      framework {
        baseName = "core"
      }
    }
  }
  val coroutinesVersion = "1.3.9-native-mt"
  val ktor_version = "1.4.2"
  val serializationVersion = "1.0.0-RC"
  val koin_version = "3.0.0-alpha-4"
  val sqlDelight = "1.4.4"

  sourceSets {

    val commonMain by getting {
      dependencies {
        implementation("io.ktor:ktor-client-core:$ktor_version")
        implementation("io.ktor:ktor-client-serialization:$ktor_version")

        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")


        implementation("com.squareup.sqldelight:runtime:$sqlDelight")
        // SqlDelight extension
        implementation("com.squareup.sqldelight:coroutines-extensions:$sqlDelight")
        // Koin for Kotlin
        implementation("org.koin:koin-core:$koin_version")
        //shared preferences
        implementation("com.russhwolf:multiplatform-settings:0.6.3")
      }
    }
    val commonTest by getting {
      dependencies {
        implementation(kotlin("test-common"))
        implementation(kotlin("test-annotations-common"))
      }
    }
    val androidMain by getting {
      dependencies {
        implementation("androidx.core:core-ktx:1.3.2")
        implementation("io.ktor:ktor-client-android:$ktor_version")
        implementation("com.squareup.sqldelight:android-driver:$sqlDelight")
      }
    }
    val androidTest by getting {
      dependencies {
        implementation(kotlin("test-junit"))
        implementation("junit:junit:4.12")
      }
    }
    val iosMain by getting {
      dependencies {
        implementation("io.ktor:ktor-client-ios:$ktor_version")
        implementation("com.squareup.sqldelight:native-driver:$sqlDelight")
      }
    }

  
    val iosTest by getting
  }
}



android {
  compileSdkVersion(29)
  sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
  defaultConfig {
    minSdkVersion(23)
    targetSdkVersion(29)
    versionCode = 1
    versionName = "1.0"
  }
  buildTypes {
    getByName("release") {
      isMinifyEnabled = false
    }
  }
}
val packForXcode by tasks.creating(Sync::class) {
  group = "build"
  val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
  val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
  val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
  val framework =
    kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)
  inputs.property("mode", mode)
  dependsOn(framework.linkTask)
  val targetDir = File(buildDir, "xcode-frameworks")
  from({ framework.outputDirectory })
  into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)


sqldelight {
  database("CoreDb") {
    packageName = "com.example.app.core.database"
    sourceFolders = listOf("sqldelight")
    dialect = "sqlite:3.24"
  }
}

and for top level build.gradle

classpath "com.squareup.sqldelight:gradle-plugin:$sqlDelight"

Update

My project folder structure

root
  app
    src
      ...

  core //(kmm shared module)
    androidMain
        com.example.app.core
            database
    commonMain
        com.example.app.core
            database
            repository
            ...
            sqldelight
    iosMain
        com.example.app.core
            database
Chessy answered 27/11, 2020 at 9:45 Comment(5)
Could you please post your project folder structure?Aphorism
@Aphorism I have updated the postChessy
sqldelight folder with your *.sq files should be put inside commonMain directlyAphorism
I'll investigate moreAphorism
thanks a lot I'm trying to fix that since yesterdayChessy
A
39

It seems that you have your sqldelight folder, where you put your *.sq files, in the wrong place.

It should be put inside commonMain directly and inside sqldelight you must specify your package.

If your package is com.example.kmmtest003.database your folder structure should be:

- commonMain
    - sqldelight
      - com
        - example
          - kmmtest003
            - database

And here you must put your *.sq files.

enter image description here

OTHER POSSIBLE REASONS

As IgorGanapolsky pointed out, this same issue could be caused also by an incompatible gradle plugin version.

Aphorism answered 27/11, 2020 at 11:16 Comment(10)
I tried that and it says: Task :core:generateAndroidDebugCoreDbInterface FAILED /Users/mrkt/StudioProjects/projectName/core/src/commonMain/sqldelight/User.sq line 1:0 - SqlDelight files must be placed in a package directory.Chessy
@JemoMgebrishvili got it! You have to put the package folder structure inside the folder sqldeglight as the one you specify in your build.gradle.kts:sqldelght section.Aphorism
Nice and thanks, didn't checked yet. Will check it today asapChessy
This isn't the real problem causing such an issue.Preheat
Hi, @Preheat can you elaborate more?Aphorism
@Aphorism I had this issue, and it wasn't due to wrong location of sqldelight. It was due to incompatible gradle plugin version.Preheat
@Preheat so that could be another cause of this issue. But I think that both my answer and yout commet could be usefull. So I update the answer with also this possible cause. Thx!Aphorism
This is the issue I was having with the latest KMM and 1.5.3 of sqldelight. It doesn't state that you need to create these actual directories in the Kotlin tutorial. By creating directories that match the packageName provided you will be able to generate your named database. Thanks @AphorismChenille
I am getting this issue in Compose Desktop project and I dont have a "commonMain" module. Any suggestions?Felspar
@Felspar I guess you don't have a kotlin multiplatform setup. But it doesn't matter. If your source folder is not commonMain but another one, just follow your package name folder structure convention and all should work as expected.Aphorism
P
4

This might help someone in the future...I had created a directory in KMM, and it was named sqldelight.com.package.database

I thought this was a proper package, but realized this was not being caught by SQLDelight, and thus my schema wasn't being generated.

I needed to create the structure as a proper directory structure (and then everything worked):

sqldelight
  com
    package
      database
Porche answered 25/2, 2022 at 17:41 Comment(0)
C
3

Alternately, you can change the folder to kotlin if you want the SQL code to be in the same directory with your code:

sqldelight {
  database("CoreDb") {
    ...
    sourceFolders = listOf("kotlin")
    ...
  }
}
Counterstatement answered 8/3, 2022 at 17:23 Comment(0)
T
3

This might help if you have multiple databases and configuring version >=2.0.0

You need separate top level directory for each database.

The second/incorrect folder structure worked with version 1.x but on 2.x will produce

SqlDelight files must be placed in a package directory

Correct

File structure

src
└─ main
   └─ sqdelight-db1
      └─ com/example/db1
         ├─ Team.sq
         └─ Player.sq
   └─ sqdelight-db2
      └─ com/example/db2
         ├─ Team.sq
         └─ Player.sq

Config

sqldelight {
    databases {
        create("db1") {
            packageName.set("com.example.db1")
            srcDirs.setFrom("src/main/sqldelight-db1")
        }
        create("db2") {
            packageName.set("com.example.db2")
            srcDirs.setFrom("src/main/sqldelight-db2")
        }
    }
}

Incorrect - one that will produce error

File structure

src
└─ main
   └─ sqdelight
      └─ com/example/db1
         ├─ Team.sq
         └─ Player.sq
      └─ com/example/db2 <-- This is wrong
         ├─ Team.sq
         └─ Player.sq

Config

sqldelight {
    databases {
        create("db1") {
            packageName.set("com.example.db1")
            srcDirs.setFrom("src/main/sqldelight/com/example/db1") <-- This is wrong
        }
        create("db2") {
            packageName.set("com.example.db2")
            srcDirs.setFrom("src/main/sqldelight/com/example/db2") <-- This is wrong
        }
    }
}
Tamah answered 18/8, 2023 at 19:5 Comment(2)
Figuring this out on my own was such a pain. Thanks you so much!Puncture
You need a raise man, I was struggling with this for hours..Ground
J
1

I ran into the same problem and I guess the reason was that I tried to place sqldelight not in commonMain but in my jvmMain package in a standard KMM project.

Moving sqldelight to commonMain helped, but I hope there is a solution someone here can share to configure sqldelight in jvmMain or other platform specific sources.

Jade answered 28/9, 2023 at 8:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.