Migration
Migration
Learn how to manage database schema changes using SQLiteNow’s migration system.
Directory Structure
Migration files are organized alongside your schema and queries:
src/commonMain/sql/SampleDatabase/
├── schema/ # Latest schema (always current)
├── queries/ # SELECT, INSERT, UPDATE, DELETE queries
├── init/ # Initial data
└── migration/ # Versioned migration files
├── 0001.sql
├── 0002.sql
├── 0003.sql
└── .....sql
How Migration Works
Schema Directory
The schema/
directory must always contain the most recent schema definitions, even when you
alter table in migration files, you must always reflect the final state in the schema files.
These files are only executed when the database is created for the first time, and it is important
to note that migration files are not executed when the database is created for the first time,
this is why you must always keep the schema files up to date. Also, annotations in schema files
are used to generate adapters and other code, annotations in migration files are ignored.
Migration Directory
The migration/
directory contains versioned migration files that update existing databases from
one version to another.
Migration Files
Migration files are numbered sequentially starting from 0001.sql
:
File: migration/0001.sql
-- Migration from version 0 (initial version) to version 1
ALTER TABLE Person
ADD COLUMN middle_name TEXT;
CREATE INDEX idx_person_middle_name ON Person (middle_name);
File: migration/0002.sql
-- Migration from version 1 to version 2
CREATE TABLE UserPreferences
(
id INTEGER PRIMARY KEY NOT NULL,
user_id INTEGER NOT NULL,
theme TEXT NOT NULL DEFAULT 'light',
FOREIGN KEY (user_id) REFERENCES Person (id)
);
Each migration file represents a single version increment and contains the SQL statements needed to upgrade from the previous version.
Generated Migration Class
SQLiteNow automatically generates a VersionBasedDatabaseMigrations
class that contains all your migration files
and knows how to apply them.
Using Migrations
Database Initialization
Pass the generated migration class to your database constructor:
val db = SampleDatabase(
dbName = "sample.db",
migration = VersionBasedDatabaseMigrations(),
// ... other parameters
)
Version Tracking
SQLiteNow automatically tracks the database version by storing it in the database file’s metadata. When your app starts:
- New Database: Creates schema from
schema/
directory, sets version to latest - Existing Database: Checks current version, applies necessary migrations sequentially
Migration Process
Adding a New Migration
- Update Schema Files: Modify files in
schema/
to reflect the latest structure - Create Migration File: Add new numbered migration file (e.g.,
0004.sql
) - Build Project (or run gradle generate task): SQLiteNow regenerates the migration class
Best Practices
Sequential Numbering
Files must be numbered sequentially starting from 0001.sql
.
- ✅
0001.sql
,0002.sql
,0003.sql
- ❌
1.sql
,2.sql
,migration1.sql
For SqliteNow it does not really matter if you have 0001.sql
, 0002.sql
, 0015.sql
or 1.sql
, 2.sql
, 15.sql
but it is recommended to keep it sequential for better readability and easier maintenance.
One-Way Migrations
Migrations should only move forward. Never modify existing migration files after they’ve been released.
Schema Consistency
Always ensure your schema/
files match the result of applying all migrations to an empty database.
Example Workflow
- Initial Release: Database created from
schema/
files (version 0 → latest) - Update 1: Add
migration/0001.sql
, updateschema/
files - Update 2: Add
migration/0002.sql
, updateschema/
files - Update 3: Add
migration/0003.sql
, updateschema/
files
Users upgrading from any previous version will have all necessary migrations applied automatically.