Skip to content

Commit be91294

Browse files
pbbadenhorstclaude
andcommitted
fix(android): let user sqliteFlags override performanceMode defaults
User-supplied sqliteFlags from package.json could not override flags set by performanceMode on Android. The performance flags went through gradle cFlags (landing in CMAKE_C_FLAGS, late on the clang command line) while user flags went through CMake add_definitions (sorted alphabetically, early on the command line). clang's last-define-wins rule then made the performance defaults authoritative. Route both library defaults (performanceMode, fts5, rtree) and user sqliteFlags through CMake add_compile_options, with defaults declared first and user flags last. add_compile_options preserves declaration order (unlike add_definitions, which CMake sorts before emitting), so the user override is guaranteed to win on the clang command line. Verified against the example app: with no user flags, -DSQLITE_DQS=0 still appears; with "sqliteFlags": "-DSQLITE_DQS=3 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=0", both override flags appear after their defaults in the generated compile_commands.json. iOS already had override semantics via the podspec appending sqliteFlags after optimizedCflags; this aligns Android with iOS behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e7dd159 commit be91294

3 files changed

Lines changed: 28 additions & 13 deletions

File tree

android/CMakeLists.txt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@ if (USE_TURSO)
1919
include_directories(src/main/tursoLibs/include)
2020
endif()
2121

22+
# Apply library-default SQLite flags (driven by package.json toggles such as
23+
# performanceMode, fts5 and rtree) FIRST, then user-supplied sqliteFlags. clang's
24+
# last-define-wins rule lets the user override any default when both define the
25+
# same macro. This mirrors iOS, where the podspec appends sqliteFlags after the
26+
# optimizedCflags. Use add_compile_options (not add_definitions) because CMake
27+
# sorts COMPILE_DEFINITIONS alphabetically before emitting them, which would
28+
# break the override ordering for pairs like -DSQLITE_FOO=1 vs -DSQLITE_FOO=0.
29+
separate_arguments(DEFAULT_SQLITE_FLAGS_LIST UNIX_COMMAND "${DEFAULT_SQLITE_FLAGS}")
2230
separate_arguments(SQLITE_FLAGS_LIST UNIX_COMMAND "${SQLITE_FLAGS}")
2331

24-
add_definitions(
25-
${SQLITE_FLAGS_LIST}
26-
)
32+
add_compile_options(${DEFAULT_SQLITE_FLAGS_LIST})
33+
add_compile_options(${SQLITE_FLAGS_LIST})
2734

