Jemo Mgebrishvili
Jemo Mgebrishvili

Reputation: 5497

Sqldelight database schema not generated

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

Upvotes: 22

Views: 10649

Answers (5)

Yuliana Poliakova
Yuliana Poliakova

Reputation: 31

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.

Upvotes: 1

gswierczynski
gswierczynski

Reputation: 4173

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
        }
    }
}

Upvotes: 5

Booger
Booger

Reputation: 18725

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

Upvotes: 4

shadowsheep
shadowsheep

Reputation: 15012

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.

Upvotes: 40

Saeed Ir
Saeed Ir

Reputation: 2332

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")
    ...
  }
}

Upvotes: 3

Related Questions