feat: set up repo (#1)

* initial commit

* add gha

* add readme

* move installation steps

* use 3.51.1

* checksum verification

* fix compatibility with android <29

* missing source file

* security fixes

* fix credential persistence

* use commit instead of version

* rearrange

* add vtab

* carray

* generate_series

* fully renovated

* autoinit

* default busy timeout and fk

* remove ci

* bump deps
This commit is contained in:
Mert
2026-02-19 12:36:02 -05:00
committed by GitHub
parent 0da82303b7
commit 57e28db8e2
25 changed files with 1131 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
.build/
.DS_Store
.swiftpm/
Sources/
sqlite-android-custom/
+123
View File
@@ -0,0 +1,123 @@
{
"originHash" : "63d8efd39ff42dbce61b9d3aa4a4ec8e02658e133add2ea4308bfff507949048",
"pins" : [
{
"identity" : "combine-schedulers",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/combine-schedulers",
"state" : {
"revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6",
"version" : "1.1.0"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "cc46202b53476d64e824e0b6612da09d84ffde8e",
"version" : "1.0.6"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
"version" : "1.3.0"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "5a3825302b1a0d744183200915a47b508c828e6f",
"version" : "1.3.2"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1",
"version" : "1.3.3"
}
},
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "a10f9feeb214bc72b5337b6ef6d5a029360db4cc",
"version" : "1.10.0"
}
},
{
"identity" : "swift-identified-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-identified-collections",
"state" : {
"revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597",
"version" : "1.1.1"
}
},
{
"identity" : "swift-perception",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-perception",
"state" : {
"revision" : "4f47ebafed5f0b0172cf5c661454fa8e28fb2ac4",
"version" : "2.0.9"
}
},
{
"identity" : "swift-sharing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-sharing",
"state" : {
"revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818",
"version" : "2.7.4"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "a8b7c5e0ed33d8ab8887d1654d9b59f2cbad529b",
"version" : "1.18.7"
}
},
{
"identity" : "swift-structured-queries",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-structured-queries",
"state" : {
"revision" : "9c84335373bae5f5c9f7b5f0adf3ae10f2cab5b9",
"version" : "0.25.2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-syntax",
"state" : {
"revision" : "4799286537280063c85a32f09884cfbca301b1a1",
"version" : "602.0.0"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618",
"version" : "1.7.0"
}
}
],
"version" : 3
}
+151
View File
@@ -0,0 +1,151 @@
// swift-tools-version: 6.1
import PackageDescription
let package = Package(
name: "sqlite-libs",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13),
.watchOS(.v6),
],
products: [
.library(name: "GRDB", targets: ["GRDB"]),
.library(name: "SQLiteExtensions", targets: ["SQLiteExtensions"]),
.library(name: "SQLiteData", targets: ["SQLiteData"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"),
.package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"),
.package(url: "https://github.com/pointfreeco/swift-structured-queries", from: "0.24.0"),
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"),
],
targets: [
.target(
name: "GRDBSQLite",
path: "Sources/SQLiteCustom",
exclude: ["sqlean/LICENSE"],
sources: [
"sqlite3.c",
"series.c",
"sqlean/sqlite3-uuid.c",
"sqlean/uuid/extension.c",
"sqlean/sqlite3-text.c",
"sqlean/text/extension.c",
"sqlean/text/bstring.c",
"sqlean/text/rstring.c",
"sqlean/text/runes.c",
"sqlean/text/utf8/case.c",
"sqlean/text/utf8/rune.c",
"sqlean/text/utf8/utf8.c",
],
publicHeadersPath: "include",
cSettings: [
.headerSearchPath("include"),
.define("SQLITE_EXTRA_INIT_MUTEXED", to: "sqlite_extensions_init"),
.define("SQLITE_ENABLE_SNAPSHOT"),
.define("SQLITE_ENABLE_FTS5"),
.define("SQLITE_ENABLE_PREUPDATE_HOOK"),
.define("SQLITE_ENABLE_RTREE"),
.define("SQLITE_THREADSAFE", to: "2"),
.define("SQLITE_DQS", to: "0"),
.define("SQLITE_DEFAULT_MEMSTATUS", to: "0"),
.define("SQLITE_LIKE_DOESNT_MATCH_BLOBS"),
.define("SQLITE_MAX_EXPR_DEPTH", to: "0"),
.define("SQLITE_OMIT_PROGRESS_CALLBACK"),
.define("SQLITE_OMIT_SHARED_CACHE"),
.define("SQLITE_USE_ALLOCA"),
.define("SQLITE_OMIT_DEPRECATED"),
.define("SQLITE_TEMP_STORE", to: "2"),
.define("SQLITE_ENABLE_STAT4"),
.define("SQLITE_CORE"),
.define("SQLITE_DEFAULT_CACHE_SIZE", to: "10000"),
.define("SQLITE_DEFAULT_WAL_SYNCHRONOUS"),
.define("SQLITE_DEFAULT_BUSY_TIMEOUT", to: "30000"),
.define("SQLITE_DEFAULT_FOREIGN_KEYS", to: "1"),
.define("SQLITE_ENABLE_PERCENTILE"),
.define("SQLITE_ENABLE_MATH_FUNCTIONS"),
.define("SQLITE_UNTESTABLE"),
.define("SQLITE_OMIT_TCL_VARIABLE"),
.define("SQLITE_HAVE_ISNAN"),
.define("SQLITE_HAVE_LOCALTIME_R"),
.define("SQLITE_HAVE_MALLOC_USABLE_SIZE"),
.define("SQLITE_HAVE_STRCHRNUL"),
.define("SQLITE_ENABLE_GEOPOLY"),
.define("SQLITE_ENABLE_DBSTAT_VTAB"),
.define("SQLITE_ENABLE_CARRAY"),
.define("SQLITE_STAT4_SAMPLES", to: "64"),
.define("NDEBUG", .when(configuration: .release)),
.headerSearchPath("sqlean"),
.headerSearchPath("sqlean/uuid"),
.headerSearchPath("sqlean/text"),
.headerSearchPath("sqlean/text/utf8"),
.unsafeFlags(["-Wno-ambiguous-macro", "-O3"]),
],
),
.target(
name: "GRDB",
dependencies: ["GRDBSQLite"],
path: "Sources/GRDB",
exclude: ["Documentation.docc", "PrivacyInfo.xcprivacy", "LICENSE"],
swiftSettings: [
.define("SQLITE_ENABLE_SNAPSHOT"),
.define("SQLITE_ENABLE_FTS5"),
.define("SQLITE_ENABLE_PREUPDATE_HOOK"),
.define("GRDBCUSTOMSQLITE"),
.unsafeFlags(["-O"]),
]
),
.target(
name: "SQLiteExtensions",
dependencies: ["GRDBSQLite"],
path: "Sources/SQLiteExtensions",
exclude: [
"usearch/LICENSE",
"usearch/stringzilla/LICENSE",
"usearch/simsimd/LICENSE",
"usearch/fp16/LICENSE",
],
sources: [
"initialize-extensions.c",
"usearch/lib.cpp",
],
publicHeadersPath: "include",
cSettings: [
.define("SQLITE_CORE"),
.unsafeFlags(["-O3"]),
],
cxxSettings: [
.headerSearchPath("include"),
.headerSearchPath("usearch/include"),
.headerSearchPath("usearch/stringzilla/include"),
.headerSearchPath("usearch/simsimd/include"),
.headerSearchPath("usearch/fp16/include"),
.define("SQLITE_CORE"),
.define("USEARCH_USE_SIMSIMD"),
.define("USEARCH_USE_FP16LIB"),
.unsafeFlags(["-O3", "-ffast-math"]),
]
),
.target(
name: "SQLiteData",
dependencies: [
"GRDB",
.product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"),
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
.product(name: "OrderedCollections", package: "swift-collections"),
.product(name: "Sharing", package: "swift-sharing"),
.product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"),
],
path: "Sources/SQLiteData",
exclude: ["LICENSE"],
swiftSettings: [.unsafeFlags(["-O"])]
),
],
cLanguageStandard: .c11,
cxxLanguageStandard: .cxx17
)
+55
View File
@@ -0,0 +1,55 @@
# SQLite Libraries
This repository bundles a custom SQLite build for use as a dependency in iOS and Android apps via SPM, JitPack, pub and CocoaPods. Included are:
- SQLite amalgamation, built with optimized settings and the following official extensions:
- snapshot
- fts5
- rtree
- math
- percentile
- geopoly
- carray
- series
- USearch vector extension (SIMD vector search and various distance metrics)
- SQLean's uuid extension (native UUID support, including UUIDv7)
- SQLean's text extension (QoL helpers that exist in PostgreSQL)
- GRDB (Swift SQLite driver, statically linked to custom SQLite)
- SQLiteData (Swift query builder, built on GRDB)
The dependencies are prepared via `scripts/setup.sh`, which downloads and organizes the relevant source code and adds a few shims.
## Installation
### Flutter (Drift)
```yaml
dependency_overrides:
sqlite3_flutter_libs:
git:
url: https://github.com/immich-app/sqlite-libs
path: flutter
ref: <version>
```
### Android (Room/Gradle)
```groovy
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.immich-app.sqlite-libs:sqlite-android:<version>'
}
```
To use with Room:
```kotlin
Room.databaseBuilder(context, AppDatabase::class.java, "db")
.openHelperFactory(RequerySQLiteOpenHelperFactory())
.build()
```
### iOS (Swift Package Manager)
Add to your `Package.swift` or Xcode project:
```
https://github.com/immich-app/sqlite-libs @ <version>
```
+9
View File
@@ -0,0 +1,9 @@
.dart_tool/
.packages
.pub/
pubspec.lock
*.iml
.idea/
build/
.flutter-plugins
.flutter-plugins-dependencies
+49
View File
@@ -0,0 +1,49 @@
group 'eu.simonbinder.sqlite3_flutter_libs'
version '1.0'
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0'
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
mavenLocal()
maven { url 'https://jitpack.io' }
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
namespace 'eu.simonbinder.sqlite3_flutter_libs'
compileSdk 34
defaultConfig {
minSdk 26
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
implementation 'com.github.immich-app.sqlite-libs:sqlite-android:v0.1.0'
}
+8
View File
@@ -0,0 +1,8 @@
rootProject.name = 'sqlite3_flutter_libs'
// Include the sqlite-android module from the parent project
def sqliteAndroidPath = file('../sqlite-android-custom/sqlite-android')
if (sqliteAndroidPath.exists()) {
include ':sqlite-android'
project(':sqlite-android').projectDir = sqliteAndroidPath
}
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,15 @@
package eu.simonbinder.sqlite3_flutter_libs
import io.flutter.embedding.engine.plugins.FlutterPlugin
/**
* Flutter plugin that bundles custom SQLite with extensions.
*
* This plugin ensures the custom SQLite library (with FTS5, USearch, SQLean extensions)
* is bundled with the app via the sqlite-android dependency. The plugin class itself
* is a no-op required by Flutter's plugin system.
*/
class Sqlite3FlutterLibsPlugin : FlutterPlugin {
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
}
@@ -0,0 +1,33 @@
Pod::Spec.new do |s|
s.name = 'sqlite3_flutter_libs'
s.version = '0.0.1'
s.summary = 'Custom SQLite build with extensions for Flutter'
s.description = <<-DESC
Flutter plugin providing a custom SQLite build with FTS5, USearch vector search,
and SQLean extensions (uuid, text). The native library is provided by the
sqlite-libs Swift Package.
DESC
s.homepage = 'https://github.com/immich-app/sqlite-libs'
s.license = { :type => 'AGPLv3' }
s.author = { 'Mert Alev' => '' }
s.source = { :path => '.' }
s.source_files = 'sqlite3_flutter_libs/Sources/sqlite3_flutter_libs/**/*.swift'
s.ios.dependency 'Flutter'
s.osx.dependency 'FlutterMacOS'
s.ios.deployment_target = '13.0'
s.osx.deployment_target = '10.15'
s.swift_version = '5.0'
# The actual SQLite library comes from the sqlite-libs SPM package,
# which is added to the iOS/macOS app via SPM or through the podspec's
# script phase below.
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
# Ensure we can find the SQLite symbols from the parent SPM package
'OTHER_LDFLAGS' => '-lsqlite3',
}
end
@@ -0,0 +1,122 @@
{
"pins" : [
{
"identity" : "combine-schedulers",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/combine-schedulers",
"state" : {
"revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6",
"version" : "1.1.0"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "cc46202b53476d64e824e0b6612da09d84ffde8e",
"version" : "1.0.6"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
"version" : "1.3.0"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "5a3825302b1a0d744183200915a47b508c828e6f",
"version" : "1.3.2"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1",
"version" : "1.3.3"
}
},
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "a10f9feeb214bc72b5337b6ef6d5a029360db4cc",
"version" : "1.10.0"
}
},
{
"identity" : "swift-identified-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-identified-collections",
"state" : {
"revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597",
"version" : "1.1.1"
}
},
{
"identity" : "swift-perception",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-perception",
"state" : {
"revision" : "4f47ebafed5f0b0172cf5c661454fa8e28fb2ac4",
"version" : "2.0.9"
}
},
{
"identity" : "swift-sharing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-sharing",
"state" : {
"revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818",
"version" : "2.7.4"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "a8b7c5e0ed33d8ab8887d1654d9b59f2cbad529b",
"version" : "1.18.7"
}
},
{
"identity" : "swift-structured-queries",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-structured-queries",
"state" : {
"revision" : "9c84335373bae5f5c9f7b5f0adf3ae10f2cab5b9",
"version" : "0.25.2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-syntax",
"state" : {
"revision" : "4799286537280063c85a32f09884cfbca301b1a1",
"version" : "602.0.0"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618",
"version" : "1.7.0"
}
}
],
"version" : 2
}
@@ -0,0 +1,26 @@
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "sqlite3_flutter_libs",
platforms: [
.iOS(.v13),
.macOS(.v10_15)
],
products: [
.library(name: "sqlite3-flutter-libs", type: .static, targets: ["sqlite3_flutter_libs"])
],
dependencies: [
// Reference the parent sqlite-libs package
.package(path: "../../.."),
],
targets: [
.target(
name: "sqlite3_flutter_libs",
dependencies: [
.product(name: "SQLiteExtensions", package: "sqlite-libs"),
]
)
]
)
@@ -0,0 +1,19 @@
import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#endif
/// Flutter plugin that provides custom SQLite with extensions.
///
/// This plugin itself is a no-op - its purpose is to ensure the custom SQLite
/// library (with FTS5, USearch, SQLean extensions) is linked into the app.
/// The actual SQLite symbols come from the sqlite-libs SPM package.
public class Sqlite3FlutterLibsPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
// No method channel needed on iOS/macOS.
// The plugin just ensures SQLite is linked via the SPM dependency.
}
}
+12
View File
@@ -0,0 +1,12 @@
/// Flutter plugin providing custom SQLite build with extensions.
///
/// This package bundles a custom SQLite build with FTS5, USearch vector search,
/// and SQLean extensions (uuid, text). It serves as a drop-in replacement for
/// the standard sqlite3_flutter_libs package.
library sqlite3_flutter_libs;
/// No-op for API compatibility with sqlite3_flutter_libs.
///
/// The original function worked around a bug in Android 6.0.1's dynamic linker.
/// This is unnecessary for minSdk 26+.
Future<void> applyWorkaroundToOpenSqlite3OnOldAndroidVersions() async {}
+28
View File
@@ -0,0 +1,28 @@
name: sqlite3_flutter_libs
description: >-
Flutter plugin providing custom SQLite build with extensions (FTS5, USearch, SQLean).
Drop-in replacement for sqlite3_flutter_libs.
version: 0.5.40
homepage: https://github.com/immich-app/sqlite-libs
environment:
sdk: ">=2.17.0 <4.0.0"
flutter: ">=3.7.0"
dependencies:
flutter:
sdk: flutter
flutter:
plugin:
platforms:
android:
package: eu.simonbinder.sqlite3_flutter_libs
pluginClass: Sqlite3FlutterLibsPlugin
ios:
pluginClass: Sqlite3FlutterLibsPlugin
sharedDarwinSource: true
macos:
pluginClass: Sqlite3FlutterLibsPlugin
sharedDarwinSource: true
+4
View File
@@ -0,0 +1,4 @@
LOCAL_PATH:= $(call my-dir)
include $(LOCAL_PATH)/sqlite/Android.mk
+6
View File
@@ -0,0 +1,6 @@
APP_STL := c++_static
APP_CPPFLAGS := -std=c++17 -fexceptions -frtti
APP_OPTIM := release
APP_ABI := arm64-v8a,x86_64
NDK_TOOLCHAIN_VERSION := clang
NDK_APP_LIBS_OUT := ../jniLibs
+116
View File
@@ -0,0 +1,116 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Custom SQLite flags
# Note: Some flags differ from iOS to maintain compatibility with requery's JNI code:
# - SQLITE_OMIT_TRACE: removed (requery uses sqlite3_trace)
# - SQLITE_OMIT_PROGRESS_CALLBACK: removed (requery uses sqlite3_progress_handler)
# - SQLITE_OMIT_DEPRECATED: removed (sqlite3_trace/profile are deprecated)
sqlite_flags := \
-DNDEBUG=1 \
-DSQLITE_EXTRA_INIT_MUTEXED=sqlite_extensions_init \
-DSQLITE_ENABLE_SNAPSHOT \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_PREUPDATE_HOOK \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_THREADSAFE=2 \
-DSQLITE_DQS=0 \
-DSQLITE_DEFAULT_MEMSTATUS=0 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_USE_ALLOCA \
-DSQLITE_OMIT_AUTOINIT \
-DSQLITE_TEMP_STORE=2 \
-DSQLITE_ENABLE_STAT4 \
-DSQLITE_CORE \
-DSQLITE_DEFAULT_CACHE_SIZE=10000 \
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS \
-DSQLITE_DEFAULT_BUSY_TIMEOUT=30000 \
-DSQLITE_DEFAULT_FOREIGN_KEYS=1 \
-DSQLITE_ENABLE_PERCENTILE \
-DSQLITE_ENABLE_MATH_FUNCTIONS \
-DSQLITE_UNTESTABLE \
-DSQLITE_OMIT_TCL_VARIABLE \
-DSQLITE_HAVE_ISNAN \
-DSQLITE_HAVE_LOCALTIME_R \
-DSQLITE_HAVE_MALLOC_USABLE_SIZE \
-DSQLITE_HAVE_STRCHRNUL \
-DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_CARRAY \
-DHAVE_USLEEP=1 \
-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
-DSQLITE_POWERSAFE_OVERWRITE=1 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
-DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
-DSQLITE_ENABLE_BATCH_ATOMIC_WRITE \
-O3
LOCAL_CFLAGS += $(sqlite_flags)
LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
LOCAL_CFLAGS += -Wno-uninitialized -Wno-parentheses
LOCAL_CPPFLAGS += -Wno-conversion-null
ifeq ($(TARGET_ARCH), arm)
LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
else
LOCAL_CFLAGS += -DPACKED=""
endif
# USearch extension flags
usearch_flags := \
-DSQLITE_CORE \
-DUSEARCH_USE_SIMSIMD \
-DUSEARCH_USE_FP16LIB \
-O3 \
-ffast-math
LOCAL_CPPFLAGS += $(usearch_flags)
# Source files
LOCAL_SRC_FILES := \
android_database_SQLiteCommon.cpp \
android_database_SQLiteConnection.cpp \
android_database_SQLiteFunction.cpp \
android_database_SQLiteGlobal.cpp \
android_database_SQLiteDebug.cpp \
android_database_CursorWindow.cpp \
CursorWindow.cpp \
JNIHelp.cpp \
JNIString.cpp \
sqlite3.c \
sqlite_extensions_init.c \
series.c \
../usearch/lib.cpp \
../sqlean/sqlite3-uuid.c \
../sqlean/uuid/extension.c \
../sqlean/sqlite3-text.c \
../sqlean/text/extension.c \
../sqlean/text/bstring.c \
../sqlean/text/rstring.c \
../sqlean/text/runes.c \
../sqlean/text/utf8/case.c \
../sqlean/text/utf8/rune.c \
../sqlean/text/utf8/utf8.c
# Include paths
LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \
$(LOCAL_PATH)/../usearch/include \
$(LOCAL_PATH)/../usearch/stringzilla/include \
$(LOCAL_PATH)/../usearch/simsimd/include \
$(LOCAL_PATH)/../usearch/fp16/include \
$(LOCAL_PATH)/../sqlean \
$(LOCAL_PATH)/../sqlean/uuid \
$(LOCAL_PATH)/../sqlean/text \
$(LOCAL_PATH)/../sqlean/text/utf8
# Export include path so usearch can find sqlite3ext.h
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := libsqlite3
LOCAL_LDLIBS += -ldl -llog -latomic
include $(BUILD_SHARED_LIBRARY)
@@ -0,0 +1,19 @@
#define SQLITE_CORE 1
#include "sqlite3.h"
// Extension entry points
extern int sqlite3_series_init(sqlite3*, char**, const void*);
extern int sqlite3_uuid_init(sqlite3*, char**, const void*);
extern int sqlite3_text_init(sqlite3*, char**, const void*);
extern int sqlite3_usearch_sqlite_init(sqlite3*, char**, const void*);
// Called automatically during sqlite3_initialize() via SQLITE_EXTRA_INIT_MUTEXED
// Runs under the init mutex, so thread-safe
int sqlite_extensions_init(const char *unused) {
(void)unused;
sqlite3_auto_extension((void (*)(void))sqlite3_series_init);
sqlite3_auto_extension((void (*)(void))sqlite3_uuid_init);
sqlite3_auto_extension((void (*)(void))sqlite3_text_init);
sqlite3_auto_extension((void (*)(void))sqlite3_usearch_sqlite_init);
return SQLITE_OK;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef GRDBSQLITE_H
#define GRDBSQLITE_H
// Umbrella header for the GRDBSQLite module
// This header exposes SQLite and the GRDB shim to Swift
// SQLITE_CORE must be defined before including sqlite3ext.h
// to prevent it from redefining functions to use sqlite3_api
#ifndef SQLITE_CORE
#define SQLITE_CORE 1
#endif
#include "sqlite3.h"
#include "sqlite3ext.h"
#include "shim.h"
#endif /* GRDBSQLITE_H */
@@ -0,0 +1,8 @@
#ifndef INITIALIZE_EXTENSIONS_H
#define INITIALIZE_EXTENSIONS_H
// This function is called automatically during sqlite3_initialize()
// via SQLITE_EXTRA_INIT_MUTEXED - no need to call it manually
int sqlite_extensions_init(const char *unused);
#endif
@@ -0,0 +1,19 @@
#define SQLITE_CORE 1
#include "sqlite3.h"
// Extension entry points (C extensions in GRDBSQLite, USearch in SQLiteExtensions)
extern int sqlite3_series_init(sqlite3*, char**, const void*);
extern int sqlite3_uuid_init(sqlite3*, char**, const void*);
extern int sqlite3_text_init(sqlite3*, char**, const void*);
extern int sqlite3_usearchsqlite_init(sqlite3*, char**, const void*);
// Called automatically during sqlite3_initialize() via SQLITE_EXTRA_INIT_MUTEXED
// Runs under the init mutex, so thread-safe
int sqlite_extensions_init(const char *unused) {
(void)unused;
sqlite3_auto_extension((void (*)(void))sqlite3_series_init);
sqlite3_auto_extension((void (*)(void))sqlite3_uuid_init);
sqlite3_auto_extension((void (*)(void))sqlite3_text_init);
sqlite3_auto_extension((void (*)(void))sqlite3_usearchsqlite_init);
return SQLITE_OK;
}
+79
View File
@@ -0,0 +1,79 @@
#ifndef GRDB_SHIM_H
#define GRDB_SHIM_H
#include "sqlite3.h"
// MARK: - Variadic Functions Support
// sqlite3_config() is a variadic function that can't be directly called from
// Swift. This shim provides a typed wrapper for the specific use case needed.
static inline void _registerErrorLogCallback(void (*callback)(void *pArg, int iErrCode, const char *zMsg)) {
sqlite3_config(SQLITE_CONFIG_LOG, callback, 0);
}
// sqlite3_db_config() is also variadic. These helpers provide typed access.
static inline void _enableDoubleQuotedStringLiterals(sqlite3 *db) {
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 1, (void *)0);
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 1, (void *)0);
}
static inline void _disableDoubleQuotedStringLiterals(sqlite3 *db) {
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, (void *)0);
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, (void *)0);
}
static inline void _disableDefensiveMode(sqlite3 *db) {
sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, (void *)0);
}
// MARK: - Preupdate Hook Functions
// These functions are always declared since they're compiled into our custom
// SQLite build with SQLITE_ENABLE_PREUPDATE_HOOK defined.
// Note: We cannot use #ifdef here because SPM cSettings don't propagate
// to header preprocessing.
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx,
sqlite3 *db,
int op,
char const *zDb,
char const *zName,
sqlite3_int64 iKey1,
sqlite3_int64 iKey2
),
void*
);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
// MARK: - Snapshot Functions
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot **ppSnapshot
);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot *pSnapshot
);
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
sqlite3_snapshot *p2
);
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
#endif /* GRDB_SHIM_H */
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -eu
# Setup script for Android SQLite build
# This regenerates the sqlite-android fork with custom SQLite and USearch extension
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ANDROID_DIR="$ROOT_DIR/sqlite-android-custom"
TEMPLATE_DIR="$SCRIPT_DIR/android"
SQLITE_ANDROID_REPO="https://github.com/requery/sqlite-android.git"
echo "=== SQLite Android Setup ==="
echo "Root directory: $ROOT_DIR"
echo "Android directory: $ANDROID_DIR"
echo "Cloning sqlite-android..."
rm -rf "$ANDROID_DIR"
git clone "$SQLITE_ANDROID_REPO" "$ANDROID_DIR"
rm -rf "$ANDROID_DIR/.git"
JNI_DIR="$ANDROID_DIR/sqlite-android/src/main/jni"
SQLITE_DIR="$JNI_DIR/sqlite"
USEARCH_DIR="$JNI_DIR/usearch"
SQLEAN_DIR="$JNI_DIR/sqlean"
# Copy SQLite source files
echo "Copying SQLite source files..."
cp "$ROOT_DIR/Sources/SQLiteCustom/sqlite3.c" "$SQLITE_DIR/"
cp "$ROOT_DIR/Sources/SQLiteCustom/include/sqlite3.h" "$SQLITE_DIR/"
cp "$ROOT_DIR/Sources/SQLiteCustom/include/sqlite3ext.h" "$SQLITE_DIR/"
# Copy USearch extension
echo "Copying USearch extension..."
rm -rf "$USEARCH_DIR"
mkdir -p "$USEARCH_DIR"
cp -r "$ROOT_DIR/Sources/SQLiteExtensions/usearch/include" "$USEARCH_DIR/"
cp -r "$ROOT_DIR/Sources/SQLiteExtensions/usearch/stringzilla" "$USEARCH_DIR/"
cp -r "$ROOT_DIR/Sources/SQLiteExtensions/usearch/simsimd" "$USEARCH_DIR/"
cp -r "$ROOT_DIR/Sources/SQLiteExtensions/usearch/fp16" "$USEARCH_DIR/"
cp "$ROOT_DIR/Sources/SQLiteExtensions/usearch/lib.cpp" "$USEARCH_DIR/"
cp "$ROOT_DIR/Sources/SQLiteExtensions/usearch/LICENSE" "$USEARCH_DIR/"
# Copy SQLean extensions (uuid and text)
echo "Copying SQLean extensions..."
rm -rf "$SQLEAN_DIR"
mkdir -p "$SQLEAN_DIR"
cp -r "$ROOT_DIR/Sources/SQLiteCustom/sqlean/"* "$SQLEAN_DIR/"
# Copy SQLite series extension
echo "Copying series extension..."
cp "$ROOT_DIR/Sources/SQLiteCustom/series.c" "$SQLITE_DIR/"
# Patch SQLean uuid for Android (timespec_get is not available in Bionic libc)
echo "Patching SQLean uuid for Android..."
UUID_EXT="$SQLEAN_DIR/uuid/extension.c"
sed -i.bak 's/timespec_get(&ts, TIME_UTC)/clock_gettime(CLOCK_REALTIME, \&ts)/' "$UUID_EXT" && rm "$UUID_EXT.bak"
# Copy build configuration files from templates
echo "Copying build configuration files..."
cp "$TEMPLATE_DIR/Application.mk" "$JNI_DIR/"
cp "$TEMPLATE_DIR/Android.mk" "$JNI_DIR/"
cp "$TEMPLATE_DIR/sqlite/Android.mk" "$SQLITE_DIR/"
cp "$TEMPLATE_DIR/sqlite/sqlite_extensions_init.c" "$SQLITE_DIR/"
# Patch library name from sqlite3x to sqlite3
echo "Patching library name..."
SQLITE_DB_FILE="$ANDROID_DIR/sqlite-android/src/main/java/io/requery/android/database/sqlite/SQLiteDatabase.java"
sed -i.bak 's/LIBRARY_NAME = "sqlite3x"/LIBRARY_NAME = "sqlite3"/' "$SQLITE_DB_FILE" && rm "$SQLITE_DB_FILE.bak"
# Patch build.gradle
echo "Patching build.gradle..."
BUILD_GRADLE="$ANDROID_DIR/sqlite-android/build.gradle"
awk '
/abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"/ {
sub(/abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"/, "abiFilters \"arm64-v8a\", \"x86_64\"")
}
/^ext \{/,/^preBuild.dependsOn installSqlite/ {
next
}
{ print }
' "$BUILD_GRADLE" > "$BUILD_GRADLE.tmp" && mv "$BUILD_GRADLE.tmp" "$BUILD_GRADLE"
# Patch gradle.properties for JitPack
echo "Patching gradle.properties for JitPack..."
GRADLE_PROPS="$ANDROID_DIR/gradle.properties"
sed -i.bak 's/^GROUP=.*/GROUP=com.github.immich-app.sqlite-libs/' "$GRADLE_PROPS" && rm "$GRADLE_PROPS.bak"
echo ""
echo "=== Setup complete ==="
echo ""
echo "To build the Android library:"
echo " cd $ANDROID_DIR"
echo " ./gradlew :sqlite-android:assembleRelease"
echo ""
echo "To publish to local Maven:"
echo " ./gradlew :sqlite-android:publishToMavenLocal"
echo ""
echo "The AAR will be at:"
echo " $ANDROID_DIR/sqlite-android/build/outputs/aar/sqlite-android-release.aar"
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env bash
set -eu
# renovate: datasource=github-tags depName=sqlite/sqlite
SQLITE_COMMIT="${SQLITE_COMMIT:-ba76c160c735437de974c6ea24c890a663214c6b}" # version-3.51.2
# renovate: datasource=github-tags depName=groue/GRDB.swift
GRDB_COMMIT="${GRDB_COMMIT:-36e30a6f1ef10e4194f6af0cff90888526f0c115}" # v7.10.0
# renovate: datasource=github-tags depName=pointfreeco/sqlite-data
SQLITEDATA_COMMIT="${SQLITEDATA_COMMIT:-5de18896e7a0358084bb4e3c83f7227500ba029b}" # 1.5.2
# renovate: datasource=github-tags depName=unum-cloud/USearch
USEARCH_COMMIT="${USEARCH_COMMIT:-40d127f472e9073875566f0e9308c0302b89100a}" # v2.24.0
# renovate: datasource=github-tags depName=nalgeon/sqlean
SQLEAN_COMMIT="${SQLEAN_COMMIT:-0e2985467a5da3d7641447616609f8a8b8665b0a}" # 0.28.1
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
OUTPUT_DIR="${1:-$ROOT_DIR}"
TEMPLATES_DIR="${SCRIPT_DIR}/ios"
if [ ! -d "${TEMPLATES_DIR}" ]; then
echo "Error: ios/ templates directory not found at ${TEMPLATES_DIR}"
exit 1
fi
echo "Creating GRDB + SQLiteData package..."
echo " SQLite: ${SQLITE_COMMIT}"
echo " GRDB: ${GRDB_COMMIT}"
echo " SQLiteData: ${SQLITEDATA_COMMIT}"
echo " USearch: ${USEARCH_COMMIT}"
echo " SQLean: ${SQLEAN_COMMIT}"
rm -rf "${OUTPUT_DIR}/Sources"
mkdir -p "${OUTPUT_DIR}/Sources"/{GRDB,SQLiteCustom/include,SQLiteData,SQLiteExtensions/include}
mkdir -p "${OUTPUT_DIR}/Sources"/SQLiteExtensions/usearch/{include/usearch,stringzilla/include/stringzilla,stringzilla/c,simsimd/include/simsimd,fp16/include/fp16}
cd "${OUTPUT_DIR}"
TEMP=$(mktemp -d)
trap "rm -rf ${TEMP}" EXIT
echo "Downloading GRDB..."
curl -sL "https://github.com/groue/GRDB.swift/archive/${GRDB_COMMIT}.tar.gz" \
| tar -xz -C "${TEMP}"
cp -R "${TEMP}"/GRDB.swift-*/GRDB/. Sources/GRDB/
cp "${TEMP}"/GRDB.swift-*/LICENSE Sources/GRDB/LICENSE
echo "Building SQLite amalgamation..."
curl -sL "https://github.com/sqlite/sqlite/archive/${SQLITE_COMMIT}.tar.gz" \
| tar -xz -C "${TEMP}"
SQLITE_SRC="${TEMP}/sqlite-${SQLITE_COMMIT}"
(cd "${SQLITE_SRC}" && ./configure --quiet --enable-update-limit && make -j sqlite3.c)
cp "${SQLITE_SRC}/sqlite3.c" Sources/SQLiteCustom/
cp "${SQLITE_SRC}/sqlite3.h" Sources/SQLiteCustom/include/
cp "${SQLITE_SRC}/sqlite3ext.h" Sources/SQLiteCustom/include/
cp "${SQLITE_SRC}/ext/misc/series.c" Sources/SQLiteCustom/
echo "Downloading SQLiteData..."
curl -sL "https://github.com/pointfreeco/sqlite-data/archive/${SQLITEDATA_COMMIT}.tar.gz" \
| tar -xz -C "${TEMP}"
cp -R "${TEMP}"/sqlite-data-*/Sources/SQLiteData/. Sources/SQLiteData/
cp "${TEMP}"/sqlite-data-*/LICENSE Sources/SQLiteData/LICENSE
rm -rf Sources/SQLiteData/CloudKit Sources/SQLiteData/Documentation.docc 2>/dev/null || true
echo "Downloading USearch..."
git clone --quiet --depth 1 --recursive --shallow-submodules \
https://github.com/unum-cloud/USearch.git "${TEMP}/usearch"
git -C "${TEMP}/usearch" fetch --quiet --depth 1 origin "${USEARCH_COMMIT}"
git -C "${TEMP}/usearch" checkout --quiet "${USEARCH_COMMIT}"
git -C "${TEMP}/usearch" submodule update --quiet --recursive
cp "${TEMP}/usearch/include/usearch/"*.hpp Sources/SQLiteExtensions/usearch/include/usearch/
cp "${TEMP}/usearch/sqlite/lib.cpp" Sources/SQLiteExtensions/usearch/
cp "${TEMP}/usearch/LICENSE" Sources/SQLiteExtensions/usearch/LICENSE
cp "${TEMP}/usearch/stringzilla/include/stringzilla/"*.h Sources/SQLiteExtensions/usearch/stringzilla/include/stringzilla/
cp "${TEMP}/usearch/stringzilla/include/stringzilla/"*.hpp Sources/SQLiteExtensions/usearch/stringzilla/include/stringzilla/
cp "${TEMP}/usearch/stringzilla/c/lib.c" Sources/SQLiteExtensions/usearch/stringzilla/c/
cp "${TEMP}/usearch/stringzilla/LICENSE" Sources/SQLiteExtensions/usearch/stringzilla/LICENSE
cp "${TEMP}/usearch/simsimd/include/simsimd/"*.h Sources/SQLiteExtensions/usearch/simsimd/include/simsimd/
cp "${TEMP}/usearch/simsimd/LICENSE" Sources/SQLiteExtensions/usearch/simsimd/LICENSE
cp "${TEMP}/usearch/fp16/include/fp16/"*.h Sources/SQLiteExtensions/usearch/fp16/include/fp16/
cp "${TEMP}/usearch/fp16/LICENSE" Sources/SQLiteExtensions/usearch/fp16/LICENSE
echo "Downloading SQLean..."
curl -sL "https://github.com/nalgeon/sqlean/archive/${SQLEAN_COMMIT}.tar.gz" \
| tar -xz -C "${TEMP}"
mkdir -p Sources/SQLiteCustom/sqlean
cp "${TEMP}"/sqlean-*/src/sqlean.h Sources/SQLiteCustom/sqlean/
cp "${TEMP}"/sqlean-*/src/sqlite3-uuid.c Sources/SQLiteCustom/sqlean/
cp -R "${TEMP}"/sqlean-*/src/uuid Sources/SQLiteCustom/sqlean/
cp "${TEMP}"/sqlean-*/src/sqlite3-text.c Sources/SQLiteCustom/sqlean/
cp -R "${TEMP}"/sqlean-*/src/text Sources/SQLiteCustom/sqlean/
cp "${TEMP}"/sqlean-*/LICENSE Sources/SQLiteCustom/sqlean/LICENSE
cp "${TEMPLATES_DIR}/shim.h" Sources/SQLiteCustom/include/
cp "${TEMPLATES_DIR}/GRDBSQLite.h" Sources/SQLiteCustom/include/
cp "${TEMPLATES_DIR}/SQLiteExtensions/initialize-extensions.c" Sources/SQLiteExtensions/
cp "${TEMPLATES_DIR}/SQLiteExtensions/include/initialize-extensions.h" Sources/SQLiteExtensions/include/
echo ""
echo "Setting up Android build..."
"${SCRIPT_DIR}/setup-android.sh"