2835
add_library(
2936
${PACKAGE_NAME}

android/build.gradle

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ if(!tokenizers.isEmpty()) {
129129
println "[OP-SQLITE] Tokenizers enabled. Detected tokenizers: " + tokenizers
130130
}
131131

132+
// Build the list of library-default SQLite compile flags driven by package.json
133+
// toggles. These are emitted via CMake add_definitions() BEFORE the user-supplied
134+
// sqliteFlags, so that user flags take precedence when both define the same macro
135+
// (clang's last-define-wins). This matches the iOS podspec behavior where
136+
// optimizedCflags are appended before sqliteFlags.
137+
def defaultSqliteFlags = []
138+
if (performanceMode) {
139+
defaultSqliteFlags += ["-DSQLITE_DQS=0", "-DSQLITE_DEFAULT_MEMSTATUS=0", "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1", "-DSQLITE_MAX_EXPR_DEPTH=0", "-DSQLITE_OMIT_DEPRECATED=1", "-DSQLITE_OMIT_PROGRESS_CALLBACK=1", "-DSQLITE_OMIT_SHARED_CACHE=1", "-DSQLITE_USE_ALLOCA=1", "-DSQLITE_THREADSAFE=1"]
140+
}
141+
if (enableFTS5) {
142+
defaultSqliteFlags += "-DSQLITE_ENABLE_FTS5=1"
143+
}
144+
if (enableRtree) {
145+
defaultSqliteFlags += "-DSQLITE_ENABLE_RTREE=1"
146+
}
147+
132148
android {
133149
namespace "com.op.sqlite"
134150

@@ -159,15 +175,6 @@ android {
159175
cFlags += "-DOP_SQLITE_USE_CRSQLITE=1"
160176
cppFlags += "-DOP_SQLITE_USE_CRSQLITE=1"
161177
}
162-
if(performanceMode) {
163-
cFlags += ["-DSQLITE_DQS=0", "-DSQLITE_DEFAULT_MEMSTATUS=0", "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1", "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1", "-DSQLITE_MAX_EXPR_DEPTH=0", "-DSQLITE_OMIT_DEPRECATED=1", "-DSQLITE_OMIT_PROGRESS_CALLBACK=1", "-DSQLITE_OMIT_SHARED_CACHE=1", "-DSQLITE_USE_ALLOCA=1", "-DSQLITE_THREADSAFE=1"]
164-
}
165-
if(enableFTS5) {
166-
cFlags += ["-DSQLITE_ENABLE_FTS5=1"]
167-
}
168-
if(enableRtree) {
169-
cFlags += ["-DSQLITE_ENABLE_RTREE=1"]
170-
}
171178
if(useSqliteVec) {
172179
cFlags += "-DOP_SQLITE_USE_SQLITE_VEC=1"
173180
cppFlags += "-DOP_SQLITE_USE_SQLITE_VEC=1"
@@ -192,6 +199,7 @@ android {
192199
cppFlags "-O3 -frtti -fexceptions -Wall -fstack-protector-all"
193200
abiFilters(*reactNativeArchitectures())
194201
arguments "-DANDROID_STL=c++_shared",
202+
"-DDEFAULT_SQLITE_FLAGS='${defaultSqliteFlags.join(' ')}'",
195203
"-DSQLITE_FLAGS='$sqliteFlags'",
196204
"-DUSE_SQLCIPHER=${useSQLCipher ? 1 : 0}",
197205
"-DUSE_CRSQLITE=${useCRSQLite ? 1 : 0}",

docs/docs/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ All keys are optional, only turn on the features you want:
8080
- `crsqlite` is an extension that allows replication to a server backed sqlite database copy. [Repo here](https://github.com/vlcn-io/cr-sqlite).
8181
- `performanceMode` turns on certain compilation flags that make sqlite speedier at the cost of disabling some features. You should almost always turn this on, but test your app thoroughly.
8282
- `iosSqlite` uses the embedded iOS version from sqlite, which saves disk space but may use an older version and cannot load extensions as Apple disables it due to security concerns. On Android SQLite is always compiled from source as each vendor messes with sqlite or uses outdated versions.
83-
- `sqliteFlags` allows you to pass your own compilation flags to further disable/enable features and extensions. It follows the C flag format: `-D[YOUR_FLAG]=[YOUR_VALUE]`. If you are running large queries on large databases sometimes on Android devices you might get a IO exception. You can disable temporary files by using adding the `"-DSQLITE_TEMP_STORE=2"` flag.
83+
- `sqliteFlags` allows you to pass your own compilation flags to further disable/enable features and extensions. It follows the C flag format: `-D[YOUR_FLAG]=[YOUR_VALUE]`. If you are running large queries on large databases sometimes on Android devices you might get a IO exception. You can disable temporary files by using adding the `"-DSQLITE_TEMP_STORE=2"` flag. Flags listed here are applied AFTER the library defaults (including those added by `performanceMode`), so they override any default with the same name on both iOS and Android. For example, setting `"sqliteFlags": "-DSQLITE_DQS=3"` re-enables double-quoted string literals even when `performanceMode` is on.
8484
- `fts5` enables the full [text search extension](https://www.sqlite.org/fts5.html).
8585
- `tokenizers` allows you to write your own C tokenizers. Read more in the corresponding section in this documentation.
8686
- `rtree` enables the [rtree extension](https://www.sqlite.org/rtree.html)

0 commit comments

Comments
 (0)