Exploring BundledSQLiteDriver in androidx.sqlite for Kotlin Multiplatform Projects
Introduction
As Kotlin Multiplatform (KMP) continues to gain traction, developers are seeking robust solutions for cross-platform data storage. The androidx.sqlite
library, part of Android Jetpack, introduces BundledSQLiteDriver
—a modern, embedded SQLite driver designed for seamless use across Android, iOS, JVM, and desktop platforms. In this article, we’ll explore how BundledSQLiteDriver
differs from the default Android SQLite implementation, its unique features, limitations, and performance characteristics.
Background: Room, androidx.sqlite, and Abstractions
Room and SQLite Access
Room is a popular ORM-like library for local data storage on Android, built on top of SQLite. Since early versions, Room has accessed SQLite through abstraction interfaces provided by the androidx.sqlite:sqlite
library, such as:
SupportSQLiteOpenHelper
SupportSQLiteDatabase
SupportSQLiteStatement
This abstraction allows Room to swap out the underlying SQLite implementation. The default is FrameworkSQLiteOpenHelper
from androidx.sqlite:sqlite-framework
, but third-party libraries like SQLCipher or requery/sqlite-android can also be used.
Limitations for Multiplatform
These original interfaces closely mirrored Android’s platform classes and depended on Android-specific types (e.g., Cursor
, ContentObserver
, Context
). As a result, they were unsuitable for Kotlin Multiplatform projects.
The KMP Rewrite
With version 2.5.0, androidx.sqlite
was refactored for Kotlin Multiplatform. New, platform-agnostic interfaces were introduced:
SQLiteDriver
: Opens databases and creates connectionsSQLiteConnection
: Manages database interactions and statement creationSQLiteStatement
: Represents prepared SQL statements
These interfaces are simpler, more concise, and closer to the SQLite C API, making them ideal for multiplatform use. They also allow for easy extension—such as logging, profiling, analytics, or encryption—via decorators.
Available SQLiteDriver Implementations
Three main implementations are provided:
- AndroidSQLiteDriver: Uses the system SQLite APIs; Android-only.
- NativeSQLiteDriver: For iOS, Mac, and Linux; links to the system’s
libsqlite
. - BundledSQLiteDriver: Ships a custom SQLite build with your app; recommended for Android, iOS, Mac, Linux, and JVM.
While androidx.sqlite
is designed as a foundation for higher-level frameworks, you can use it directly in your projects, including on the JVM as an alternative to SQLite JDBC.
Why Use BundledSQLiteDriver?
When using BundledSQLiteDriver
on Android, you gain several advantages:
1. Modern SQLite Version
Unlike AndroidSQLiteDriver
, which relies on the device’s system SQLite (often outdated), BundledSQLiteDriver
always uses a recent SQLite release.
2. Predictable Behavior Across Devices
Since the SQLite library is bundled, you can count on consistent features, extensions, and query planner behavior, regardless of device or OS version.
3. Improved Performance
- Faster Queries: Benchmarks show 20–28% faster execution compared to the system driver.
- No Legacy Buffering: The system driver uses a fixed-size buffer (
CursorWindow
) for inter-process communication, which can be a bottleneck.BundledSQLiteDriver
avoids this.
Trade-offs
- App Size: Bundling SQLite increases your APK by about 1MB.
- Memory Usage: Potentially higher memory consumption.
Limitations and Compatibility Considerations
While BundledSQLiteDriver
brings many benefits, there are some important limitations, especially if you’re migrating from AndroidSQLiteDriver
:
1. Localization Support
- No ICU Extension: Functions like case-insensitive
LIKE
,upper()
,lower()
, and regionalCOLLATE
rules may not work as expected. - No REGEXP Operator: Regular expression queries are unavailable.
- Workarounds: For Russian and English, you can normalize text case before saving. Alternatively, consider using Full-Text Search (FTS) with a Unicode tokenizer.
2. Android-Specific Extensions
- Only standard collations (
BINARY
,RTRIM
,NOCASE
) are available. - Android-specific functions (e.g.,
PHONE_NUMBERS_EQUAL()
) are not supported.
3. Missing SQLite Options
- Features like
SQLITE_ENABLE_BYTECODE_VTAB
andSQLITE_ENABLE_DBSTAT_VTAB
are not enabled (as of this writing). - Some legacy PRAGMAs and shared cache support are removed.
Unique Features of BundledSQLiteDriver
BundledSQLiteDriver
unlocks several modern SQLite features not available in the default Android driver (as of SQLite 3.32.2):
- FTS5: Advanced full-text search extension.
- JSON Functions: Native JSON and JSONB support for storing and querying structured data.
- *R-Tree Indexes:** Efficient spatial indexing for range and geospatial queries.
- RIGHT and FULL OUTER JOIN: Expanded SQL join capabilities.
- ALTER TABLE DROP COLUMN: Remove columns from tables (with some restrictions).
- Enhanced UPSERT and RETURNING: More flexible conflict handling and ability to return generated values.
- UPDATE FROM: Update queries using data from other tables or subqueries.
- CTE Table Types: Specify materialization in Common Table Expressions.
- STAT4 Statistics: Improved query planner statistics for better performance.
- Extended Date/Time Functions: New functions and modifiers for date/time calculations.
- Additional Functions:
concat()
,string_agg()
,unhex()
,octet_length()
, and more. - PRAGMA table_list: Retrieve table and view metadata.
- STRICT Tables: Enforce strict schema and data insertion rules.
- Default PRAGMA synchronous: Now set to
NORMAL
for better performance.
Performance Benchmarks
Using Androidx Microbenchmark, tests compared AndroidSQLiteDriver
and BundledSQLiteDriver
on Android 13 with a large dataset (~600MB, 881k records):
- Database Creation: Faster with BundledSQLiteDriver
- Paged Selects: Faster with BundledSQLiteDriver
- Complex Queries: Faster with BundledSQLiteDriver
Lower is better: BundledSQLiteDriver consistently outperforms the system driver by 20–28%.
For full test details and code, see the sqlite-driver-benchmark repository.
Conclusion & Recommendations
BundledSQLiteDriver
is a powerful choice for Kotlin Multiplatform and modern Android projects, offering:
- Access to the latest SQLite features
- Predictable, cross-platform behavior
- Significant performance improvements
However, consider the following before adopting it:
- Localization Needs: If your app relies heavily on advanced localization or regional collation, test thoroughly or consider alternatives.
- App Size Constraints: The increased APK size may be a concern for some projects.
Tip: Always benchmark with your own data and queries to ensure the driver meets your performance and compatibility requirements.
Further Reading:
If you have questions or want to share your experience with BundledSQLiteDriver
, let us know in the comments!