SQLDelight: Manage Databases in Kotlin Multiplatform (KMP)

Jakub Minarik
4 min readNov 4, 2023

Persisting your data in a KMP project can be challenging as implementations vary on different platforms. Fortunately, CashApp has created SQLDelight, a library that allows you to generate a type-safe Kotlin database API from SQL queries. And it works with KMP! Their Getting Started guide is not very comprehensive so I will try to explain in a bit more detail in the context of a KMP project using Compose Multiplatform

SQLDelight implementation in a KMP project

Supposing you have your KMP project set up and running, follow these steps.

Step 1: Set Up SQLDelight Dependencies

Go to your shared module’s build.gradle file and add the following (replace 2.0.0 with the current latest version):

Some important things to note here:

  • The generated database Kotlin code will have the name you set up here (MyAppSQLDelightDatabase). I like to include the library name in, so that there is no confusion
  • The packageName you set here will be important in step 3.

Also, add the platform-specific dependencies (replace 2.0.0 with the current latest version):

Note that I am also adding the coroutines-extensions dependency to commonMain. It is not necessary but highly likely that you will want to leverage some of its features (like converting queries into Flows).

Step 2: Create platform-specific drivers

Obtaining an SqlDriver is platform-specific, so we need different implementations for each platform.

Add this to the commonMain code:

And then provide androidMain implementation

Note: We are using a static application context here. You can check out this StackOverflow thread for ideas how to get it.

And the iosMain implementation.

Step 3: Define your schema

Now you’re ready to define your database schema. Create one or more .sq files in the sqldelight folder in your commonMain package.

IMPORTANT: the sub-folder needs to match the packageName you’ve set up in step 1! This is where SQLDelight expects the .sq files to be.

The important correct folder naming.

Pro tip: Install the SQLDelight Android Studio plugin to make your work easier.

SQLDelight AS plugin

And now you can finally start defining your schema. Typically the first statement in the .sq file creates a table, but you can also create indexes or set up default content. Example:

From these statements, SQLDelight will generate a Database class with an associated Schema object that can be used to create your database and execute statements on it. The Database class is generated by the generateSqlDelightInterface Gradle task which is run automatically by the SQLDelight IDE plugin when you edit a .sq file, and also as part of a normal Gradle build.

If you’ve installed the plugin or build the project now, you should see the generated classes under shared/build/generated/sqldelight.

Step 4: Create a Database instance

I like to create a Database class wrapping the SQLDelight specifics and mapping results to domain objects, Flows etc. All of this is done in the commonMain space. For example like this:

To instantiate the Database class, use a dependency injection framework of your choice. For example with Koin for Compose Multiplatform, the result might look like this:

Module definitions:

In your App Composable:

Step 5: Tweak and test

  • In Xcode, you might need to add -lsqlite3 to Other Liker Flags in your Bulid Settings in order to build the project successfully.
  • Write tests for your Database.
  • Tweak the platform-specific settings if needed.
  • Always map the database entities to custom data classes (as shown in step 4), DO NOT use the auto-generated classes directly.

Conclusion

Creating a Database layer in the context of KMP is fairly simple with SQLDelight. There are, however, a few things to watch out for which I tried to highlight in this article. Feel free to provide your feedback and experience in the comments.

--

--