Repository: simolus3/sqlite3.dart
Branch: main
Commit: 366921dae224
Files: 359
Total size: 9.0 MB
Directory structure:
gitextract_d7om4gvc/
├── .gitattributes
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── compile_sqlite.yml
│ ├── main.yml
│ └── release.yml
├── .gitignore
├── .gitmodules
├── .vscode/
│ └── settings.json
├── LICENSE
├── README.md
├── UPGRADING_TO_V3.md
├── examples/
│ ├── flutter_integration_tests/
│ │ ├── .gitignore
│ │ ├── .metadata
│ │ ├── README.md
│ │ ├── analysis_options.yaml
│ │ ├── android/
│ │ │ ├── .gitignore
│ │ │ ├── app/
│ │ │ │ ├── build.gradle.kts
│ │ │ │ └── src/
│ │ │ │ ├── debug/
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── main/
│ │ │ │ │ ├── AndroidManifest.xml
│ │ │ │ │ ├── kotlin/
│ │ │ │ │ │ └── com/
│ │ │ │ │ │ └── example/
│ │ │ │ │ │ └── flutter_integration_tests/
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ │ └── res/
│ │ │ │ │ ├── drawable/
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable-v21/
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── values/
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values-night/
│ │ │ │ │ └── styles.xml
│ │ │ │ └── profile/
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── build.gradle.kts
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradle.properties
│ │ │ └── settings.gradle.kts
│ │ ├── integration_test/
│ │ │ └── integration_test.dart
│ │ ├── ios/
│ │ │ ├── .gitignore
│ │ │ ├── Flutter/
│ │ │ │ ├── AppFrameworkInfo.plist
│ │ │ │ ├── Debug.xcconfig
│ │ │ │ └── Release.xcconfig
│ │ │ ├── Runner/
│ │ │ │ ├── AppDelegate.swift
│ │ │ │ ├── Assets.xcassets/
│ │ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── LaunchImage.imageset/
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ └── README.md
│ │ │ │ ├── Base.lproj/
│ │ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ │ └── Main.storyboard
│ │ │ │ ├── Info.plist
│ │ │ │ └── Runner-Bridging-Header.h
│ │ │ ├── Runner.xcodeproj/
│ │ │ │ ├── project.pbxproj
│ │ │ │ ├── project.xcworkspace/
│ │ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ │ └── xcshareddata/
│ │ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ │ └── WorkspaceSettings.xcsettings
│ │ │ │ └── xcshareddata/
│ │ │ │ └── xcschemes/
│ │ │ │ └── Runner.xcscheme
│ │ │ ├── Runner.xcworkspace/
│ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ └── xcshareddata/
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ │ └── RunnerTests/
│ │ │ └── RunnerTests.swift
│ │ ├── lib/
│ │ │ └── main.dart
│ │ ├── linux/
│ │ │ ├── .gitignore
│ │ │ ├── CMakeLists.txt
│ │ │ ├── flutter/
│ │ │ │ ├── CMakeLists.txt
│ │ │ │ ├── generated_plugin_registrant.cc
│ │ │ │ ├── generated_plugin_registrant.h
│ │ │ │ └── generated_plugins.cmake
│ │ │ └── runner/
│ │ │ ├── CMakeLists.txt
│ │ │ ├── main.cc
│ │ │ ├── my_application.cc
│ │ │ └── my_application.h
│ │ ├── macos/
│ │ │ ├── .gitignore
│ │ │ ├── Flutter/
│ │ │ │ ├── Flutter-Debug.xcconfig
│ │ │ │ ├── Flutter-Release.xcconfig
│ │ │ │ └── GeneratedPluginRegistrant.swift
│ │ │ ├── Runner/
│ │ │ │ ├── AppDelegate.swift
│ │ │ │ ├── Assets.xcassets/
│ │ │ │ │ └── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Base.lproj/
│ │ │ │ │ └── MainMenu.xib
│ │ │ │ ├── Configs/
│ │ │ │ │ ├── AppInfo.xcconfig
│ │ │ │ │ ├── Debug.xcconfig
│ │ │ │ │ ├── Release.xcconfig
│ │ │ │ │ └── Warnings.xcconfig
│ │ │ │ ├── DebugProfile.entitlements
│ │ │ │ ├── Info.plist
│ │ │ │ ├── MainFlutterWindow.swift
│ │ │ │ └── Release.entitlements
│ │ │ ├── Runner.xcodeproj/
│ │ │ │ ├── project.pbxproj
│ │ │ │ ├── project.xcworkspace/
│ │ │ │ │ └── xcshareddata/
│ │ │ │ │ └── IDEWorkspaceChecks.plist
│ │ │ │ └── xcshareddata/
│ │ │ │ └── xcschemes/
│ │ │ │ └── Runner.xcscheme
│ │ │ ├── Runner.xcworkspace/
│ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ └── xcshareddata/
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── RunnerTests/
│ │ │ └── RunnerTests.swift
│ │ ├── pubspec.yaml
│ │ └── windows/
│ │ ├── .gitignore
│ │ ├── CMakeLists.txt
│ │ ├── flutter/
│ │ │ ├── CMakeLists.txt
│ │ │ ├── generated_plugin_registrant.cc
│ │ │ ├── generated_plugin_registrant.h
│ │ │ └── generated_plugins.cmake
│ │ └── runner/
│ │ ├── CMakeLists.txt
│ │ ├── Runner.rc
│ │ ├── flutter_window.cpp
│ │ ├── flutter_window.h
│ │ ├── main.cpp
│ │ ├── resource.h
│ │ ├── runner.exe.manifest
│ │ ├── utils.cpp
│ │ ├── utils.h
│ │ ├── win32_window.cpp
│ │ └── win32_window.h
│ ├── multiplatform/
│ │ ├── analysis_options.yaml
│ │ ├── db/
│ │ │ ├── db.dart
│ │ │ └── sqlite3/
│ │ │ ├── native.dart
│ │ │ ├── sqlite3.dart
│ │ │ ├── unsupported.dart
│ │ │ └── web.dart
│ │ ├── main.dart
│ │ └── pubspec.yaml
│ └── pubspec.yaml
├── legacy/
│ ├── sqlcipher_flutter_libs/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── lib/
│ │ │ └── sqlcipher_flutter_libs.dart
│ │ └── pubspec.yaml
│ └── sqlite3_flutter_libs/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── lib/
│ │ └── sqlite3_flutter_libs.dart
│ └── pubspec.yaml
├── native_tests/
│ ├── all_native_tests.dart
│ ├── analysis_options.yaml
│ ├── ignorelist.txt
│ ├── pubspec.yaml
│ └── run.dart
├── pubspec.yaml
├── sqlite3/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── assets/
│ │ ├── sqlite3.h
│ │ └── sqlite3_dart_wasm.h
│ ├── build.yaml
│ ├── dart_test.yaml
│ ├── dartdoc_options.yaml
│ ├── doc/
│ │ ├── common.md
│ │ ├── hook.md
│ │ ├── native.md
│ │ ├── releasing.md
│ │ └── wasm.md
│ ├── example/
│ │ ├── custom_extension/
│ │ │ ├── README.md
│ │ │ ├── example/
│ │ │ │ └── main.dart
│ │ │ ├── hook/
│ │ │ │ └── build.dart
│ │ │ ├── lib/
│ │ │ │ └── sqlite_vec.dart
│ │ │ ├── pubspec.yaml
│ │ │ └── test/
│ │ │ └── extension_test.dart
│ │ ├── custom_wasm_build/
│ │ │ ├── .cargo/
│ │ │ │ └── config.toml
│ │ │ ├── .gitignore
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ ├── build.rs
│ │ │ ├── link.dart
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── jsonb.dart
│ │ ├── main.dart
│ │ └── web/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── main.dart
│ │ └── worker.dart
│ ├── hook/
│ │ └── build.dart
│ ├── lib/
│ │ ├── common.dart
│ │ ├── sqlite3.dart
│ │ ├── src/
│ │ │ ├── constants.dart
│ │ │ ├── database.dart
│ │ │ ├── exception.dart
│ │ │ ├── ffi/
│ │ │ │ ├── api.dart
│ │ │ │ ├── bindings.dart
│ │ │ │ ├── implementation.dart
│ │ │ │ ├── libsqlite3.g.dart
│ │ │ │ └── memory.dart
│ │ │ ├── functions.dart
│ │ │ ├── hook/
│ │ │ │ ├── asset_hashes.dart
│ │ │ │ ├── assets.dart
│ │ │ │ ├── description.dart
│ │ │ │ ├── used_symbols.dart
│ │ │ │ └── utils.dart
│ │ │ ├── implementation/
│ │ │ │ ├── bindings.dart
│ │ │ │ ├── database.dart
│ │ │ │ ├── exception.dart
│ │ │ │ ├── session.dart
│ │ │ │ ├── sqlite3.dart
│ │ │ │ ├── statement.dart
│ │ │ │ └── utils.dart
│ │ │ ├── in_memory_vfs.dart
│ │ │ ├── jsonb.dart
│ │ │ ├── result_set.dart
│ │ │ ├── session.dart
│ │ │ ├── sqlite3.dart
│ │ │ ├── statement.dart
│ │ │ ├── utils.dart
│ │ │ ├── vfs.dart
│ │ │ └── wasm/
│ │ │ ├── bindings.dart
│ │ │ ├── injected_values.dart
│ │ │ ├── js_interop/
│ │ │ │ ├── atomics.dart
│ │ │ │ ├── core.dart
│ │ │ │ ├── fetch.dart
│ │ │ │ ├── file_system_access.dart
│ │ │ │ ├── indexed_db.dart
│ │ │ │ ├── new_file_system_access.dart
│ │ │ │ └── typed_data.dart
│ │ │ ├── js_interop.dart
│ │ │ ├── loader.dart
│ │ │ ├── sqlite3.dart
│ │ │ ├── sqlite3_wasm.g.dart
│ │ │ ├── vfs/
│ │ │ │ ├── async_opfs/
│ │ │ │ │ ├── client.dart
│ │ │ │ │ ├── sync_channel.dart
│ │ │ │ │ └── worker.dart
│ │ │ │ ├── indexed_db.dart
│ │ │ │ └── simple_opfs.dart
│ │ │ └── wasm_interop.dart
│ │ ├── unstable/
│ │ │ └── ffi_bindings.dart
│ │ └── wasm.dart
│ ├── pubspec.yaml
│ ├── test/
│ │ ├── common/
│ │ │ ├── database.dart
│ │ │ ├── prepared_statement.dart
│ │ │ ├── session.dart
│ │ │ ├── utils.dart
│ │ │ └── vfs.dart
│ │ ├── ffi/
│ │ │ ├── common_database_test.dart
│ │ │ ├── database_test.dart
│ │ │ ├── errors_test.dart
│ │ │ ├── ffi_test.dart
│ │ │ ├── prepared_statement_test.dart
│ │ │ ├── sqlite3_test.dart
│ │ │ └── vfs_test.dart
│ │ ├── hook/
│ │ │ ├── assets_test.dart
│ │ │ └── description_test.dart
│ │ ├── jsonb_test.dart
│ │ ├── source_code_test.dart
│ │ └── wasm/
│ │ ├── asset_server.dart
│ │ ├── common_database_test.dart
│ │ ├── encryption_test.dart
│ │ ├── file_system_test.dart
│ │ ├── prepared_statement_test.dart
│ │ ├── sqlite3_test.dart
│ │ ├── utils.dart
│ │ ├── worker.dart
│ │ └── worker_server.dart
│ └── tool/
│ ├── check_compile_time_option.dart
│ ├── example_server.dart
│ ├── format_native.sh
│ └── generate_bindings.dart
├── sqlite3_connection_pool/
│ ├── .cargo/
│ │ └── config.toml
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── LICENSE
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── example/
│ │ └── main.dart
│ ├── hook/
│ │ └── build.dart
│ ├── lib/
│ │ ├── sqlite3_connection_pool.dart
│ │ └── src/
│ │ ├── abort_exception.dart
│ │ ├── connection.dart
│ │ ├── ffi.g.dart
│ │ ├── mutex.dart
│ │ ├── pool.dart
│ │ └── raw.dart
│ ├── pubspec.yaml
│ ├── src/
│ │ ├── client.rs
│ │ ├── connection.rs
│ │ ├── dart.rs
│ │ ├── headers.h
│ │ ├── lib.rs
│ │ ├── pool.rs
│ │ ├── registry.rs
│ │ └── update_hook.rs
│ ├── test/
│ │ └── pool_test.dart
│ └── tool/
│ ├── build_apple.sh
│ ├── build_linux.sh
│ ├── build_linux_sanitizer.sh
│ └── generate_bindings.dart
├── sqlite3_test/
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── example/
│ │ └── sqlite3_test_example.dart
│ ├── lib/
│ │ └── sqlite3_test.dart
│ ├── pubspec.yaml
│ └── test/
│ └── sqlite3_test_test.dart
├── sqlite3_wasm_build/
│ ├── README.md
│ ├── pubspec.yaml
│ ├── src/
│ │ ├── CMakeLists.txt
│ │ ├── bridge.h
│ │ ├── external_objects.c
│ │ ├── external_objects.h
│ │ ├── getentropy.c
│ │ ├── helpers.c
│ │ ├── os_web.c
│ │ └── sqlite_cfg.h
│ └── tool/
│ └── wasm_symbols.dart
├── sqlite3_web/
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── benchmark/
│ │ ├── benchmark.dart
│ │ ├── index.html
│ │ ├── main.dart
│ │ ├── message.dart
│ │ ├── sql/
│ │ │ ├── benchmark1.sql
│ │ │ ├── benchmark10.sql
│ │ │ ├── benchmark11.sql
│ │ │ ├── benchmark12.sql
│ │ │ ├── benchmark13.sql
│ │ │ ├── benchmark14.sql
│ │ │ ├── benchmark15.sql
│ │ │ ├── benchmark16.sql
│ │ │ ├── benchmark2.sql
│ │ │ ├── benchmark3.sql
│ │ │ ├── benchmark4.sql
│ │ │ ├── benchmark5.sql
│ │ │ ├── benchmark6.sql
│ │ │ ├── benchmark7.sql
│ │ │ ├── benchmark8.sql
│ │ │ └── benchmark9.sql
│ │ └── worker.dart
│ ├── build.yaml
│ ├── dart_test.yaml
│ ├── example/
│ │ ├── controller.dart
│ │ ├── index.html
│ │ ├── main.dart
│ │ ├── main.js
│ │ └── worker.dart
│ ├── lib/
│ │ ├── protocol_utils.dart
│ │ ├── sqlite3_web.dart
│ │ └── src/
│ │ ├── channel.dart
│ │ ├── client.dart
│ │ ├── database.dart
│ │ ├── locks.dart
│ │ ├── protocol/
│ │ │ ├── compatibility_result.dart
│ │ │ ├── dsl.dart
│ │ │ ├── extensions.dart
│ │ │ ├── helper.g.dart
│ │ │ └── messages.dart
│ │ ├── protocol.dart
│ │ ├── shared.dart
│ │ ├── types.dart
│ │ ├── worker.dart
│ │ └── worker_connector.dart
│ ├── pubspec.yaml
│ ├── test/
│ │ ├── asset_server.dart
│ │ ├── client_test.dart
│ │ ├── integration_test.dart
│ │ ├── protocol_test.dart
│ │ └── worker_test.dart
│ ├── tool/
│ │ ├── protocol_generator.dart
│ │ └── server.dart
│ └── web/
│ ├── controller.dart
│ ├── index.html
│ ├── main.dart
│ ├── main.js
│ └── worker.dart
└── tool/
├── build_sqlite.dart
├── build_with_sanitizers.dart
├── download_sqlite.dart
├── hook_overrides.dart
└── write_asset_hashes.dart
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
sqlite3_web/benchmark/sql/* -linguist-detectable
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
groups:
all-github-actions:
patterns:
- "*"
- package-ecosystem: "pub"
versioning-strategy: "increase-if-necessary"
directory: "/"
schedule:
interval: "weekly"
groups:
all-pub-dependencies:
patterns:
- "*"
================================================
FILE: .github/workflows/compile_sqlite.yml
================================================
name: Download and compile SQLite
on:
workflow_call:
outputs:
artifact_id:
description: "ID of the artifact containing prebuilt SQLite libraries"
value: ${{ jobs.merge_assets.outputs.sqlite_merged }}
pool_libs_artifact_id:
description: "ID of the artifact containing libraries for sqlite3_connection_pool"
value: ${{ jobs.merge_assets.outputs.pool_libs }}
sanitized_artifact_id:
description: "ID of the artifact containing libraries compiled with sanitizers"
value: ${{ jobs.build_with_sanitizers.outputs.libs }}
jobs:
download_sqlite:
runs-on: ubuntu-latest
name: Download SQLite sources
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite-src/
key: sqlite-src-${{ hashFiles('tool/download_sqlite.dart') }}
- uses: dart-lang/setup-dart@v1
if: steps.cache_build.outputs.cache-hit != 'true'
- name: Download sqlite3
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
dart run tool/download_sqlite.dart
- name: Upload sqlite3 sources
uses: actions/upload-artifact@v7
with:
name: sqlite-src
path: sqlite-src/
if-no-files-found: error
retention-days: 1
build_sqlite:
needs: [download_sqlite]
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: Compile sqlite3
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite-compiled
key: sqlite-prebuilt-${{ runner.os }}-${{ hashFiles('tool/**', 'sqlite3/lib/src/hook/description.dart', 'sqlite3/lib/src/hook/used_symbols.dart') }}
- name: Download sqlite3 sources
if: steps.cache_build.outputs.cache-hit != 'true'
uses: actions/download-artifact@v8
with:
name: sqlite-src
path: sqlite-src
- uses: dart-lang/setup-dart@v1
if: steps.cache_build.outputs.cache-hit != 'true'
- name: Install cross-compiling GCC
shell: bash
if: runner.os == 'Linux' && steps.cache_build.outputs.cache-hit != 'true'
run: |
sudo apt update
sudo apt install -y gcc-aarch64-linux-gnu gcc-riscv64-linux-gnu gcc-arm-linux-gnueabihf gcc-i686-linux-gnu
- name: Compile sqlite3
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
dart pub get
dart run tool/build_sqlite.dart
- name: Upload sqlite3 binaries
uses: actions/upload-artifact@v7
with:
name: sqlite3-libs-${{ runner.os }}
path: sqlite-compiled
if-no-files-found: error
retention-days: 1
build_with_sanitizers:
needs: [download_sqlite]
runs-on: ubuntu-latest
outputs:
libs: ${{ steps.upload.outputs.artifact-id }}
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite-sanitized
key: sqlite-sanitizers-${{ runner.os }}-${{ hashFiles('tool/**', 'sqlite3/lib/src/hook/description.dart', 'sqlite3_connection_pool/src/**') }}
- name: Download sqlite3 sources
if: steps.cache_build.outputs.cache-hit != 'true'
uses: actions/download-artifact@v8
with:
name: sqlite-src
path: sqlite-src
- uses: dart-lang/setup-dart@v1
if: steps.cache_build.outputs.cache-hit != 'true'
- uses: dtolnay/rust-toolchain@stable
if: steps.cache_build.outputs.cache-hit != 'true'
with:
toolchain: nightly
components: rust-src
- name: Install LLVM toolchain
shell: bash
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
sudo apt update
sudo apt install -y llvm clang lld
- name: Compile sqlite3
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
dart pub get
dart run tool/build_with_sanitizers.dart
- name: Compile pool libraries
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: ./tool/build_linux_sanitizer.sh
- name: Upload binaries
uses: actions/upload-artifact@v7
id: upload
with:
name: sqlite3-sanitized
path: sqlite-sanitized
if-no-files-found: error
retention-days: 1
compile_wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite3_wasm_build/out/
key: sqlite-prebuilt-wasm-${{ hashFiles('sqlite3_wasm_build/src/**') }}
# clang 18 that ships on ubuntu crashes when compiling the wasm sources
- name: Install LLVM and Clang
if: steps.cache_build.outputs.cache-hit != 'true'
uses: KyleMayes/install-llvm-action@v2.0.9
with:
version: "21"
- name: Download WASI SDK
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
ls -al ${{ env.LLVM_PATH }}
curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.deb -o wasi-sdk.deb
sudo dpkg -i wasi-sdk.deb
sudo mkdir /usr/lib/llvm-18/lib/clang/18/lib/wasi
sudo cp -r /opt/wasi-sdk/lib/clang/20/lib/* ${{ env.LLVM_PATH }}/lib/clang/21/lib/
curl -L https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-x86_64-linux.tar.gz -o binaryen.tar.gz
tar --extract --gzip --file binaryen.tar.gz
sudo mv binaryen-version_124/bin/* /usr/local/bin
- uses: dart-lang/setup-dart@v1
if: steps.cache_build.outputs.cache-hit != 'true'
- name: Compile WASM binaries
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_wasm_build/
run: |
cmake -Dwasi_sysroot=/opt/wasi-sdk/share/wasi-sysroot/ -S src -B .dart_tool/sqlite_build
cmake --build .dart_tool/sqlite_build/ -t output -j
- name: Upload sqlite3 binaries
uses: actions/upload-artifact@v7
with:
name: sqlite3-libs-wasm
path: sqlite3_wasm_build/out/
if-no-files-found: error
retention-days: 1
compile_pool_linux_android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite3_connection_pool/out
key: pool-helper-${{ runner.os }}-${{ hashFiles('sqlite3_connection_pool/src/**', 'sqlite3_connection_pool/Cargo.toml', 'sqlite3_connection_pool/.cargo/**') }}
- uses: dtolnay/rust-toolchain@stable
if: steps.cache_build.outputs.cache-hit != 'true'
with:
toolchain: nightly
components: rust-src
targets: aarch64-unknown-linux-gnu,x86_64-unknown-linux-gnu,riscv64gc-unknown-linux-gnu,armv7-unknown-linux-gnueabihf,aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android
- run: cargo install cargo-ndk
if: steps.cache_build.outputs.cache-hit != 'true'
- name: Install cross-compiling GCC
if: steps.cache_build.outputs.cache-hit != 'true'
run: |
sudo apt update
sudo apt install -y gcc-aarch64-linux-gnu gcc-riscv64-linux-gnu gcc-arm-linux-gnueabihf
- name: Build for Linux
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: |
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
./tool/build_linux.sh
- name: Build Android libs
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
env:
RUSTFLAGS: "-Zlocation-detail=none -Zfmt-debug=none -Zunstable-options -Cpanic=immediate-abort"
run: cargo +nightly ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -o target/android build --release -Zbuild-std=std,panic_abort -Zbuild-std-features=
- name: Copy libraries
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: |
mkdir out
cp target/x86_64-unknown-linux-gnu/release/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.linux_x64.so
cp target/aarch64-unknown-linux-gnu/release/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.linux_aarch64.so
cp target/armv7-unknown-linux-gnueabihf/release/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.linux_arm7.so
cp target/riscv64gc-unknown-linux-gnu/release/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.linux_riscv.so
cp target/android/x86_64/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.android_x86_64.so
cp target/android/armeabi-v7a/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.android_v7a.so
cp target/android/arm64-v8a/libsqlite3_connection_pool.so out/libsqlite3_connection_pool.android_v8a.so
- uses: actions/upload-artifact@v7
with:
name: connection-pool-linux
retention-days: 1
path: sqlite3_connection_pool/out
compile_pool_apple:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite3_connection_pool/out
key: pool-helper-${{ runner.os }}-${{ hashFiles('sqlite3_connection_pool/src/**', 'sqlite3_connection_pool/Cargo.toml', 'sqlite3_connection_pool/.cargo/**') }}
- uses: dtolnay/rust-toolchain@stable
if: steps.cache_build.outputs.cache-hit != 'true'
with:
toolchain: nightly
components: rust-src
targets: x86_64-apple-darwin,aarch64-apple-darwin
- name: Build for macOS and iOS
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: |
rustup component add rust-src --toolchain nightly-aarch64-apple-darwin
./tool/build_apple.sh
- name: Copy libraries
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: |
mkdir out
cp target/x86_64-apple-darwin/release/libsqlite3_connection_pool.dylib out/libsqlite3_connection_pool.macos_x64.dylib
cp target/aarch64-apple-darwin/release/libsqlite3_connection_pool.dylib out/libsqlite3_connection_pool.macos_aarch64.dylib
cp target/aarch64-apple-ios/release/libsqlite3_connection_pool.dylib out/libsqlite3_connection_pool.ios_aarch64.dylib
cp target/aarch64-apple-ios-sim/release/libsqlite3_connection_pool.dylib out/libsqlite3_connection_pool.ios_sim_aarch64.dylib
cp target/x86_64-apple-ios/release/libsqlite3_connection_pool.dylib out/libsqlite3_connection_pool.ios_sim_x64.dylib
- uses: actions/upload-artifact@v7
with:
name: connection-pool-apple
retention-days: 1
path: sqlite3_connection_pool/out
compile_pool_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/cache@v5
id: cache_build
with:
path: sqlite3_connection_pool/out
key: pool-helper-${{ runner.os }}-${{ hashFiles('sqlite3_connection_pool/src/**', 'sqlite3_connection_pool/Cargo.toml', 'sqlite3_connection_pool/.cargo/**') }}
- uses: dtolnay/rust-toolchain@stable
if: steps.cache_build.outputs.cache-hit != 'true'
with:
toolchain: nightly
components: rust-src
targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
- name: Build for Windows
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
env:
toolchain: nightly
components: rust-src
RUSTFLAGS: "-Zlocation-detail=none -Zfmt-debug=none -Zunstable-options -Cpanic=immediate-abort"
run: |
rustup component add rust-src --toolchain nightly-x86_64-pc-windows-msvc
cargo +nightly build --release -Z build-std=std,panic_abort -Z build-std-features= --target x86_64-pc-windows-msvc
cargo +nightly build --release -Z build-std=std,panic_abort -Z build-std-features= --target aarch64-pc-windows-msvc
- name: Copy libraries
if: steps.cache_build.outputs.cache-hit != 'true'
working-directory: sqlite3_connection_pool
run: |
mkdir out
cp target/x86_64-pc-windows-msvc/release/sqlite3_connection_pool.dll out/sqlite3_connection_pool.win_x64.dll
cp target/aarch64-pc-windows-msvc/release/sqlite3_connection_pool.dll out/sqlite3_connection_pool.win_aarch64.dll
- uses: actions/upload-artifact@v7
with:
name: connection-pool-windows
retention-days: 1
path: sqlite3_connection_pool/out
merge_assets:
runs-on: ubuntu-latest
needs:
- build_sqlite
- compile_wasm
- compile_pool_linux_android
- compile_pool_apple
- compile_pool_windows
name: Merge prebuilt libraries into single directory
outputs:
sqlite_merged: ${{ steps.upload.outputs.artifact-id }}
pool_libs: ${{ steps.upload_pool.outputs.artifact-id }}
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
path: out/
merge-multiple: true
pattern: sqlite3-libs-*
- uses: actions/download-artifact@v8
with:
path: sqlite3_connection_pool/lib/src/precompiled
merge-multiple: true
pattern: connection-pool-*
- run: ls -al out/
- run: ls -al sqlite3_connection_pool/lib/src/precompiled/
- name: Upload sqlite3 binaries
uses: actions/upload-artifact@v7
id: upload
with:
name: sqlite3-precompiled
path: out/
if-no-files-found: error
retention-days: 1
- name: Upload pool helper binaries
uses: actions/upload-artifact@v7
id: upload_pool
with:
name: connection-pool-libs
path: sqlite3_connection_pool/lib/src/precompiled/
if-no-files-found: error
retention-days: 1
================================================
FILE: .github/workflows/main.yml
================================================
name: CI
on:
push:
branches: ['**']
pull_request:
branches: [ main ]
jobs:
fetch_sqlite:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
uses: ./.github/workflows/compile_sqlite.yml
analyze:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
timeout-minutes: 5
strategy:
matrix:
dart: [stable]
name: Analyze ${{ matrix.package }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
with:
sdk: ${{ matrix.dart }}
- uses: actions/cache@v5
with:
path: "${{ env.PUB_CACHE }}"
key: dart-dependencies-${{ matrix.dart }}-${{ runner.os }}
restore-keys: |
dart-dependencies-${{ matrix.dart }}-
dart-dependencies-
- name: Pub get
run: dart pub get
- name: Format dart
run: |
dart format --set-exit-if-changed sqlite3
dart format --set-exit-if-changed sqlite3_test
dart format --set-exit-if-changed sqlite3_web
- name: Format native
run: clang-format --Werror --dry-run --style=google assets/*.h
working-directory: sqlite3
- name: Format native
run: clang-format --Werror --dry-run --style=google src/*{.h,.c}
working-directory: sqlite3_wasm_build
- name: Analyze
run: dart analyze --fatal-infos sqlite3 sqlite3_web sqlite3_test
test:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
timeout-minutes: 5
needs: [analyze, fetch_sqlite]
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
dart: [stable, dev]
name: Unit tests with Dart ${{ matrix.dart }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
with:
sdk: ${{ matrix.dart }}
- name: Download compiled sqlite3
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.artifact_id }}
path: sqlite-compiled
- name: Download connection pool libraries
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.pool_libs_artifact_id }}
path: sqlite3_connection_pool/lib/src/precompiled/
- name: Download libraries compiled with sanitizers
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.sanitized_artifact_id }}
path: sqlite-sanitized/
- uses: actions/cache@v5
with:
path: "${{ env.PUB_CACHE }}"
key: dart-dependencies-${{ matrix.dart }}-${{ runner.os }}
restore-keys: |
dart-dependencies-${{ matrix.dart }}-
dart-dependencies-
- name: Get Dart dependencies
run: |
dart pub get
- name: Write asset hashes
run: dart run tool/write_asset_hashes.dart
- name: Prepare for tests with pre-compiled SQLite
run: |
dart run tool/hook_overrides.dart compiled
- name: Test sqlite3 package
run: |
dart test --test-randomize-ordering-seed "random" -P ci
working-directory: sqlite3/
- name: Test sqlite3_connection_pool package
run: |
dart test
working-directory: sqlite3_connection_pool/
- name: Test sqlite3_test package
run: dart test
if: ${{ runner.os != 'windows' }} # TODO: Investigate crashes on Windows
working-directory: sqlite3_test/
- name: Test extension example
run: dart test
working-directory: sqlite3/example/custom_extension
- name: Run tests with AOT executable
run: dart run run.dart
working-directory: native_tests/
- name: Run tests AddressSanitizer and MemorySanitizer
if: runner.os == 'Linux'
run: |
dart run.dart --sanitizer=asan
dart run.dart --sanitizer=msan
dart run.dart --sanitizer=tsan
working-directory: native_tests/
- name: Enable sqlite3mc
run: |
dart run tool/hook_overrides.dart compiled-ciphers
- name: Test sqlite3 package with sqlite3mc
run: |
dart test --test-randomize-ordering-seed "random" -P ci
working-directory: sqlite3/
- name: Prepare for tests with system SQLite
run: |
dart run tool/hook_overrides.dart system-os-specific
- name: Test sqlite3 package
run: |
dart test --test-randomize-ordering-seed "random" -P ci
working-directory: sqlite3/
- name: Test sqlite3_connection_pool package
run: |
dart test
working-directory: sqlite3_connection_pool/
- name: Test sqlite3_test package
run: dart test
if: ${{ runner.os != 'windows' }} # TODO: Investigate crashes on Windows
working-directory: sqlite3_test/
- name: Web tests
run: |
cp ../sqlite-compiled/*.wasm example/web
dart test -P web -r expanded
# If browsers behave differently on different platforms, surely that's not our fault...
# So, only run browser tests on Linux to be faster.
if: runner.os == 'Linux'
working-directory: sqlite3/
upload_asset_hashes:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
timeout-minutes: 5
needs: [test, fetch_sqlite]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
- name: Download compiled sqlite3
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.artifact_id }}
path: sqlite-compiled
- uses: actions/cache@v5
with:
path: "${{ env.PUB_CACHE }}"
key: dart-dependencies-beta-${{ runner.os }}
restore-keys: |
dart-dependencies-beta-
dart-dependencies-
- name: Get Dart dependencies
run: |
dart pub get
- name: Write asset hashes
run: dart run tool/write_asset_hashes.dart
- name: Upload asset hashes
uses: actions/upload-artifact@v7
id: upload
with:
name: asset-hashes
path: sqlite3/lib/src/hook/asset_hashes.dart
if-no-files-found: error
retention-days: 1
integration_test_web:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
timeout-minutes: 10
needs: [analyze, fetch_sqlite]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
- name: Download compiled sqlite3
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.artifact_id }}
path: sqlite-compiled
- uses: actions/cache@v5
with:
path: "${{ env.PUB_CACHE }}"
key: dart-dependencies-${{ matrix.dart }}-${{ runner.os }}
restore-keys: |
dart-dependencies-${{ matrix.dart }}-
dart-dependencies-
- name: Prepare for tests
run: |
dart run tool/write_asset_hashes.dart
dart run tool/hook_overrides.dart compiled
- name: Web tests
run: |
cp ../sqlite-compiled/*.wasm web/
dart pub get
dart test -P gh_actions -r expanded
working-directory: sqlite3_web
# The integration tests for android are currently broken (the emulator doesn't want to
# start up...)
#
# integration_test_android:
# runs-on: macos-latest
# needs: [test]
# strategy:
# matrix:
# test:
# - flutter_libs
# - sqlcipher_flutter
# steps:
# - uses: actions/checkout@v6
# - uses: subosito/flutter-action@v2
# with:
# channel: dev
# - name: pub get
# working-directory: "integration_tests/${{ matrix.test }}"
# run: flutter pub get
#
# - name: run tests
# uses: reactivecircus/android-emulator-runner@v2
# with:
# api-level: 29
# script: flutter test integration_test
# working-directory: "integration_tests/${{ matrix.test }}"
# Shamelessly stolen from https://medium.com/flutter-community/run-flutter-driver-tests-on-github-actions-13c639c7e4ab
integration_test:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
strategy:
matrix:
runner: [ubuntu-latest, macos-latest]
needs: [test, fetch_sqlite]
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
env:
AVD_NAME: ubuntu-avd-x86_64-34
steps:
- name: List simulators
if: runner.os == 'macos'
run: "xcrun xctrace list devices"
- name: Start simulator
if: runner.os == 'macos'
run: |
IPHONE=$(xcrun xctrace list devices 2>&1 | grep -m 1 "iPhone" | awk -F'[()]' '{print $4}')
xcrun simctl boot $IPHONE
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
- name: Flutter version
run: flutter --version
- name: Setup runner
if: runner.os == 'linux'
# https://github.com/ReactiveCircus/android-emulator-runner?tab=readme-ov-file#usage--examples
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD Cache
uses: actions/cache@v5
id: avd-cache
if: runner.os == 'linux'
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-35
- name: Download compiled sqlite3
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.artifact_id }}
path: sqlite-compiled
- name: Download connection pool libraries
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.pool_libs_artifact_id }}
path: sqlite3_connection_pool/lib/src/precompiled/
- uses: actions/cache@v5
with:
path: "${{ env.PUB_CACHE }}"
key: dart-dependencies-${{ matrix.dart }}-${{ runner.os }}
restore-keys: |
dart-dependencies-${{ matrix.dart }}-
dart-dependencies-
- name: Write asset hashes
run: |
dart pub get
dart run tool/write_asset_hashes.dart
dart run tool/hook_overrides.dart compiled
- name: Flutter sqlite3 tests on macOS
if: runner.os == 'macos'
working-directory: examples/flutter_integration_tests
run: |
flutter config --enable-swift-package-manager
flutter test integration_test
flutter test integration_test -d macos
- name: Flutter sqlite3 tests on Linux
if: false # runner.os == 'linux' currently broken in ci, can't reproduce locally or in Ubuntu VM
working-directory: examples/flutter_integration_tests
run: |
flutter test integration_test -d linux
- name: SQLite Android emulator tests
uses: reactivecircus/android-emulator-runner@v2
if: runner.os == 'linux'
with:
api-level: 34
force-avd-creation: false
target: google_apis
arch: x86_64
disable-animations: false
avd-name: $AVD_NAME
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: flutter test integration_test
working-directory: "examples/flutter_integration_tests"
- name: Enable sqlite3mc
run: |
dart run tool/hook_overrides.dart compiled-ciphers
- name: Flutter sqlite3mc tests on macOS
if: runner.os == 'macos'
working-directory: examples/flutter_integration_tests
run: |
flutter config --enable-swift-package-manager
flutter test integration_test -Dsqlite3.multipleciphers=true
flutter test integration_test -Dsqlite3.multipleciphers=true -d macos
- name: sqlite3mc Android emulator tests
uses: reactivecircus/android-emulator-runner@v2
if: runner.os == 'linux'
with:
api-level: 34
force-avd-creation: false
target: google_apis
arch: x86_64
disable-animations: false
avd-name: $AVD_NAME
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: flutter test integration_test -Dsqlite3.multipleciphers=true
working-directory: "examples/flutter_integration_tests"
================================================
FILE: .github/workflows/release.yml
================================================
name: Publish to pub.dev
on:
push:
tags:
- 'sqlite3-[0-9]+.[0-9]+.[0-9]+*'
- 'sqlite3_test-[0-9]+.[0-9]+.[0-9]+*'
- 'sqlite3_web-[0-9]+.[0-9]+.[0-9]+*'
- 'sqlite3_connection_pool-[0-9]+.[0-9]+.[0-9]+*'
jobs:
fetch_sqlite:
uses: ./.github/workflows/compile_sqlite.yml
prepare_release:
needs: [fetch_sqlite]
permissions:
packages: write
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1
- name: Pub get
run: dart pub get
- name: Download compiled sqlite3
uses: actions/download-artifact@v8
with:
github-token: ${{ github.token }}
artifact-ids: ${{ needs.fetch_sqlite.outputs.artifact_id }}
path: sqlite-compiled
- name: Set tag name
if: "${{ startsWith(github.ref_name, 'sqlite3-') }}"
id: tag
run: |
tag=$(basename "${{ github.ref }}")
echo "tag=$tag" >> $GITHUB_OUTPUT
- name: Verify asset hashes
if: "${{ startsWith(github.ref_name, 'sqlite3-') }}"
run: dart run tool/write_asset_hashes.dart "${{ steps.tag.outputs.tag }}"
- name: List libraries
run: ls -al sqlite-compiled
- name: Create Release
if: "${{ startsWith(github.ref_name, 'sqlite3-') }}"
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
tag="${{ steps.tag.outputs.tag }}"
body="Pending release for $tag"
gh release create --draft "$tag" --title "$tag" --notes "$body"
gh release upload "$tag" sqlite-compiled/*
publish_sqlite3:
needs: [prepare_release]
permissions:
id-token: write
if: "${{ startsWith(github.ref_name, 'sqlite3-') }}"
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
with:
environment: 'pub.dev'
working-directory: sqlite3/
publish_sqlite3_test:
needs: [prepare_release]
permissions:
id-token: write
if: "${{ startsWith(github.ref_name, 'sqlite3_test-') }}"
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
with:
environment: 'pub.dev'
working-directory: sqlite3_test/
publish_sqlite3_web:
needs: [prepare_release]
permissions:
id-token: write
if: "${{ startsWith(github.ref_name, 'sqlite3_web-') }}"
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
with:
environment: 'pub.dev'
working-directory: sqlite3_web/
publish_sqlite3_connection_pool:
needs: [fetch_sqlite, prepare_release]
permissions:
id-token: write
if: "${{ startsWith(github.ref_name, 'sqlite3_connection_pool-') }}"
runs-on: ubuntu-latest
environment: 'pub.dev'
# This can't use the workflow because we need to download assets to include in
# the package.
steps:
- uses: actions/checkout@v6
- uses: dart-lang/setup-dart@v1 # This will request an OIDC token for pub.dev
- name: Download connection pool libraries
uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.fetch_sqlite.outputs.pool_libs_artifact_id }}
path: sqlite3_connection_pool/lib/src/precompiled/
- name: Pub get
run: dart pub get
- name: Publish - dry run
run: dart pub publish --dry-run
working-directory: sqlite3_connection_pool
- name: Publish to pub.dev
run: dart pub publish -f
working-directory: sqlite3_connection_pool
================================================
FILE: .gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/flutter,dart
# Edit at https://www.toptal.com/developers/gitignore?templates=flutter,dart
### Dart ###
# See https://www.dartlang.org/guides/libraries/private-files
# Files and directories created by pub
.dart_tool/
.packages
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
# dotenv environment variables file
.env*
# Avoid committing generated Javascript files:
*.dart.js
*.info.json # Produced by the --dump-info flag.
*.js # When generated by dart2js. Don't specify *.js if your
# project includes source files written in JavaScript.
*.js_
*.js.deps
*.js.map
.flutter-plugins
.flutter-plugins-dependencies
### Dart Patch ###
# dotenv environment variables file
.env
### Flutter ###
# Flutter/Dart/Pub related
**/doc/api/
.fvm/
.pub-cache/
.pub/
coverage/
lib/generated_plugin_registrant.dart
# For library packages, don’t commit the pubspec.lock file.
# Regenerating the pubspec.lock file lets you test your package against the latest compatible versions of its dependencies.
# See https://dart.dev/guides/libraries/private-files#pubspeclock
#pubspec.lock
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/key.properties
**/.idea/
*.iml
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/.last_build_id
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# End of https://www.toptal.com/developers/gitignore/api/flutter,dart
*.wasm
sqlite-src
sqlite-compiled
tmp
================================================
FILE: .gitmodules
================================================
[submodule "sqlite3_android"]
path = sqlite3_android
url = https://github.com/rodydavis/sqlite-native-libraries
[submodule "sqlite_swift_package"]
path = sqlite_swift_package
url = https://github.com/rodydavis/CSQLite
================================================
FILE: .vscode/settings.json
================================================
{
"rust-analyzer.linkedProjects": [
"sqlite3/example/custom_wasm_build/Cargo.toml"
],
"cSpell.words": [
"Patchset"
]
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Simon Binder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# sqlite3.dart
This project contains Dart packages to use SQLite from Dart via `dart:ffi`.
The main package in this repository is [`sqlite3`](sqlite3), which contains all the Dart apis and their implementation.
`package:sqlite3` is a pure-Dart package without a dependency on Flutter.
It can be used both in Flutter apps or in standalone Dart applications.
`package:sqlite3_test` contains utilities that make integrating SQLite databases into Dart tests easier.
In particular, they patch `CURRENT_TIMESTAMP` and related constructs to return the (potentially faked) time
returned by `package:clock`.
`package:sqlite3_web` contains helpers for running SQLite on the web, including code to compile web workers
that help with the process.
`package:sqlite3_connection_pool` provides an asynchronous connection pool for SQLite that works well across
isolates.
## Example Usage
A file with basic usage examples for pure Dart can be found [here](sqlite3/example/main.dart).
================================================
FILE: UPGRADING_TO_V3.md
================================================
## Upgrading `package:sqlite3`.
This document collects notes on upgrading the `sqlite3` package from version
2.x to version 3.x.
For almost all users, upgrading should be very simple:
1. If you depend on `sqlite3_flutter_libs`, stop doing that.
2. If you depend on `sqlcipher_flutter_libs`, stop doing that and read
[encryption](#encryption).
3. Upgrade to `sqlite3: ^3.0.0`.
4. Make sure you update your `sqlite3.wasm` by downloading it from the
[latest releases](https://github.com/simolus3/sqlite3.dart/releases).
5. If you had `open.overrideFor` code to customize how SQLite is loaded, that needs
to be removed. The package exclusively uses hooks now.
This includes calls to `applyWorkaroundToOpenSqlite3OnOldAndroidVersions` which can
be removed after upgrading.
Version 3.x relies on [hooks](https://dart.dev/tools/hooks) to automatically bundle
a pre-compiled version of SQLite with your application. By default, these binaries
are downloaded from the GitHub releases of this package.
This mechanism replaces the earlier scheme based on platform-specific build
scripts.
If you want to compile SQLite yourself instead of relying on those downloaded
binaries, see [custom SQLite builds](#custom-sqlite-builds).
Also note that the build definition for `sqlite3.wasm` has changed. New sources
are available in [sqlite3_wasm_build](./sqlite3_wasm_build/).
## Encryption
If you've been using SQLCipher to use encrypted databases, note that SQLCipher is
no longer available with version 3. However, a precompiled version of SQLite3MultipleCiphers
can easily be enabled by adding this to your pubspec:
```yaml
hooks:
user_defines:
sqlite3:
source: sqlite3mc
```
SQLite3MultipleCiphers should be compatible with existing databases created by SQLCipher when running the following statements from SQLite3MultipleCiphers:
```
pragma cipher = 'sqlcipher';
pragma legacy = 4;
pragma key = '...your key...';
```
For details, see [hook options](./sqlite3/doc/hook.md) and [sqlite3mc documentation](https://utelle.github.io/SQLite3MultipleCiphers/docs/ciphers/cipher_sqlcipher/).
## Custom SQLite builds
If you want to customize the SQLite build for `package:sqlite3`, there are two options:
1. Downloading `sqlite3.c` into your project and then following the "Custom SQLite builds"
section of [hook options](./sqlite3/doc/hook.md).
2. Using external build scripts (such as SwiftPM or CMake) to statically link SQLite into your
Flutter application, and then following the "Alternatives" section of [hook options](./sqlite3/doc/hook.md).
For details, see [hook options](./sqlite3/doc/hook.md).
If these customization options don't meet your needs, please open an issue!
================================================
FILE: examples/flutter_integration_tests/.gitignore
================================================
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
================================================
FILE: examples/flutter_integration_tests/.metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "465e421f53c05f8f33f83a243c10c55f9f6efbc2"
channel: "beta"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: android
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: ios
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: linux
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: macos
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: web
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
- platform: windows
create_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
base_revision: 465e421f53c05f8f33f83a243c10c55f9f6efbc2
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
================================================
FILE: examples/flutter_integration_tests/README.md
================================================
# flutter_integration_tests
Integration tests for the `sqlite3` package embedded Flutter projects.
================================================
FILE: examples/flutter_integration_tests/analysis_options.yaml
================================================
include: package:flutter_lints/flutter.yaml
================================================
FILE: examples/flutter_integration_tests/android/.gitignore
================================================
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
================================================
FILE: examples/flutter_integration_tests/android/app/build.gradle.kts
================================================
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.flutter_integration_tests"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.flutter_integration_tests"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}
================================================
FILE: examples/flutter_integration_tests/android/app/src/debug/AndroidManifest.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/AndroidManifest.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/kotlin/com/example/flutter_integration_tests/MainActivity.kt
================================================
package com.example.flutter_integration_tests
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/res/drawable/launch_background.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/res/drawable-v21/launch_background.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/res/values/styles.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/main/res/values-night/styles.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/app/src/profile/AndroidManifest.xml
================================================
================================================
FILE: examples/flutter_integration_tests/android/build.gradle.kts
================================================
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean") {
delete(rootProject.layout.buildDirectory)
}
================================================
FILE: examples/flutter_integration_tests/android/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
================================================
FILE: examples/flutter_integration_tests/android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
================================================
FILE: examples/flutter_integration_tests/android/settings.gradle.kts
================================================
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
}
include(":app")
================================================
FILE: examples/flutter_integration_tests/integration_test/integration_test.dart
================================================
// ignore_for_file: avoid_print
import 'package:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_connection_pool/sqlite3_connection_pool.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
test('can open sqlite3', () {
print(sqlite3.version);
final db = sqlite3.openInMemory()..closeWhenDone();
print(db.select('pragma compile_options'));
});
test('pool smoke test', () async {
final pool = SqliteConnectionPool.open(
name: 'test-pool',
openConnections: () => PoolConnections(sqlite3.openInMemory(), []),
);
pool.execute('CREATE TABLE foo (bar TEXT)');
pool.close();
});
test('can open databases', () {
final db = sqlite3.openInMemory()
..closeWhenDone()
..execute('CREATE TABLE foo (bar)')
..execute('INSERT INTO foo VALUES (1), (2)');
expect(db.select('SELECT * FROM foo'), [
{'bar': 1},
{'bar': 2},
]);
});
test('has json support', () {
final db = sqlite3.openInMemory()..closeWhenDone();
expect(db.select("SELECT json('[1, 2, 3]') AS r;"), [
{'r': '[1,2,3]'},
]);
});
test('has fts5 support', () {
final db = sqlite3.openInMemory()..closeWhenDone();
db.execute('CREATE VIRTUAL TABLE foo USING fts5 (a,b,c);');
});
test('can create collation', () {
final db = sqlite3.openInMemory()
..closeWhenDone()
..execute('CREATE TABLE foo2 (bar)')
..execute(
"INSERT INTO foo2 VALUES ('AaAaaaAA'), ('BBBbBb'),('cCCCcc '), (' dD ')",
);
/// Create a collation to compare String without extra-blank to the right and
/// ignoring case
db.createCollation(
name: "RTRIMNOCASE",
function: (String? a, String? b) {
// Combining nocase and rtrim
//
String? compareA = a?.toLowerCase().trimRight();
String? compareB = b?.toLowerCase().trimRight();
if (compareA == null && compareB == null) {
return 0;
} else if (compareA == null) {
// a < b
return -1;
} else if (compareB == null) {
// a > b
return 1;
} else {
return compareA.compareTo(compareB);
}
},
);
expect(
db.select(
"SELECT * FROM foo2 WHERE bar = 'aaaaAaAa ' COLLATE RTRIMNOCASE",
),
[
{'bar': 'AaAaaaAA'},
],
);
expect(
db.select("SELECT * FROM foo2 WHERE bar = 'bbbbbb' COLLATE RTRIMNOCASE"),
[
{'bar': 'BBBbBb'},
],
);
expect(
db.select("SELECT * FROM foo2 WHERE bar = 'cCcccC' COLLATE RTRIMNOCASE"),
[
{'bar': 'cCCCcc '},
],
);
expect(
db.select("SELECT * FROM foo2 WHERE bar = 'dd' COLLATE RTRIMNOCASE"),
[],
);
});
const ciphers = bool.fromEnvironment('sqlite3.multipleciphers');
if (ciphers) {
test('contains sqlite3multipleciphers', () {
final db = sqlite3.openInMemory()..closeWhenDone();
print(db.select('select sqlite3mc_config(?)', ['cipher']));
});
}
}
extension on Database {
void closeWhenDone() => addTearDown(close);
}
================================================
FILE: examples/flutter_integration_tests/ios/.gitignore
================================================
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
================================================
FILE: examples/flutter_integration_tests/ios/Flutter/AppFrameworkInfo.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
App
CFBundleIdentifier
io.flutter.flutter.app
CFBundleInfoDictionaryVersion
6.0
CFBundleName
App
CFBundlePackageType
FMWK
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1.0
MinimumOSVersion
13.0
================================================
FILE: examples/flutter_integration_tests/ios/Flutter/Debug.xcconfig
================================================
#include "Generated.xcconfig"
================================================
FILE: examples/flutter_integration_tests/ios/Flutter/Release.xcconfig
================================================
#include "Generated.xcconfig"
================================================
FILE: examples/flutter_integration_tests/ios/Runner/AppDelegate.swift
================================================
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
================================================
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Base.lproj/Main.storyboard
================================================
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Info.plist
================================================
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
Flutter Integration Tests
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
flutter_integration_tests
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
CADisableMinimumFrameDurationOnPhone
UIApplicationSupportsIndirectInputEvents
================================================
FILE: examples/flutter_integration_tests/ios/Runner/Runner-Bridging-Header.h
================================================
#import "GeneratedPluginRegistrant.h"
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
packageProductDependencies = (
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
);
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
packageReferences = (
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
);
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
isa = XCSwiftPackageProductDependency;
productName = FlutterGeneratedPluginSwiftPackage;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
IDEDidComputeMac32BitWarning
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
================================================
PreviewsEnabled
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
IDEDidComputeMac32BitWarning
================================================
FILE: examples/flutter_integration_tests/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
================================================
PreviewsEnabled
================================================
FILE: examples/flutter_integration_tests/ios/RunnerTests/RunnerTests.swift
================================================
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
================================================
FILE: examples/flutter_integration_tests/lib/main.dart
================================================
import 'package:flutter/material.dart';
import 'package:sqlite3/sqlite3.dart';
void main() {
runApp(SqliteDiagnostics());
}
class SqliteDiagnostics extends StatelessWidget {
const SqliteDiagnostics({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: SingleChildScrollView(child: const _SqliteDiagnosticText()),
),
),
);
}
}
class _SqliteDiagnosticText extends StatefulWidget {
const _SqliteDiagnosticText();
@override
State<_SqliteDiagnosticText> createState() => _SqliteDiagnosticTextState();
}
class _SqliteDiagnosticTextState extends State<_SqliteDiagnosticText> {
var _text = 'Loading';
@override
void initState() {
super.initState();
final db = sqlite3.openInMemory();
final options = db.select('pragma compile_options');
setState(() {
_text = 'Version: ${sqlite3.version}\nOptions: $options';
});
db.close();
}
@override
Widget build(BuildContext context) {
return Text(_text);
}
}
================================================
FILE: examples/flutter_integration_tests/linux/.gitignore
================================================
flutter/ephemeral
================================================
FILE: examples/flutter_integration_tests/linux/CMakeLists.txt
================================================
# Project-level configuration.
cmake_minimum_required(VERSION 3.13)
project(runner LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "flutter_integration_tests")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.example.flutter_integration_tests")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(SET CMP0063 NEW)
# Load bundled libraries from the lib/ directory relative to the binary.
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
# Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>")
endfunction()
# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
# Application build; see runner/CMakeLists.txt.
add_subdirectory("runner")
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endforeach(bundled_library)
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
================================================
FILE: examples/flutter_integration_tests/linux/flutter/CMakeLists.txt
================================================
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)
================================================
FILE: examples/flutter_integration_tests/linux/flutter/generated_plugin_registrant.cc
================================================
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}
================================================
FILE: examples/flutter_integration_tests/linux/flutter/generated_plugin_registrant.h
================================================
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
================================================
FILE: examples/flutter_integration_tests/linux/flutter/generated_plugins.cmake
================================================
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
================================================
FILE: examples/flutter_integration_tests/linux/runner/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.13)
project(runner LANGUAGES CXX)
# Define the application target. To change its name, change BINARY_NAME in the
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
# work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})
# Add preprocessor definitions for the application ID.
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
================================================
FILE: examples/flutter_integration_tests/linux/runner/main.cc
================================================
#include "my_application.h"
int main(int argc, char** argv) {
g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
}
================================================
FILE: examples/flutter_integration_tests/linux/runner/my_application.cc
================================================
#include "my_application.h"
#include
#ifdef GDK_WINDOWING_X11
#include
#endif
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication {
GtkApplication parent_instance;
char** dart_entrypoint_arguments;
};
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Called when first Flutter frame received.
static void first_frame_cb(MyApplication* self, FlView *view)
{
gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
}
// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application);
GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// Use a header bar when running in GNOME as this is the common style used
// by applications and is the setup most users will be using (e.g. Ubuntu
// desktop).
// If running on X and not using GNOME then just use a traditional title bar
// in case the window manager does more exotic layout, e.g. tiling.
// If running on Wayland assume the header bar will work (may need changing
// if future cases occur).
gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11
GdkScreen* screen = gtk_window_get_screen(window);
if (GDK_IS_X11_SCREEN(screen)) {
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
use_header_bar = FALSE;
}
}
#endif
if (use_header_bar) {
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "flutter_integration_tests");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
} else {
gtk_window_set_title(window, "flutter_integration_tests");
}
gtk_window_set_default_size(window, 1280, 720);
g_autoptr(FlDartProject) project = fl_dart_project_new();
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
FlView* view = fl_view_new(project);
GdkRGBA background_color;
// Background defaults to black, override it here if necessary, e.g. #00000000 for transparent.
gdk_rgba_parse(&background_color, "#000000");
fl_view_set_background_color(view, &background_color);
gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
// Show the window when Flutter renders.
// Requires the view to be realized so we can start rendering.
g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), self);
gtk_widget_realize(GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
}
// Implements GApplication::local_command_line.
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
MyApplication* self = MY_APPLICATION(application);
// Strip out the first argument as it is the binary name.
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
g_autoptr(GError) error = nullptr;
if (!g_application_register(application, nullptr, &error)) {
g_warning("Failed to register: %s", error->message);
*exit_status = 1;
return TRUE;
}
g_application_activate(application);
*exit_status = 0;
return TRUE;
}
// Implements GApplication::startup.
static void my_application_startup(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);
// Perform any actions required at application startup.
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
}
// Implements GApplication::shutdown.
static void my_application_shutdown(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);
// Perform any actions required at application shutdown.
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
}
// Implements GObject::dispose.
static void my_application_dispose(GObject* object) {
MyApplication* self = MY_APPLICATION(object);
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
}
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
}
static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() {
// Set the program name to the application ID, which helps various systems
// like GTK and desktop environments map this running application to its
// corresponding .desktop file. This ensures better integration by allowing
// the application to be recognized beyond its binary name.
g_set_prgname(APPLICATION_ID);
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE,
nullptr));
}
================================================
FILE: examples/flutter_integration_tests/linux/runner/my_application.h
================================================
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_
#include
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication)
/**
* my_application_new:
*
* Creates a new Flutter-based application.
*
* Returns: a new #MyApplication.
*/
MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_
================================================
FILE: examples/flutter_integration_tests/macos/.gitignore
================================================
# Flutter-related
**/Flutter/ephemeral/
**/Pods/
# Xcode-related
**/dgph
**/xcuserdata/
================================================
FILE: examples/flutter_integration_tests/macos/Flutter/Flutter-Debug.xcconfig
================================================
#include "ephemeral/Flutter-Generated.xcconfig"
================================================
FILE: examples/flutter_integration_tests/macos/Flutter/Flutter-Release.xcconfig
================================================
#include "ephemeral/Flutter-Generated.xcconfig"
================================================
FILE: examples/flutter_integration_tests/macos/Flutter/GeneratedPluginRegistrant.swift
================================================
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
}
================================================
FILE: examples/flutter_integration_tests/macos/Runner/AppDelegate.swift
================================================
import Cocoa
import FlutterMacOS
@main
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
}
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_16.png",
"scale" : "1x"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_64.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_128.png",
"scale" : "1x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_1024.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Base.lproj/MainMenu.xib
================================================
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Configs/AppInfo.xcconfig
================================================
// Application-level settings for the Runner target.
//
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
// future. If not, the values below would default to using the project name when this becomes a
// 'flutter create' template.
// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = flutter_integration_tests
// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved.
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Configs/Debug.xcconfig
================================================
#include "../../Flutter/Flutter-Debug.xcconfig"
#include "Warnings.xcconfig"
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Configs/Release.xcconfig
================================================
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Configs/Warnings.xcconfig
================================================
WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
GCC_WARN_UNDECLARED_SELECTOR = YES
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
CLANG_WARN_PRAGMA_PACK = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
GCC_WARN_STRICT_SELECTOR_MATCH = YES
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
GCC_WARN_SHADOW = YES
CLANG_WARN_UNREACHABLE_CODE = YES
================================================
FILE: examples/flutter_integration_tests/macos/Runner/DebugProfile.entitlements
================================================
com.apple.security.app-sandbox
com.apple.security.cs.allow-jit
com.apple.security.network.server
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Info.plist
================================================
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIconFile
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
NSHumanReadableCopyright
$(PRODUCT_COPYRIGHT)
NSMainNibFile
MainMenu
NSPrincipalClass
NSApplication
================================================
FILE: examples/flutter_integration_tests/macos/Runner/MainFlutterWindow.swift
================================================
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
}
================================================
FILE: examples/flutter_integration_tests/macos/Runner/Release.entitlements
================================================
com.apple.security.app-sandbox
================================================
FILE: examples/flutter_integration_tests/macos/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
buildPhases = (
33CC111E2044C6BF0003C045 /* ShellScript */,
);
dependencies = (
);
name = "Flutter Assemble";
productName = FLX;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC10EC2044A3C60003C045;
remoteInfo = Runner;
};
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
remoteInfo = FLX;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
33CC110E2044A8840003C045 /* Bundle Framework */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Bundle Framework";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
33CC10ED2044A3C60003C045 /* flutter_integration_tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "flutter_integration_tests.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
331C80D2294CF70F00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EA2044A3C60003C045 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C80D7294CF71000263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "";
};
33BA886A226E78AF003329D5 /* Configs */ = {
isa = PBXGroup;
children = (
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
);
path = Configs;
sourceTree = "";
};
33CC10E42044A3C60003C045 = {
isa = PBXGroup;
children = (
33FAB671232836740065AC1E /* Runner */,
33CEB47122A05771004F2AC0 /* Flutter */,
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
);
sourceTree = "";
};
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* flutter_integration_tests.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "";
};
33CC11242044D66E0003C045 /* Resources */ = {
isa = PBXGroup;
children = (
33CC10F22044A3C60003C045 /* Assets.xcassets */,
33CC10F42044A3C60003C045 /* MainMenu.xib */,
33CC10F72044A3C60003C045 /* Info.plist */,
);
name = Resources;
path = ..;
sourceTree = "";
};
33CEB47122A05771004F2AC0 /* Flutter */ = {
isa = PBXGroup;
children = (
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
);
path = Flutter;
sourceTree = "";
};
33FAB671232836740065AC1E /* Runner */ = {
isa = PBXGroup;
children = (
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
33E51914231749380026EE4D /* Release.entitlements */,
33CC11242044D66E0003C045 /* Resources */,
33BA886A226E78AF003329D5 /* Configs */,
);
path = Runner;
sourceTree = "";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C80D4294CF70F00263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C80DA294CF71000263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
33CC10EC2044A3C60003C045 /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
);
buildRules = (
);
dependencies = (
33CC11202044C79F0003C045 /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* flutter_integration_tests.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
33CC10E52044A3C60003C045 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 33CC10EC2044A3C60003C045;
};
33CC10EC2044A3C60003C045 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1100;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
};
};
};
33CC111A2044C6BA0003C045 = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Manual;
};
};
};
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 33CC10E42044A3C60003C045;
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
33CC10EC2044A3C60003C045 /* Runner */,
331C80D4294CF70F00263BE5 /* RunnerTests */,
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C80D3294CF70F00263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EB2044A3C60003C045 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
};
33CC111E2044C6BF0003C045 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
Flutter/ephemeral/FlutterInputs.xcfilelist,
);
inputPaths = (
Flutter/ephemeral/tripwire,
);
outputFileListPaths = (
Flutter/ephemeral/FlutterOutputs.xcfilelist,
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C80D1294CF70F00263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10E92044A3C60003C045 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC10EC2044A3C60003C045 /* Runner */;
targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
};
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
33CC10F52044A3C60003C045 /* Base */,
);
name = MainMenu.xib;
path = Runner;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/flutter_integration_tests.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/flutter_integration_tests";
};
name = Debug;
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/flutter_integration_tests.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/flutter_integration_tests";
};
name = Release;
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterIntegrationTests.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/flutter_integration_tests.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/flutter_integration_tests";
};
name = Profile;
};
338D0CE9231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Profile;
};
338D0CEA231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Profile;
};
338D0CEB231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Profile;
};
33CC10F92044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
33CC10FA2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
};
33CC10FC2044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
33CC10FD2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
};
33CC111C2044C6BA0003C045 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
33CC111D2044C6BA0003C045 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C80DB294CF71000263BE5 /* Debug */,
331C80DC294CF71000263BE5 /* Release */,
331C80DD294CF71000263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10F92044A3C60003C045 /* Debug */,
33CC10FA2044A3C60003C045 /* Release */,
338D0CE9231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10FC2044A3C60003C045 /* Debug */,
33CC10FD2044A3C60003C045 /* Release */,
338D0CEA231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC111C2044C6BA0003C045 /* Debug */,
33CC111D2044C6BA0003C045 /* Release */,
338D0CEB231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
}
================================================
FILE: examples/flutter_integration_tests/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
IDEDidComputeMac32BitWarning
================================================
FILE: examples/flutter_integration_tests/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
================================================
FILE: examples/flutter_integration_tests/macos/Runner.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: examples/flutter_integration_tests/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
IDEDidComputeMac32BitWarning
================================================
FILE: examples/flutter_integration_tests/macos/RunnerTests/RunnerTests.swift
================================================
import Cocoa
import FlutterMacOS
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
================================================
FILE: examples/flutter_integration_tests/pubspec.yaml
================================================
name: flutter_integration_tests
publish_to: 'none'
version: 1.0.0+1
resolution: workspace
environment:
sdk: ^3.10.0-0
dependencies:
flutter:
sdk: flutter
sqlite3:
sqlite3_connection_pool:
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
flutter_lints: ^6.0.0
flutter:
uses-material-design: true
================================================
FILE: examples/flutter_integration_tests/windows/.gitignore
================================================
flutter/ephemeral/
# Visual Studio user-specific files.
*.suo
*.user
*.userosscache
*.sln.docstates
# Visual Studio build-related files.
x64/
x86/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
================================================
FILE: examples/flutter_integration_tests/windows/CMakeLists.txt
================================================
# Project-level configuration.
cmake_minimum_required(VERSION 3.14)
project(flutter_integration_tests LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "flutter_integration_tests")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(VERSION 3.14...3.25)
# Define build configuration option.
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTICONFIG)
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
CACHE STRING "" FORCE)
else()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
endif()
# Define settings for the Profile build mode.
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
# Use Unicode for all projects.
add_definitions(-DUNICODE -D_UNICODE)
# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_17)
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
target_compile_options(${TARGET} PRIVATE /EHsc)
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
endfunction()
# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})
# Application build; see runner/CMakeLists.txt.
add_subdirectory("runner")
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# Support files are copied into place next to the executable, so that it can
# run in place. This is done instead of making a separate bundle (as on Linux)
# so that building and running from within Visual Studio will work.
set(BUILD_BUNDLE_DIR "$")
# Make the "install" step default, as it's required to run.
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
CONFIGURATIONS Profile;Release
COMPONENT Runtime)
================================================
FILE: examples/flutter_integration_tests/windows/flutter/CMakeLists.txt
================================================
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.14)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
# Set fallback configurations for older versions of the flutter tool.
if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
set(FLUTTER_TARGET_PLATFORM "windows-x64")
endif()
# === Flutter Library ===
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"flutter_export.h"
"flutter_windows.h"
"flutter_messenger.h"
"flutter_plugin_registrar.h"
"flutter_texture_registrar.h"
)
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
add_dependencies(flutter flutter_assemble)
# === Wrapper ===
list(APPEND CPP_WRAPPER_SOURCES_CORE
"core_implementations.cc"
"standard_codec.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
"plugin_registrar.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
list(APPEND CPP_WRAPPER_SOURCES_APP
"flutter_engine.cc"
"flutter_view_controller.cc"
)
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
# Wrapper sources needed for a plugin.
add_library(flutter_wrapper_plugin STATIC
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_PLUGIN}
)
apply_standard_settings(flutter_wrapper_plugin)
set_target_properties(flutter_wrapper_plugin PROPERTIES
POSITION_INDEPENDENT_CODE ON)
set_target_properties(flutter_wrapper_plugin PROPERTIES
CXX_VISIBILITY_PRESET hidden)
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
target_include_directories(flutter_wrapper_plugin PUBLIC
"${WRAPPER_ROOT}/include"
)
add_dependencies(flutter_wrapper_plugin flutter_assemble)
# Wrapper sources needed for the runner.
add_library(flutter_wrapper_app STATIC
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_APP}
)
apply_standard_settings(flutter_wrapper_app)
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
target_include_directories(flutter_wrapper_app PUBLIC
"${WRAPPER_ROOT}/include"
)
add_dependencies(flutter_wrapper_app flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
${CPP_WRAPPER_SOURCES_APP}
${PHONY_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
${FLUTTER_TARGET_PLATFORM} $
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
${CPP_WRAPPER_SOURCES_CORE}
${CPP_WRAPPER_SOURCES_PLUGIN}
${CPP_WRAPPER_SOURCES_APP}
)
================================================
FILE: examples/flutter_integration_tests/windows/flutter/generated_plugin_registrant.cc
================================================
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void RegisterPlugins(flutter::PluginRegistry* registry) {
}
================================================
FILE: examples/flutter_integration_tests/windows/flutter/generated_plugin_registrant.h
================================================
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include
// Registers Flutter plugins.
void RegisterPlugins(flutter::PluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
================================================
FILE: examples/flutter_integration_tests/windows/flutter/generated_plugins.cmake
================================================
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
================================================
FILE: examples/flutter_integration_tests/windows/runner/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.14)
project(runner LANGUAGES CXX)
# Define the application target. To change its name, change BINARY_NAME in the
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
# work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME} WIN32
"flutter_window.cpp"
"main.cpp"
"utils.cpp"
"win32_window.cpp"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
"Runner.rc"
"runner.exe.manifest"
)
# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})
# Add preprocessor definitions for the build version.
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
# Disable Windows macros that collide with C++ standard library functions.
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
# Add dependency libraries and include directories. Add any application-specific
# dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
================================================
FILE: examples/flutter_integration_tests/windows/runner/Runner.rc
================================================
// Microsoft Visual C++ generated resource script.
//
#pragma code_page(65001)
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APP_ICON ICON "resources\\app_icon.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
#else
#define VERSION_AS_NUMBER 1,0,0,0
#endif
#if defined(FLUTTER_VERSION)
#define VERSION_AS_STRING FLUTTER_VERSION
#else
#define VERSION_AS_STRING "1.0.0"
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_AS_NUMBER
PRODUCTVERSION VERSION_AS_NUMBER
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "com.example" "\0"
VALUE "FileDescription", "flutter_integration_tests" "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "flutter_integration_tests" "\0"
VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0"
VALUE "OriginalFilename", "flutter_integration_tests.exe" "\0"
VALUE "ProductName", "flutter_integration_tests" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
================================================
FILE: examples/flutter_integration_tests/windows/runner/flutter_window.cpp
================================================
#include "flutter_window.h"
#include
#include "flutter/generated_plugin_registrant.h"
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
: project_(project) {}
FlutterWindow::~FlutterWindow() {}
bool FlutterWindow::OnCreate() {
if (!Win32Window::OnCreate()) {
return false;
}
RECT frame = GetClientArea();
// The size here must match the window dimensions to avoid unnecessary surface
// creation / destruction in the startup path.
flutter_controller_ = std::make_unique(
frame.right - frame.left, frame.bottom - frame.top, project_);
// Ensure that basic setup of the controller was successful.
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
return false;
}
RegisterPlugins(flutter_controller_->engine());
SetChildContent(flutter_controller_->view()->GetNativeWindow());
flutter_controller_->engine()->SetNextFrameCallback([&]() {
this->Show();
});
// Flutter can complete the first frame before the "show window" callback is
// registered. The following call ensures a frame is pending to ensure the
// window is shown. It is a no-op if the first frame hasn't completed yet.
flutter_controller_->ForceRedraw();
return true;
}
void FlutterWindow::OnDestroy() {
if (flutter_controller_) {
flutter_controller_ = nullptr;
}
Win32Window::OnDestroy();
}
LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
// Give Flutter, including plugins, an opportunity to handle window messages.
if (flutter_controller_) {
std::optional result =
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
lparam);
if (result) {
return *result;
}
}
switch (message) {
case WM_FONTCHANGE:
flutter_controller_->engine()->ReloadSystemFonts();
break;
}
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}
================================================
FILE: examples/flutter_integration_tests/windows/runner/flutter_window.h
================================================
#ifndef RUNNER_FLUTTER_WINDOW_H_
#define RUNNER_FLUTTER_WINDOW_H_
#include
#include
#include
#include "win32_window.h"
// A window that does nothing but host a Flutter view.
class FlutterWindow : public Win32Window {
public:
// Creates a new FlutterWindow hosting a Flutter view running |project|.
explicit FlutterWindow(const flutter::DartProject& project);
virtual ~FlutterWindow();
protected:
// Win32Window:
bool OnCreate() override;
void OnDestroy() override;
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
LPARAM const lparam) noexcept override;
private:
// The project to run.
flutter::DartProject project_;
// The Flutter instance hosted by this window.
std::unique_ptr flutter_controller_;
};
#endif // RUNNER_FLUTTER_WINDOW_H_
================================================
FILE: examples/flutter_integration_tests/windows/runner/main.cpp
================================================
#include
#include
#include
#include "flutter_window.h"
#include "utils.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) {
// Attach to console when present (e.g., 'flutter run') or create a
// new console when running with a debugger.
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
CreateAndAttachConsole();
}
// Initialize COM, so that it is available for use in the library and/or
// plugins.
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
flutter::DartProject project(L"data");
std::vector command_line_arguments =
GetCommandLineArguments();
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.Create(L"flutter_integration_tests", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);
::MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::CoUninitialize();
return EXIT_SUCCESS;
}
================================================
FILE: examples/flutter_integration_tests/windows/runner/resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Runner.rc
//
#define IDI_APP_ICON 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
================================================
FILE: examples/flutter_integration_tests/windows/runner/runner.exe.manifest
================================================
PerMonitorV2
================================================
FILE: examples/flutter_integration_tests/windows/runner/utils.cpp
================================================
#include "utils.h"
#include
#include
#include
#include
#include
void CreateAndAttachConsole() {
if (::AllocConsole()) {
FILE *unused;
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
_dup2(_fileno(stdout), 1);
}
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
_dup2(_fileno(stdout), 2);
}
std::ios::sync_with_stdio();
FlutterDesktopResyncOutputStreams();
}
}
std::vector GetCommandLineArguments() {
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
int argc;
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
if (argv == nullptr) {
return std::vector();
}
std::vector command_line_arguments;
// Skip the first argument as it's the binary name.
for (int i = 1; i < argc; i++) {
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
}
::LocalFree(argv);
return command_line_arguments;
}
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
if (utf16_string == nullptr) {
return std::string();
}
unsigned int target_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
-1, nullptr, 0, nullptr, nullptr)
-1; // remove the trailing null character
int input_length = (int)wcslen(utf16_string);
std::string utf8_string;
if (target_length == 0 || target_length > utf8_string.max_size()) {
return utf8_string;
}
utf8_string.resize(target_length);
int converted_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
input_length, utf8_string.data(), target_length, nullptr, nullptr);
if (converted_length == 0) {
return std::string();
}
return utf8_string;
}
================================================
FILE: examples/flutter_integration_tests/windows/runner/utils.h
================================================
#ifndef RUNNER_UTILS_H_
#define RUNNER_UTILS_H_
#include
#include
// Creates a console for the process, and redirects stdout and stderr to
// it for both the runner and the Flutter library.
void CreateAndAttachConsole();
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
// encoded in UTF-8. Returns an empty std::string on failure.
std::string Utf8FromUtf16(const wchar_t* utf16_string);
// Gets the command line arguments passed in as a std::vector,
// encoded in UTF-8. Returns an empty std::vector on failure.
std::vector GetCommandLineArguments();
#endif // RUNNER_UTILS_H_
================================================
FILE: examples/flutter_integration_tests/windows/runner/win32_window.cpp
================================================
#include "win32_window.h"
#include
#include
#include "resource.h"
namespace {
/// Window attribute that enables dark mode window decorations.
///
/// Redefined in case the developer's machine has a Windows SDK older than
/// version 10.0.22000.0.
/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
/// Registry key for app theme preference.
///
/// A value of 0 indicates apps should use dark mode. A non-zero or missing
/// value indicates apps should use light mode.
constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
// The number of Win32Window objects that currently exist.
static int g_active_window_count = 0;
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
// Scale helper to convert logical scaler values to physical using passed in
// scale factor
int Scale(int source, double scale_factor) {
return static_cast(source * scale_factor);
}
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
// This API is only needed for PerMonitor V1 awareness mode.
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
HMODULE user32_module = LoadLibraryA("User32.dll");
if (!user32_module) {
return;
}
auto enable_non_client_dpi_scaling =
reinterpret_cast(
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
if (enable_non_client_dpi_scaling != nullptr) {
enable_non_client_dpi_scaling(hwnd);
}
FreeLibrary(user32_module);
}
} // namespace
// Manages the Win32Window's window class registration.
class WindowClassRegistrar {
public:
~WindowClassRegistrar() = default;
// Returns the singleton registrar instance.
static WindowClassRegistrar* GetInstance() {
if (!instance_) {
instance_ = new WindowClassRegistrar();
}
return instance_;
}
// Returns the name of the window class, registering the class if it hasn't
// previously been registered.
const wchar_t* GetWindowClass();
// Unregisters the window class. Should only be called if there are no
// instances of the window.
void UnregisterWindowClass();
private:
WindowClassRegistrar() = default;
static WindowClassRegistrar* instance_;
bool class_registered_ = false;
};
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
const wchar_t* WindowClassRegistrar::GetWindowClass() {
if (!class_registered_) {
WNDCLASS window_class{};
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
window_class.lpszClassName = kWindowClassName;
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = GetModuleHandle(nullptr);
window_class.hIcon =
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
window_class.hbrBackground = 0;
window_class.lpszMenuName = nullptr;
window_class.lpfnWndProc = Win32Window::WndProc;
RegisterClass(&window_class);
class_registered_ = true;
}
return kWindowClassName;
}
void WindowClassRegistrar::UnregisterWindowClass() {
UnregisterClass(kWindowClassName, nullptr);
class_registered_ = false;
}
Win32Window::Win32Window() {
++g_active_window_count;
}
Win32Window::~Win32Window() {
--g_active_window_count;
Destroy();
}
bool Win32Window::Create(const std::wstring& title,
const Point& origin,
const Size& size) {
Destroy();
const wchar_t* window_class =
WindowClassRegistrar::GetInstance()->GetWindowClass();
const POINT target_point = {static_cast(origin.x),
static_cast(origin.y)};
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
double scale_factor = dpi / 96.0;
HWND window = CreateWindow(
window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
nullptr, nullptr, GetModuleHandle(nullptr), this);
if (!window) {
return false;
}
UpdateTheme(window);
return OnCreate();
}
bool Win32Window::Show() {
return ShowWindow(window_handle_, SW_SHOWNORMAL);
}
// static
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
if (message == WM_NCCREATE) {
auto window_struct = reinterpret_cast(lparam);
SetWindowLongPtr(window, GWLP_USERDATA,
reinterpret_cast(window_struct->lpCreateParams));
auto that = static_cast(window_struct->lpCreateParams);
EnableFullDpiSupportIfAvailable(window);
that->window_handle_ = window;
} else if (Win32Window* that = GetThisFromHandle(window)) {
return that->MessageHandler(window, message, wparam, lparam);
}
return DefWindowProc(window, message, wparam, lparam);
}
LRESULT
Win32Window::MessageHandler(HWND hwnd,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
switch (message) {
case WM_DESTROY:
window_handle_ = nullptr;
Destroy();
if (quit_on_close_) {
PostQuitMessage(0);
}
return 0;
case WM_DPICHANGED: {
auto newRectSize = reinterpret_cast(lparam);
LONG newWidth = newRectSize->right - newRectSize->left;
LONG newHeight = newRectSize->bottom - newRectSize->top;
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
return 0;
}
case WM_SIZE: {
RECT rect = GetClientArea();
if (child_content_ != nullptr) {
// Size and position the child window.
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, TRUE);
}
return 0;
}
case WM_ACTIVATE:
if (child_content_ != nullptr) {
SetFocus(child_content_);
}
return 0;
case WM_DWMCOLORIZATIONCOLORCHANGED:
UpdateTheme(hwnd);
return 0;
}
return DefWindowProc(window_handle_, message, wparam, lparam);
}
void Win32Window::Destroy() {
OnDestroy();
if (window_handle_) {
DestroyWindow(window_handle_);
window_handle_ = nullptr;
}
if (g_active_window_count == 0) {
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
}
}
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
return reinterpret_cast(
GetWindowLongPtr(window, GWLP_USERDATA));
}
void Win32Window::SetChildContent(HWND content) {
child_content_ = content;
SetParent(content, window_handle_);
RECT frame = GetClientArea();
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
frame.bottom - frame.top, true);
SetFocus(child_content_);
}
RECT Win32Window::GetClientArea() {
RECT frame;
GetClientRect(window_handle_, &frame);
return frame;
}
HWND Win32Window::GetHandle() {
return window_handle_;
}
void Win32Window::SetQuitOnClose(bool quit_on_close) {
quit_on_close_ = quit_on_close;
}
bool Win32Window::OnCreate() {
// No-op; provided for subclasses.
return true;
}
void Win32Window::OnDestroy() {
// No-op; provided for subclasses.
}
void Win32Window::UpdateTheme(HWND const window) {
DWORD light_mode;
DWORD light_mode_size = sizeof(light_mode);
LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
kGetPreferredBrightnessRegValue,
RRF_RT_REG_DWORD, nullptr, &light_mode,
&light_mode_size);
if (result == ERROR_SUCCESS) {
BOOL enable_dark_mode = light_mode == 0;
DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
&enable_dark_mode, sizeof(enable_dark_mode));
}
}
================================================
FILE: examples/flutter_integration_tests/windows/runner/win32_window.h
================================================
#ifndef RUNNER_WIN32_WINDOW_H_
#define RUNNER_WIN32_WINDOW_H_
#include
#include
#include
#include
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
// inherited from by classes that wish to specialize with custom
// rendering and input handling
class Win32Window {
public:
struct Point {
unsigned int x;
unsigned int y;
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
};
struct Size {
unsigned int width;
unsigned int height;
Size(unsigned int width, unsigned int height)
: width(width), height(height) {}
};
Win32Window();
virtual ~Win32Window();
// Creates a win32 window with |title| that is positioned and sized using
// |origin| and |size|. New windows are created on the default monitor. Window
// sizes are specified to the OS in physical pixels, hence to ensure a
// consistent size this function will scale the inputted width and height as
// as appropriate for the default monitor. The window is invisible until
// |Show| is called. Returns true if the window was created successfully.
bool Create(const std::wstring& title, const Point& origin, const Size& size);
// Show the current window. Returns true if the window was successfully shown.
bool Show();
// Release OS resources associated with window.
void Destroy();
// Inserts |content| into the window tree.
void SetChildContent(HWND content);
// Returns the backing Window handle to enable clients to set icon and other
// window properties. Returns nullptr if the window has been destroyed.
HWND GetHandle();
// If true, closing this window will quit the application.
void SetQuitOnClose(bool quit_on_close);
// Return a RECT representing the bounds of the current client area.
RECT GetClientArea();
protected:
// Processes and route salient window messages for mouse handling,
// size change and DPI. Delegates handling of these to member overloads that
// inheriting classes can handle.
virtual LRESULT MessageHandler(HWND window,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept;
// Called when CreateAndShow is called, allowing subclass window-related
// setup. Subclasses should return false if setup fails.
virtual bool OnCreate();
// Called when Destroy is called.
virtual void OnDestroy();
private:
friend class WindowClassRegistrar;
// OS callback called by message pump. Handles the WM_NCCREATE message which
// is passed when the non-client area is being created and enables automatic
// non-client DPI scaling so that the non-client area automatically
// responds to changes in DPI. All other messages are handled by
// MessageHandler.
static LRESULT CALLBACK WndProc(HWND const window,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept;
// Retrieves a class instance pointer for |window|
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
// Update the window frame's theme to match the system theme.
static void UpdateTheme(HWND const window);
bool quit_on_close_ = false;
// window handle for top level window.
HWND window_handle_ = nullptr;
// window handle for hosted content.
HWND child_content_ = nullptr;
};
#endif // RUNNER_WIN32_WINDOW_H_
================================================
FILE: examples/multiplatform/analysis_options.yaml
================================================
# https://dart.dev/guides/language/analysis-options
include: package:lints/recommended.yaml
================================================
FILE: examples/multiplatform/db/db.dart
================================================
import 'package:sqlite3/common.dart' show CommonDatabase;
import 'sqlite3/sqlite3.dart' show openSqliteDb;
late CommonDatabase sqliteDb;
Future openDb() async {
sqliteDb = await openSqliteDb();
final dbVersion = sqliteDb
.select('PRAGMA user_version')
.first['user_version'];
print('DB version: $dbVersion');
if (dbVersion == 0) {
sqliteDb.execute('''
BEGIN;
-- TODO
PRAGMA user_version = 1;
COMMIT;
''');
}
}
================================================
FILE: examples/multiplatform/db/sqlite3/native.dart
================================================
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart'
show getApplicationDocumentsDirectory;
import 'package:sqlite3/common.dart' show CommonDatabase;
import 'package:sqlite3/sqlite3.dart' show sqlite3;
Future openSqliteDb() async {
final docsDir = await getApplicationDocumentsDirectory();
final filename = path.join(docsDir.path, 'my_app.db');
return sqlite3.open(filename);
}
================================================
FILE: examples/multiplatform/db/sqlite3/sqlite3.dart
================================================
export 'unsupported.dart'
if (dart.library.js) 'web.dart'
if (dart.library.ffi) 'native.dart'
show openSqliteDb;
================================================
FILE: examples/multiplatform/db/sqlite3/unsupported.dart
================================================
import 'package:sqlite3/common.dart' show CommonDatabase;
Future openSqliteDb() async {
throw UnsupportedError('Sqlite3 is unsupported on this platform.');
}
================================================
FILE: examples/multiplatform/db/sqlite3/web.dart
================================================
import 'package:sqlite3/common.dart' show CommonDatabase;
import 'package:sqlite3/wasm.dart' show IndexedDbFileSystem, WasmSqlite3;
Future openSqliteDb() async {
const name = 'my_app';
// Please download `sqlite3.wasm` from https://github.com/simolus3/sqlite3.dart/releases
// into the `web/` dir of your Flutter app. See `README.md` for details.
final sqlite = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3.wasm'));
final fileSystem = await IndexedDbFileSystem.open(dbName: name);
sqlite.registerVirtualFileSystem(fileSystem, makeDefault: true);
return sqlite.open(name);
}
================================================
FILE: examples/multiplatform/main.dart
================================================
import 'db/db.dart' show openDb;
Future main() async {
// WidgetsFlutterBinding.ensureInitialized();
await openDb();
// runApp(const App());
}
================================================
FILE: examples/multiplatform/pubspec.yaml
================================================
name: sqlite3_multiplatform_example
description: Uses common interface to `sqlite3` on web and native platforms.
version: 0.1.0
publish_to: 'none'
resolution: workspace
environment:
sdk: "^3.9.0"
dependencies:
path: ^1.8.3
path_provider: ^2.1.1
sqlite3: ^3.0.0-0
dev_dependencies:
lints: ^6.0.0
================================================
FILE: examples/pubspec.yaml
================================================
name: pkg_sqlite3_examples_workspace
publish_to: none
environment:
sdk: ^3.10.0-0
workspace:
- flutter_integration_tests
- multiplatform
dependency_overrides:
sqlite3:
path: ../sqlite3
sqlite3_connection_pool:
path: ../sqlite3_connection_pool
================================================
FILE: legacy/sqlcipher_flutter_libs/CHANGELOG.md
================================================
## 0.7.0+eol
- Deprecate this package. Starting from versions 3.x of the `sqlite3` package, `sqlcipher_flutter_libs` is no longer necessary.
See [these notes](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md) for details on how to upgrade.
This version removes all code from this package. It can be used to require that the old Flutter-specific scripts are no longer
used.
## 0.6.8
- Update SQLCipher to version 4.10.0.
## 0.6.7
- Update SQLCipher to version 4.9.0.
## 0.6.6
- Update SQLCipher to version 4.8.0.
## 0.6.5
- Update SQLCipher to version 4.6.1.
- Fix compilation error with Swift 6 on iOS.
## 0.6.4
- Fix compilation on Android by upgrading `compileSdk` version.
## 0.6.3
- Enable extension loading on Windows and Linux to match the compile options
used on other platforms.
## 0.6.2
- Update SQLCipher to `4.5.7`.
## 0.6.1
- Update SQLCipher to `4.5.6`.
- For Linux builds, you can now include `set(OPENSSL_USE_STATIC_LIBS OFF)` in your
`CMakeLists.txt` to link OpenSSL dynamically.
## 0.6.0
- Update SQLCipher to `4.5.5` (https://www.zetetic.net/blog/2023/08/31/sqlcipher-4.5.5-release/)
- On Android, migrate from `android-database-sqlcipher` to `sqlcipher-android`.
If you use SQLCipher APIs in your native Android platform code, consider migrating as well and
follow the [migration guide](https://www.zetetic.net/sqlcipher/sqlcipher-for-android-migration/).
## 0.5.7
- Consistently compile `SQLCipher` with `SQLITE_THREADSAFE=1` on all supported platforms.
## 0.5.6
- Upgrade `SQLCipher` to version `4.5.4` (https://www.zetetic.net/blog/2023/04/27/sqlcipher-4.5.4-release).
## 0.5.5
- Support Android projects built with Gradle 8.
## 0.5.4
- Fix building `SQLCipher` on Windows - see the readme for more details.
## 0.5.3
- Upgrade `SQLCipher` to version `4.5.2`.
## 0.5.2
- This package now works on Windows and Linux too!
- Upgrade `SQLCipher` to version `4.5.1`
## 0.5.1
- Upgrade `SQLCipher` to version `4.5.0`
## 0.5.0
- Initial pub release to match the version of `sqlite3_flutter_libs`
================================================
FILE: legacy/sqlcipher_flutter_libs/LICENSE
================================================
sqlcipher_flutter_libs
MIT License
Copyright (c) 2020 Simon Binder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
OpenSSL
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
SQLCipher
Copyright (c) 2008-2020 Zetetic LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the ZETETIC LLC nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: legacy/sqlcipher_flutter_libs/README.md
================================================
# sqlcipher_flutter_libs
> [!CAUTION]
> This package relates to version 2.x of `package:sqlite3`, and is obsolete after upgrading.
> Please see [notes on upgrading](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md)
> and remove this package from your dependencies after adopting version 3.x of `package:sqlite3`.
Starting from version `0.7.0`, this package no longer does anything.
Other libraries can depend on version `0.7.0` after migrating to version 3.x of `package:sqlite3` to
ensure that an app does not use the old Flutter-specific SQLite build scripts from `0.6.x` and older.
================================================
FILE: legacy/sqlcipher_flutter_libs/lib/sqlcipher_flutter_libs.dart
================================================
/// This package does not do anything.
///
/// This package used to provide SQLCipher libraries for use with version 2.x of
/// the `sqlite3` package. Starting from version 3.x, this separate package is
/// no longer necessary.
///
/// Please see the [documentation on upgrading](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md).
/// The reason for keeping this package around is that other packages can depend
/// on version `0.6.0` after upgrading to `package:sqlite3` version 3.x. This
/// ensures that the old Flutter build scripts are guaranteed to not be part of
/// the build.
library sqlcipher_flutter_libs;
================================================
FILE: legacy/sqlcipher_flutter_libs/pubspec.yaml
================================================
name: sqlcipher_flutter_libs
description: "Not used anymore, update to version 3.x of package:sqlite3 instead"
version: 0.7.0+eol
homepage: https://github.com/simolus3/sqlite3.dart/tree/main/legacy/sqlcipher_flutter_libs
issue_tracker: https://github.com/simolus3/sqlite3.dart/issues
resolution: workspace
environment:
sdk: ">=3.10.0 <4.0.0"
================================================
FILE: legacy/sqlite3_flutter_libs/CHANGELOG.md
================================================
## 0.6.0+eol
- Deprecate this package. Starting from versions 3.x of the `sqlite3` package, `sqlite3_flutter_libs` is no longer necessary.
See [these notes](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md) for details on how to upgrade.
This version removes all code from this package. It can be used to require that the old Flutter-specific scripts are no longer
used.
## 0.5.41
- Upgrade sqlite to version `3.51.1`.
## 0.5.40
- iOS and macOS: Compile to a shared library when SwiftPM is used to avoid
conflicts with the SQLite library from Apple SDKs.
## 0.5.39
- Upgrade sqlite to version `3.50.4`.
## 0.5.38
- Enable pre-update hooks and the session extension.
## 0.5.37
- Upgrade sqlite to version `3.50.3`.
## 0.5.36
- Update Android Gradle buildscript to avoid compiler warnings on recent JDKs.
## 0.5.35
- Upgrade sqlite to version `3.50.2`.
## 0.5.34
- Upgrade sqlite to version `3.50.1`.
## 0.5.33
- Upgrade sqlite to version `3.49.2`.
## 0.5.32
- Enable builtin math functions.
## 0.5.31
- Upgrade sqlite to version `3.49.1`.
## 0.5.30
- Upgrade sqlite to version `3.49.0`.
## 0.5.29+1
- Android: Upgrade `compileSdkVersion` to `35`.
## 0.5.29
- Upgrade sqlite to version `3.48.0`.
## 0.5.28
- Upgrade sqlite to version `3.47.2`.
## 0.5.27
- Upgrade sqlite to version `3.47.1`.
- In addition to CocoaPods, this package now supports the Swift Package Manager
for iOS and macOS builds.
## 0.5.26
- Upgrade sqlite to version `3.47.0`.
## 0.5.25
- Support 16KiB page sizes on Android 15.
## 0.5.24
- Enable the [dbstat](https://www.sqlite.org/dbstat.html) compile-time option.
## 0.5.23
- Enable extension loading on Windows and Linux to match the compile options
used on other platforms.
## 0.5.22
- Upgrade sqlite to version `3.46.0`.
## 0.5.21
- Upgrade sqlite to version `3.45.3`.
## 0.5.20
- Upgrade sqlite to version `3.45.1`.
## 0.5.19+1
- Upgrade sqlite to version `3.45.0`.
## 0.5.18
- Upgrade sqlite to version `3.44.0`.
## 0.5.17
- Upgrade sqlite to version `3.43.1`.
## 0.5.16
- Upgrade sqlite to version `3.43.0`.
## 0.5.15
- Upgrade sqlite to version `3.41.2`.
## 0.5.14
- Support Android projects built with Gradle 8.
## 0.5.13
- Upgrade sqlite to version `3.41.0`.
## 0.5.12
- Upgrade sqlite to version `3.40.0`.
## 0.5.11+1
- Upgrade sqlite3 to version `3.39.4`.
- Fix a compilation warning on Windows.
- Stop bundling `spellfix1` on platforms where that was still the case by
default.
## 0.5.10
- Upgrade sqlite to version `3.39.3`.
- Consistently compile sqlite3 with `-DSQLITE_THREADSAFE=1` on all platforms.
## 0.5.9
- Upgrade sqlite to version `3.39.2`.
## 0.5.8
- Upgrade sqlite to version `3.39.0`
## 0.5.7
- Update sqlite to version `3.38.5`
## 0.5.6
- Update sqlite to version `3.38.3`
## 0.5.5
- Update sqlite to version `3.38.2`
- Linux is now supported without additional setup.
- Windows is now supported without additional setup.
## 0.5.4
- Update sqlite to version `3.38.0`
## 0.5.3
- Update sqlite to version `3.37.2`
## 0.5.2
- Update sqlite to version `3.37.0`
## 0.5.1
- Update sqlite to version `3.36.0`
## 0.5.0
- Also include sqlite when building for macOS
## 0.4.3
- Upgrade to sqlite3 version 3.35.4 on iOS as well
## 0.4.2
- Upgrade to sqlite3 version 3.35.4 on Android
## 0.4.1
- Raise minimum SDK constraint to Dart 2.12
## 0.4.0
`0.4.0+1` fixes an issue causing sqlite3 libraries to be unavailable in the
compiled app. Please don't use `0.4.0`!
- Migrate native Android dependencies away from Bintray
## 0.3.0
- Add workaround for an apparent loader bug in Android 6.0.1 (see readme for details)
## 0.2.0
- Use ObjectiveC instead of Swift for the iOS plugin
## 0.1.0
- Add an empty Dart library to improve the pub score
## 0.0.1
- Initial release
================================================
FILE: legacy/sqlite3_flutter_libs/LICENSE
================================================
MIT License
Copyright (c) 2020 Simon Binder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: legacy/sqlite3_flutter_libs/README.md
================================================
# sqlite3_flutter_libs
> [!CAUTION]
> This package relates to version 2.x of `package:sqlite3`, and is obsolete after upgrading.
> Please see [notes on upgrading](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md)
> and remove this package from your dependencies after adopting version 3.x of `package:sqlite3`.
Starting from version `0.6.0`, this package no longer does anything.
Other libraries can depend on version `0.6.0` after migrating to version 3.x of `package:sqlite3` to
ensure that an app does not use the old Flutter-specific SQLite build scripts from `0.5.x` and older.
================================================
FILE: legacy/sqlite3_flutter_libs/lib/sqlite3_flutter_libs.dart
================================================
/// This package does not do anything.
///
/// This package used to provide SQLite libraries for use with version 2.x of
/// the `sqlite3` package. Starting from version 3.x, this separate package is
/// no longer necessary.
///
/// Please see the [documentation on upgrading](https://github.com/simolus3/sqlite3.dart/blob/main/UPGRADING_TO_V3.md).
/// The reason for keeping this package around is that other packages can depend
/// on version `0.6.0` after upgrading to `package:sqlite3` version 3.x. This
/// ensures that the old Flutter build scripts are guaranteed to not be part of
/// the build.
library sqlite3_flutter_libs;
================================================
FILE: legacy/sqlite3_flutter_libs/pubspec.yaml
================================================
name: sqlite3_flutter_libs
description: "Not used anymore, update to version 3.x of package:sqlite3 instead"
version: 0.6.0+eol
homepage: https://github.com/simolus3/sqlite3.dart/tree/main/legacy/sqlite3_flutter_libs
issue_tracker: https://github.com/simolus3/sqlite3.dart/issues
resolution: workspace
environment:
sdk: ">=3.10.0 <4.0.0"
================================================
FILE: native_tests/all_native_tests.dart
================================================
import 'package:test/test.dart';
import '../sqlite3/test/ffi/common_database_test.dart' as common_database_test;
import '../sqlite3/test/ffi/database_test.dart' as database_test;
import '../sqlite3/test/ffi/ffi_test.dart' as ffi_test;
import '../sqlite3/test/ffi/prepared_statement_test.dart'
as prepared_statement_test;
import '../sqlite3/test/ffi/sqlite3_test.dart' as sqlite3_test;
import '../sqlite3/test/ffi/vfs_test.dart' as vfs_test;
import '../sqlite3_connection_pool/test/pool_test.dart' as pool_test;
import '../sqlite3_test/test/sqlite3_test_test.dart' as sqlite3_test_test;
/// Runs all native tests.
///
/// We aot-compile this file to run tests with different sanitizers.
void main() {
group('package:sqlite3', () {
group('common_database_test.dart', common_database_test.main);
group('database_test.dart', database_test.main);
group('ffi_test.dart', ffi_test.main);
group('prepared_statement_test.dart', prepared_statement_test.main);
group('sqlite3_test.dart', sqlite3_test.main);
group('vfs_test.dart', vfs_test.main);
});
group('package:sqlite3_connection_pool', () {
pool_test.main();
});
group('package:sqlite3_test', () {
sqlite3_test_test.main();
});
}
================================================
FILE: native_tests/analysis_options.yaml
================================================
include: package:lints/recommended.yaml
analyzer:
language:
strict-casts: true
strict-raw-types: true
================================================
FILE: native_tests/ignorelist.txt
================================================
src:*/sqlite3.c
================================================
FILE: native_tests/pubspec.yaml
================================================
name: native_tests
description: Helper package to test other packages in this workspace in aot builds.
publish_to: none
resolution: workspace
environment:
sdk: ^3.11.0
topics:
- sql
- database
- ffi
- sqlite
dependencies:
sqlite3:
sqlite3_test:
sqlite3_connection_pool:
test: ^1.31.0
path: ^1.9.1
args: ^2.7.0
================================================
FILE: native_tests/run.dart
================================================
import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as p;
/// Runs `all_native_tests.dart` as a single AOT-compiled executable.
///
/// To run AOT-compiled tests without sanitizers, use `dart run run.dart`.
///
/// To run tests with a sanitizer, use `dart run.dart --sanitizer $sanitizer`,
/// where `$sanitizer` is one of `asan`, `msan` or `tsan`. Note that sanitizers
/// are only supported on X64 Linux hosts.
///
/// Running tests with sanitizers also requires an instrumented build of SQLite
/// and the pool helper library. Either obtain that from the `sqlite3-sanitized`
/// asset uploaded to CI runs on GitHub assets, or use:
///
/// 1. tool/download_sqlite.dart
/// 2. tool/build_with_sanitizers.dart (requires clang and LLVM).
/// 3. tool/build_linux_sanitizer.sh in sqlite3_connection_pool.
void main(List args) async {
final parser = ArgParser(allowTrailingOptions: false);
parser.addOption('sanitizer', allowed: ['asan', 'msan', 'tsan']);
final result = parser.parse(args);
final sanitizer = result.option('sanitizer');
final dir = await Directory.systemTemp.createTemp('pkg-sqlite3-test');
final aotPath = p.join(dir.path, 'test.aot');
final assetsConfig = await _createNativeAssetsConfig(dir, sanitizer);
try {
print('AOT-compiling tests');
final result = await Process.run(Platform.executable, [
'compile',
'aot-snapshot',
'all_native_tests.dart',
'--output',
aotPath,
if (sanitizer != null) '--target-sanitizer=$sanitizer',
'--extra-gen-kernel-options=--native-assets=${assetsConfig.path}',
]);
if (result.exitCode != 0 || !await File(aotPath).exists()) {
throw '''
could not compile test script
exitCode: ${result.exitCode}
stdout: ${result.stdout}
stderr: ${result.stderr}
''';
}
var runtimeName = 'dartaotruntime';
if (sanitizer != null) runtimeName += '_$sanitizer';
if (Platform.isWindows) runtimeName += '.exe';
print('Running with $runtimeName');
final runtime = p.join(p.dirname(Platform.resolvedExecutable), runtimeName);
final process = await Process.start(runtime, [
aotPath,
], mode: ProcessStartMode.inheritStdio);
final exit = await process.exitCode;
if (exit != 0) {
throw 'Expected exit code 0, got $exit';
}
} finally {
await dir.delete(recursive: true);
}
}
Future _createNativeAssetsConfig(
Directory tmpForRun,
String? sanitizer,
) async {
if (sanitizer == null) {
final file = File('.dart_tool/native_assets.yaml');
if (!await file.exists()) {
throw 'Expected $file to exist, are you using dart run?';
}
return file;
}
final name = switch (sanitizer) {
'asan' => 'address',
'msan' => 'memory',
'tsan' => 'thread',
_ => throw AssertionError(),
};
final sqliteFile = p.normalize(
p.absolute('../sqlite-sanitized', 'sqlite3.san_$name.so'),
);
final poolFile = p.normalize(
p.absolute(
'../sqlite-sanitized',
'libsqlite3_connection_pool.$name.san.so',
),
);
final yaml =
'''
format-version: [1, 0, 0]
native-assets:
linux_x64:
"package:sqlite3/src/ffi/libsqlite3.g.dart":
- absolute
- "$sqliteFile"
"package:sqlite3_connection_pool/sqlite3_connection_pool.dart":
- absolute
- "$poolFile"
''';
final file = File(p.join(tmpForRun.path, 'assets.yaml'));
await file.writeAsString(yaml);
return file;
}
================================================
FILE: pubspec.yaml
================================================
name: _
publish_to: none
environment:
sdk: ^3.6.0
dependencies:
path: ^1.9.1
crypto: ^3.0.6
collection: ^1.19.1
file: ^7.0.1
pool: ^1.5.2
hooks: ^1.0.0
workspace:
- sqlite3
- sqlite3/example/custom_extension
- sqlite3_connection_pool
- sqlite3_web
- sqlite3_test
- native_tests
- legacy/sqlcipher_flutter_libs
- legacy/sqlite3_flutter_libs
================================================
FILE: sqlite3/CHANGELOG.md
================================================
## 3.3.2 (unreleased)
- Support `native_toolchain_c` versions `0.18.x`.
## 3.3.1
- Avoid memory leaks when `tempDirectory` is set multiple times.
- Update to SQLite 3.53.0 and SQLite3 Multiple Ciphers version 2.3.3.
## 3.3.0
- Web: Add `WasmModuleLoader` API to customize how WebAssembly modules are loaded.
- Hook: Improve error message for failing downloads.
## 3.2.0
- Add `package:sqlite3/unstable/ffi_bindings.dart` providing low-level access to generated `libsqlite3` bindings.
- Add `PreparedStatement.leak` to transfer ownership of a prepared statement into native code.
- Add `Database.statementFromPointer`, which can be used to access a statement prepared in native code from Dart.
## 3.1.7
- Update to sqlite version 3.52.0.
## 3.1.6
- Expose the address of `sqlite3_close_v2` as static field on `Sqlite3` class.
- Allow wrapping databases without closing them with the `borrowed` parameter
on `Sqlite3.fromPointer`.
- Add `Database.leak()`, which extracts a `sqlite3*` pointer and disables
finalizers.
## 3.1.5
- Build hook: Ensure we use consistent filenames to fix issues on Apple platforms.
## 3.1.4
- Build hook: Fix paths not resolving on Windows when building from source.
## 3.1.3
- Update to SQLite version 3.51.2.
## 3.1.2
- `Database.select()` will now throw an exception if the SQL string contains
invalid text after the first statement.
- Build hook: Support OS-specific names when using `source: system`.
## 3.1.1
- Hooks: Respect `HTTPS_PROXY` and related environment variables when
downloading SQLite (requires Dart 3.11 or later).
- Update SQLite to version 3.51.1.
## 3.1.0
- Build hook: Allow using `name` key with `source: system` to load SQLite
libraries under a different name (e.g. `name: sqlcipher` to load SQLCipher).
- Wasm: Fix an internal memory corruption issue when more than 16 Dart handles
are referenced from C.
## 3.0.1
- Build hook: Use clang from XCode when pre-compiling SQLite for iOS and macOS.
## 3.0.0
- __Breaking change__: Use [build hooks](https://dart.dev/tools/hooks) to load
SQLite instead of `DynamicLibrary`.
- The SQLite library can only be customized with user defines.
- You should drop your dependencies on `sqlite3_flutter_libs` and
`sqlcipher_flutter_libs` when upgrading.
- You can also remove dependencies on `sqlite3_native_assets`, since that
package is now part of `package:sqlite3`.
- __Breaking change__: Parameters to `SqliteException`s are now named.
- Deprecated `dispose()` on `CommonDatabase` and `CommonPreparedStatement`. Use `close()`
instead.
- On native platforms, use native finalizers to reliably clear statements and databases.
- On the web, use regular finalizers more consistently.
- Refactor binding text and blob values to reduce the chance of memory leaks.
- On the web, use `externref`s to call Dart functions from compiled WebAssembly sources.
- Add `busyHandler` setter to install a custom `sqlite3_busy_handler` on databases.
## 2.9.4
- `SimpleOpfsFileSystem`: Allow opening with `readwrite-unsafe`, which can be used to implement
multi-tab OPFS databases on Chrome with an outer locking scheme.
## 2.9.3
- Allow iterating over statements after `SQLITE_BUSY` errors.
## 2.9.2
- Fix a bug introduced in version `2.9.1` where the SQLite framework provided by
`sqlite3_flutter_libs` would not load correctly on iOS.
## 2.9.1
- Check for error codes when binding values to prepared statements.
- Flutter: Fix loading SwiftPM libraries from `sqlite3_flutter_libs`.
## 2.9.0
- Add `CommonDatabase.updatesSync`, a synchronous variant of the updates stream.
## 2.8.0
- Support creating changesets and patchsets via the session extension.
- Add the `SubtypedValue` extension type to allow returning values with a subtype.
- Add the `subtypeOf` method to the `SqliteArguments` interface passed to user-defined
functions. It returns the subtype assigned to an argument.
- Web: Refactor SQLite bindings to make them easier for compilers to optimize.
## 2.7.7
- `jsonb` codec: Refuse to encode NaN values since recent SQLite versions
reject them.
## 2.7.6
- Export `package:sqlite3/native_assets.dart`, making it easier for libraries
to support both the regular `sqlite3` getter and the upcoming
`sqlite3NativeAssets` variant.
- Fix dereferencing null pointer when reading file names for temporary files in
native VFS implementation.
## 2.7.5
- On Windows, try loading `winsqlite3.dll` as a fallback if loading
`sqlite3.dll` fails.
## 2.7.4
- Prepare support for accessing SQLite through native assets. This is available
as a preview through `package:sqlite3_native_assets`.
## 2.7.3
- Web: Support `localtime` datetime modifier in SQLite.
- Introduce topics to dartdoc documentation.
- Report locations of syntax errors in `SqliteException`.
## 2.7.2
- Web: Fix update events not being delivered in some shared worker setups.
## 2.7.1
- Web: Fix a crash when using version `2.7.0` of this package with an older
WebAssembly bundle.
Note: Version `2.7.0` has been retracted from pub.dev for this reason.
## 2.7.0
- Add support for commit and rollback hooks as well as a predicate that can
revert transactions. Thanks to [@jackd](https://github.com/jackd)!
## 2.6.1
- Fix out-of-bound reads in the `xWrite` implementation of the OPFS-locks based
file-system implementation when writing more than 64 KiB in one operation.
- Support SQLite libraries compiled with `SQLITE_OMIT_AUTOINIT`.
## 2.6.0
- Add `SimpleOpfsFileSystem.deleteFromStorage` to delete OPFS-based file
systems.
- Add `jsonb`, a Dart `Codec` converting Dart object from and to SQLite
`JSONB` values.
- __Experimentally__ support encryption on the web through SQLite Multiple
Ciphers. The readme provides more information on how to use encryption on the
web.
## 2.5.0
- Allow registering custom virtual file systems on all platforms. Previously,
this was only supported on the web.
- IndexedDB file system: Store `ArrayBuffer`s instead of `Blob`s when it looks
like storing blobs would cause issues.
## 2.4.7
- Web: Improve performance of in-memory and IndexedDB file system implementations.
## 2.4.6
- WebAssembly: Call `_initialize` function of sqlite3 module if one is present.
- Support version 1.0.0 of `package:web`.
## 2.4.5
- Fix a bug in the OPFS-locks implementation causing a deadlock when the `xSleep`
VFS call is issued.
- Fix selecting large integers (being represented as a `BigInt` in Dart)
not working when compiled with dartdevc.
## 2.4.4
- Add a temporary workaround for [a Dart bug](https://github.com/dart-lang/sdk/issues/56064)
causing spurious exceptions when databases are closed and a debugger is attached.
## 2.4.3
- Migrate away from legacy web APIs: `dart:html`, `dart:js`, `dart:indexeddb`
and `package:js` are no longer imported from this package.
- Experimentally support being compiled to WebAssembly. Strong caveats apply,
please check [#230](https://github.com/simolus3/sqlite3.dart/issues/230)
before relying on this!
## 2.4.2
- Fix string and blob arguments to prepared statements never being
deallocated ([#225](https://github.com/simolus3/sqlite3.dart/issues/225)).
## 2.4.1+1
- Allow version `0.7.x` of the `js` package.
- Reduce size of `sqlite3.wasm` bundle by removing symbols not referenced in
Dart.
## 2.4.0
- Add `isReadOnly` and `isExplain` getters to prepared statements.
- Set `NativeCallable.keepIsolateAlive` to `false` for callables managed by
this package.
## 2.3.0
- Add the `autocommit` getter on databases wrapping `sqlite3_get_autocommit`.
- Improve the error message in the exception when opening a database fails.
## 2.2.0
- Add `updatedRows` getter to eventually replace `getUpdatedRows()` method.
- Clarify documentation on `lastInsertRowId` and `updatedRows`.
- Allow customizing the amount of pages to lock at a time in `backup`. A larger
amount will result in better backup performance.
- Use `NativeCallable`s for user-defined functions, collations and update
streams.
## 2.1.0
- Add `config` getter to `CommonDatabase` to access `sqlite3_db_config`.
## 2.0.0
- __Breaking__: The WASM implementation no longer registers a default virtual
file system. Instead, `registerVirtualFileSystem` needs to be used to add
desired file system implementations.
- __Breaking__: Fix a typo, `CommmonSqlite3` is now called `CommonSqlite3`.
- __Breaking__: Introduce class modifiers on classes of this package that aren't
meant to be extended or implemented by users.
- Add `PreparedStatement.reset()`.
- Add the `CustomStatementParameter` class which can be passed as a statement
parameter with a custom `sqlite3_bind_*` call.
- Add the `StatementParameters` class and `executeWith`/`selectWith` methods
on `CommonPreparedStatement`. They can be used to control whether values are
bound by index or by name. The `selectMap` and `executeMap` methods have
been deprecated.
## 1.11.2
- Report correct column names for statements that have been re-compiled due to
schema changes.
## 1.11.1
- Fix user-defined functions returning text not supporting multi-byte utf8
characters.
## 1.11.0
- Add `WasmSqlite3.loadFromUrl` which uses a streaming `fetch()` request to
load the sqlite3 WASM binary.
- Add `OpfsFileSystem`, a file system implementation for the WASM library that
is based on the synchronous File System Access API.
- The WASM version of sqlite3 used by this library is now compiled with `-Oz`
instead of `-Ofast`.
## 1.10.1
- Fix a regression introduced in 1.10.0 causing crashes when SQL statements
containing non-ASCII characters are prepared.
## 1.10.0
- Rewrite the implementation to allow more code reuse between `dart:ffi` and
the WASM-based web implementation.
## 1.9.3
- Provide more information about the source of sqlite exceptions.
- Fix prepared statements without parameters not being reused properly.
## 1.9.2
- Include parameters when throwing an exception in prepared statements.
## 1.9.1
- Change `Row.keys` and `Row.values` to return a list.
## 1.9.0
- Add an API for sqlite3's backup API via `Database.backup()`.
- Add an API to load extensions via `sqlite3.ensureExtensionLoaded`.
## 1.8.0
- Use a `Finalizer` to automatically dispose databases and statements. As
finalizers in Dart aren't reliable, you should still make sure to call
`dispose` manually after you're done with a database or a statement.
- Avoid using generative constructors on `@staticInterop` classes.
## 1.7.2
- Optimizations in the wasm-based file system.
- Fix the `mutex` parameter not doing anything in the FFI-based implementation.
## 1.7.1
- Allow binding `BigInt`s to statements and functions. They must still be
representable as a 64-bit int, but this closes a compatibility gap between
the web and the native implementations.
- Use ABI-specific integer types internally.
## 1.7.0
- Add support for application-defined window functions. To register a custom
window function, implement `WindowFunction` and register your function with
`database.registerAggregateFunction`.
- __Breaking__ (For the experimental `package:sqlite3/wasm.dart` library):
- The IndexedDB implementation now stores data in 4k blocks instead of full files.
- Removed `IndexedDbFileSystem.load`. Use `IndexedDbFileSystem.open` instead.
- An `IndexedDbFileSystem` now stores all files, the concept of a persistence
root has been removed.
To access independent databases, use two `IndexedDbFileSystem`s with a different
database name.
## 1.6.4
- Add `FileSystem.listFiles()` to list all files in a virtual WASM file system.
## 1.6.3
- Support running `sqlite3/wasm.dart` in web workers.
## 1.6.2
- Fix `CURRENT_TIMESTAMP` not working with the WebAssembly backend.
## 1.6.1
- Better support loading sqlite3 on Linux when using `sqlite3_flutter_libs`.
## 1.6.0
- Very experimental web support, based on compiling sqlite3 to web assembly
with a custom file system implementation.
## 1.5.1
- Fix `checkNoTail` throwing for harmless whitespace or comments following a
SQL statement.
- Fix a native null-pointer dereference when calling `prepare` with a statement
exclusively containing whitespace or comments.
- Fix a potential out-of-bounds read when preparing statements.
## 1.5.0
- Add `prepareMultiple` method to prepare multiple statements from one SQL string.
- Add `selectMap` and `executeMap` on `PreparedStatement` to bind SQL parameters by
their name instead of their index.
- Add support for custom collations with `createCollation`.
## 1.4.0
- Report writes on the database through the `Database.updates` stream
- Internal: Use `ffigen` to generate native bindings
## 1.3.1
- Fix a crash with common iOS and macOS configurations.
The crash has been introduced in version 1.3.0, which should be avoided.
Please consider adding `sqlite3: ^1.3.1` to your pubspec to avoid getting the
broken version
## 1.3.0
- Add `Cursor.tableNames` and `Row.toTableColumnMap()` to obtain tables
involved in a result set.
Thanks to [@juancastillo0](https://github.com/juancastillo0)!
## 1.2.0
- Add the `selectCursor` API on `PreparedStatement` to step through a result set row by row.
- Report the causing SQL statement in exceptions
- Use a new Dart API to determine whether symbols are available
## 1.1.2
- Attempt opening sqlite3 from `DynamicLibrary.process()` on macOS
## 1.1.1
- Fix memory leak when preparing statements!
- Don't allow `execute` with arguments when the provided sql string contains
more than one argument.
## 1.1.0
- Add optional parameters to `execute`.
## 1.0.1
- Don't throw when `PreparedStatement.execute` is used on a statement returning
rows.
## 1.0.0
- Support version `1.0.0` of `package:ffi`
## 0.1.10-nullsafety.0
- Support version `0.3.0` of `package:ffi`
- Migrate library to support breaking ffi changes in Dart 2.13:
- Use `Opaque` instead of empty structs
- Use `Allocator` api
## 0.1.9-nullsafety.2
- Fix loading sqlite3 on iOS
## 0.1.9-nullsafety.1
- Migrate package to null safety
## 0.1.8
- Added the `mutex` parameter to control the serialization mode
when opening databases.
## 0.1.7
- Expose the `sqlite3_temp_directory` global variable
## 0.1.6
- Expose underlying database and statement handles
- Support opening databases from uris
## 0.1.5
- Use `sqlite3_version` to determine if `sqlite3_prepare_v3` is available
instead of catching an error.
## 0.1.4
- Use `sqlite3_prepare_v2` if `sqlite3_prepare_v3` is not available
## 0.1.3
- Lower minimum version requirement on `collection` to `^1.14.0`
## 0.1.2
- Enable extended result codes
- Expose raw rows from a `ResultSet`
## 0.1.1
- Expose the `ResultSet` class
## 0.1.0
- Initial version
================================================
FILE: sqlite3/LICENSE
================================================
MIT License
Copyright (c) 2020 Simon Binder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: sqlite3/README.md
================================================
# sqlite3
Provides Dart bindings to [SQLite](https://www.sqlite.org/index.html) via `dart:ffi`.
## Using this library
Because this library uses [hooks](https://dart.dev/tools/hooks), it bundles SQLite with
your application and doesn't require any external dependencies or build configuration.
To use it, depend on it:
```shell
dart pub add sqlite3
```
For native platforms, the basic sketch for using this library is to:
1. Import `package:sqlite3/sqlite3.dart`.
2. Use `sqlite3.open()` to open a database file, or `sqlite3.openInMemory()` to
open a temporary in-memory database.
3. Use `Database.execute` or `Database.prepare` to execute statements directly
or by preparing them first.
4. Consider closing statements or databases explicitly with `close()` once you're
done with them. `package:sqlite3` uses native finalizers to do that automatically
too, though.
For a more complete example on how to use this library, see the [example](https://pub.dev/packages/sqlite3/example).
## Supported platforms
This library provides prebuilt versions of SQLite for the following platforms:
- __Android__: `armv7a`, `aarch64`, `x86`, `x64`.
- __iOS__: `arm64` (devices), `arm64` (simulator), `x64` (simulator).
- __macOS__: `arm64`, `x64`.
- __Linux__: `armv7`, `aarch64`, `x64`, `x86`, `riscv64gc`.
- __Windows__: `aarch64`, `x64`, `x86`.
For more information, see [hook options](./doc/hook.md).
In addition to native platforms, this package supports running on the web by accessing a sqlite3
build compiled to WebAssembly.
Web support is only officially supported for `dartdevc` and `dart2js`. Support
for `dart2wasm` [is experimental and incomplete](https://github.com/simolus3/sqlite3.dart/issues/230).
For more information, see [web support](#wasm-web-support) below.
On all supported platforms, you can also use SQLite3MultipleCiphers instead of SQLite to encrypt
databases. The [hook options page](./doc/hook.md) describe this setup.
## Supported datatypes
When binding parameters to queries, the supported types are `ìnt`,
`double`, `String`, `List` (for `BLOB`) and `null`.
Result sets will use the same set of types.
On the web (but only on the web), `BigInt` is supported as well.
## WASM (web support)
This package experimentally supports being used on the web with a bit of setup.
The web version binds to a custom version of sqlite3 compiled to WebAssembly without
Emscripten or any JavaScript glue code.
Please note that stable web support for `package:sqlite3` is restricted to Dart
being compiled to JavaScript. Support for `dart2wasm` is experimental. The API
is identical, but the implementation [is severely limited](https://github.com/simolus3/sqlite3.dart/issues/230).
### Setup
To use this package on the web, you need:
- The sqlite3 library compiled as a WebAssembly module, available from the
[GitHub releases](https://github.com/simolus3/sqlite3.dart/releases) of this package.
Note that, for this package, __sqlite3 has to be compiled in a special way__.
Existing WebAssembly files from e.g. sql.js will not work with `package:sqlite3/wasm.dart`.
You can also see [this directory](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3_wasm_build)
for the build files to compile this yourself.
- A file system implementation, since websites can't by default access the host's file system.
This package provides `InMemoryFileSystem` and an `IndexedDbFileSystem` implementation.
After putting `sqlite3.wasm` under the `web/` directory of your project, you can
open and use `sqlite3` like this:
```dart
import 'package:http/http.dart' as http;
import 'package:sqlite3/common.dart';
import 'package:sqlite3/wasm.dart';
Future loadSqlite() async {
final sqlite = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3.wasm'));
final fileSystem = await IndexedDbFileSystem.open(dbName: 'my_app');
sqlite.registerVirtualFileSystem(fileSystem, makeDefault: true);
return sqlite;
}
```
The returned `WasmSqlite3` has an interface compatible to that of the standard `sqlite3` field
in `package:sqlite3/sqlite3.dart`, databases can be opened in similar ways.
An example for such web folder is in `example/web/` of this repo.
To view the example, copy a compiled `sqlite3.wasm` file to `web/sqlite3.wasm` in this directory.
Then, run `dart run build_runner serve example:8080` and visit `http://localhost:8080/web/` in a browser.
Another `../examples/multiplatform/` uses common interface to `sqlite3` on web and native platforms.
To run this example, merge its files into a Flutter app.
### Sharing code between web and a Dart VM
The `package:sqlite3/common.dart` library defines common interfaces that are implemented by both
the FFI-based native version in `package:sqlite3/sqlite3.dart` and the experimental WASM
version in `package:sqlite3/wasm.dart`.
By having shared code depend on the common interfaces, it can be used for both native and web
apps.
### Web encryption
Starting from version 2.6.0, `package:sqlite3/wasm.dart` supports loading a compiled version of
[SQLite Multiple Ciphers](https://utelle.github.io/SQLite3MultipleCiphers/) providing encryption
support for the web.
Please note that this variant is not currently tested as well as the regular SQLite version.
For this reason, using SQLite Multiple Ciphers with `package:sqlite3/wasm.dart` should be considered
experimental for the time being.
To test the encryption integration, download `sqlite3mc.wasm` from the [releases](https://github.com/simolus3/sqlite3.dart/releases)
of this package and use that as a URL to load sqlite3 on the web:
```dart
final sqlite3 = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3mc.wasm'));
sqlite3.registerVirtualFileSystem(InMemoryFileSystem(), makeDefault: true);
final database = sqlite3.open('/database')
..execute("pragma key = 'test';"); // TODO: Replace key
```
### Testing
To run the tests of this package with wasm, either download the `sqlite3.wasm` file from the
GitHub releases to `example/web` or compile it yourself (see [build setup](../sqlite3_wasm_build/)).
To run tests on the Dart VM, Firefox and Chrome, use:
```
dart test -P full
```
================================================
FILE: sqlite3/analysis_options.yaml
================================================
include: package:lints/recommended.yaml
analyzer:
language:
strict-casts: true
strict-raw-types: true
================================================
FILE: sqlite3/assets/sqlite3.h
================================================
// This file defines the definitions for which we generate FFI bindings on
// native platforms. To re-generate bindings, run:
// `dart run tool/generate_bindings.dart`.
#include
typedef struct sqlite3_char sqlite3_char;
typedef struct sqlite3 sqlite3;
typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3_backup sqlite3_backup;
typedef struct sqlite3_api_routines sqlite3_api_routines;
typedef struct sqlite3_session sqlite3_session;
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
sqlite3_char* sqlite3_temp_directory;
int sqlite3_initialize();
void sqlite3_free(void*);
int sqlite3_open_v2(sqlite3_char* filename, sqlite3** ppDb, int flags,
sqlite3_char* zVfs);
int sqlite3_close_v2(sqlite3* db);
sqlite3_char* sqlite3_db_filename(sqlite3* db, sqlite3_char* zDbName);
int sqlite3_compileoption_used(const sqlite3_char* zOptName);
const sqlite3_char* sqlite3_compileoption_get(int N);
int sqlite3_busy_handler(sqlite3* db, int (*)(void*, int), void* context);
// Error handling
int sqlite3_extended_result_codes(sqlite3* db, int onoff);
int sqlite3_extended_errcode(sqlite3* db);
sqlite3_char* sqlite3_errmsg(sqlite3* db);
sqlite3_char* sqlite3_errstr(int code);
int sqlite3_error_offset(sqlite3* db);
void sqlite3_free(void* ptr);
// Versions
sqlite3_char* sqlite3_libversion();
sqlite3_char* sqlite3_sourceid();
int sqlite3_libversion_number();
// Database
int64_t sqlite3_last_insert_rowid(sqlite3* db);
int sqlite3_changes(sqlite3* db);
int sqlite3_exec(sqlite3* db, sqlite3_char* sql, void* callback, void* argToCb,
sqlite3_char** errorOut);
void* sqlite3_update_hook(sqlite3*,
void (*)(void*, int, sqlite3_char const*,
sqlite3_char const*, int64_t),
void*);
void* sqlite3_commit_hook(sqlite3*, int (*)(void*), void*);
void* sqlite3_rollback_hook(sqlite3*, void (*)(void*), void*);
int sqlite3_get_autocommit(sqlite3* db);
// Statements
int sqlite3_prepare_v2(sqlite3* db, const sqlite3_char* zSql, int nByte,
sqlite3_stmt** ppStmt, const sqlite3_char** pzTail);
int sqlite3_prepare_v3(sqlite3* db, const sqlite3_char* zSql, int nByte,
unsigned int prepFlags, sqlite3_stmt** ppStmt,
const sqlite3_char** pzTail);
int sqlite3_finalize(sqlite3_stmt* pStmt);
int sqlite3_step(sqlite3_stmt* pStmt);
int sqlite3_reset(sqlite3_stmt* pStmt);
int sqlite3_stmt_isexplain(sqlite3_stmt* pStmt);
int sqlite3_stmt_readonly(sqlite3_stmt* pStmt);
int sqlite3_column_count(sqlite3_stmt* pStmt);
int sqlite3_bind_parameter_count(sqlite3_stmt* pStmt);
int sqlite3_bind_parameter_index(sqlite3_stmt*, sqlite3_char* zName);
sqlite3_char* sqlite3_column_name(sqlite3_stmt* pStmt, int N);
sqlite3_char* sqlite3_column_table_name(sqlite3_stmt* pStmt, int N);
int sqlite3_bind_blob64(sqlite3_stmt* pStmt, int index, void* data,
uint64_t length, void (*destructor)(void*));
int sqlite3_bind_double(sqlite3_stmt* pStmt, int index, double data);
int sqlite3_bind_int64(sqlite3_stmt* pStmt, int index, int64_t data);
int sqlite3_bind_null(sqlite3_stmt* pStmt, int index);
int sqlite3_bind_text(sqlite3_stmt* pStmt, int index, sqlite3_char* data,
int length, void (*destructor)(void*));
void* sqlite3_column_blob(sqlite3_stmt* pStmt, int iCol);
double sqlite3_column_double(sqlite3_stmt* pStmt, int iCol);
int64_t sqlite3_column_int64(sqlite3_stmt* pStmt, int iCol);
sqlite3_char* sqlite3_column_text(sqlite3_stmt* pStmt, int iCol);
int sqlite3_column_bytes(sqlite3_stmt* pStmt, int iCol);
int sqlite3_column_type(sqlite3_stmt* pStmt, int iCol);
// Values
typedef struct sqlite3_value sqlite3_value;
void* sqlite3_value_blob(sqlite3_value* value);
double sqlite3_value_double(sqlite3_value* value);
int sqlite3_value_type(sqlite3_value* value);
int64_t sqlite3_value_int64(sqlite3_value* value);
sqlite3_char* sqlite3_value_text(sqlite3_value* value);
int sqlite3_value_bytes(sqlite3_value* value);
unsigned int sqlite3_value_subtype(sqlite3_value* value);
// Functions
typedef struct sqlite3_context sqlite3_context;
int sqlite3_create_function_v2(
sqlite3* db, sqlite3_char* zFunctionName, int nArg, int eTextRep,
void* pApp, void (*xFunc)(sqlite3_context*, int, sqlite3_value**),
void (*xStep)(sqlite3_context*, int, sqlite3_value**),
void (*xFinal)(sqlite3_context*), void (*xDestroy)(void*));
int sqlite3_create_window_function(
sqlite3* db, sqlite3_char* zFunctionName, int nArg, int eTextRep,
void* pApp, void (*xStep)(sqlite3_context*, int, sqlite3_value**),
void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*),
void (*xInverse)(sqlite3_context*, int, sqlite3_value**),
void (*xDestroy)(void*));
void* sqlite3_aggregate_context(sqlite3_context* ctx, int nBytes);
void* sqlite3_user_data(sqlite3_context* ctx);
void sqlite3_result_blob64(sqlite3_context* ctx, void* data, uint64_t length,
void* destructor);
void sqlite3_result_double(sqlite3_context* ctx, double result);
void sqlite3_result_error(sqlite3_context* ctx, sqlite3_char* msg, int length);
void sqlite3_result_int64(sqlite3_context* ctx, int64_t result);
void sqlite3_result_null(sqlite3_context* ctx);
void sqlite3_result_text(sqlite3_context* ctx, sqlite3_char* data, int length,
void* destructor);
void sqlite3_result_subtype(sqlite3_context* ctx, unsigned int subtype);
// Collations
int sqlite3_create_collation_v2(sqlite3*, sqlite3_char* zName, int eTextRep,
void* pArg,
int (*xCompare)(void*, int, const void*, int,
const void*),
void (*xDestroy)(void*));
// Backup
sqlite3_backup* sqlite3_backup_init(sqlite3* pDestDb, sqlite3_char* zDestDb,
sqlite3* pSrcDb, sqlite3_char* zSrcDb);
int sqlite3_backup_step(sqlite3_backup* p, int nPage);
int sqlite3_backup_finish(sqlite3_backup* p);
int sqlite3_backup_remaining(sqlite3_backup* p);
int sqlite3_backup_pagecount(sqlite3_backup* p);
// Extensions
int sqlite3_auto_extension(void* xEntryPoint);
// Database configuration
int sqlite3_db_config(sqlite3* db, int op, ...);
// VFS
typedef struct sqlite3_file sqlite3_file;
struct sqlite3_io_methods {
int iVersion;
int (*xClose)(sqlite3_file*);
int (*xRead)(sqlite3_file*, void*, int iAmt, int64_t iOfst);
int (*xWrite)(sqlite3_file*, const void*, int iAmt, int64_t iOfst);
int (*xTruncate)(sqlite3_file*, int64_t size);
int (*xSync)(sqlite3_file*, int flags);
int (*xFileSize)(sqlite3_file*, int64_t* pSize);
int (*xLock)(sqlite3_file*, int);
int (*xUnlock)(sqlite3_file*, int);
int (*xCheckReservedLock)(sqlite3_file*, int* pResOut);
int (*xFileControl)(sqlite3_file*, int op, void* pArg);
int (*xSectorSize)(sqlite3_file*);
int (*xDeviceCharacteristics)(sqlite3_file*);
/* Methods above are valid for version 1 */
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void**);
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
void (*xShmBarrier)(sqlite3_file*);
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
/* Methods above are valid for version 2 */
int (*xFetch)(sqlite3_file*, int64_t iOfst, int iAmt, void** pp);
int (*xUnfetch)(sqlite3_file*, int64_t iOfst, void* p);
/* Methods above are valid for version 3 */
/* Additional methods may be added in future releases */
};
struct sqlite3_file {
const struct sqlite3_io_methods* pMethods; /* Methods for an open file */
};
typedef struct sqlite3_vfs sqlite3_vfs;
typedef void (*sqlite3_syscall_ptr)(void);
typedef const char* sqlite3_filename;
struct sqlite3_vfs {
int iVersion; /* Structure version number (currently 3) */
int szOsFile; /* Size of subclassed sqlite3_file */
int mxPathname; /* Maximum file pathname length */
sqlite3_vfs* pNext; /* Next registered VFS */
const char* zName; /* Name of this virtual file system */
void* pAppData; /* Pointer to application-specific data */
int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*, int flags,
int* pOutFlags);
int (*xDelete)(sqlite3_vfs*, const char* zName, int syncDir);
int (*xAccess)(sqlite3_vfs*, const char* zName, int flags, int* pResOut);
int (*xFullPathname)(sqlite3_vfs*, const char* zName, int nOut, char* zOut);
void* (*xDlOpen)(sqlite3_vfs*, const char* zFilename);
void (*xDlError)(sqlite3_vfs*, int nByte, char* zErrMsg);
void (*(*xDlSym)(sqlite3_vfs*, void*, const char* zSymbol))(void);
void (*xDlClose)(sqlite3_vfs*, void*);
int (*xRandomness)(sqlite3_vfs*, int nByte, char* zOut);
int (*xSleep)(sqlite3_vfs*, int microseconds);
int (*xCurrentTime)(sqlite3_vfs*, double*);
int (*xGetLastError)(sqlite3_vfs*, int, char*);
/*
** The methods above are in version 1 of the sqlite_vfs object
** definition. Those that follow are added in version 2 or later
*/
int (*xCurrentTimeInt64)(sqlite3_vfs*, int64_t*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
** Those below are for version 3 and greater.
*/
int (*xSetSystemCall)(sqlite3_vfs*, const char* zName, sqlite3_syscall_ptr);
sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char* zName);
const char* (*xNextSystemCall)(sqlite3_vfs*, const char* zName);
/*
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
** New fields may be appended in future versions. The iVersion
** value will increment whenever this happens.
*/
};
int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
int sqlite3_vfs_unregister(sqlite3_vfs*);
// Session
int sqlite3session_create(
sqlite3* db, /* Database handle */
const sqlite3_char* zDb, /* Name of db (e.g. "main") */
sqlite3_session** ppSession /* OUT: New session object */
);
void sqlite3session_delete(sqlite3_session* pSession);
int sqlite3session_enable(sqlite3_session* pSession, int bEnable);
int sqlite3session_indirect(sqlite3_session* pSession, int bIndirect);
int sqlite3changeset_start(
sqlite3_changeset_iter** pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void* pChangeset /* Pointer to blob containing changeset */
);
int sqlite3changeset_finalize(sqlite3_changeset_iter* pIter);
int sqlite3changeset_next(sqlite3_changeset_iter* pIter);
int sqlite3changeset_op(
sqlite3_changeset_iter* pIter, /* Iterator object */
const sqlite3_char** pzTab, /* OUT: Pointer to table name */
int* pnCol, /* OUT: Number of columns in table */
int* pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */
int* pbIndirect /* OUT: True for an 'indirect' change */
);
int sqlite3changeset_old(
sqlite3_changeset_iter* pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value** ppValue /* OUT: Old value (or NULL pointer) */
);
int sqlite3changeset_new(
sqlite3_changeset_iter* pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value** ppValue /* OUT: Old value (or NULL pointer) */
);
int sqlite3changeset_apply(
sqlite3* db, /* Apply change to "main" db of this handle */
int nChangeset, /* Size of changeset in bytes */
void* pChangeset, /* Changeset blob */
int (*xFilter)(void* pCtx, /* Copy of sixth arg to _apply() */
const char* zTab /* Table name */
),
int (*xConflict)(
void* pCtx, /* Copy of sixth arg to _apply() */
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
sqlite3_changeset_iter* p /* Handle describing change and conflict */
),
void* pCtx /* First argument passed to xConflict */
);
int sqlite3changeset_invert(int nIn, const void* pIn, /* Input changeset */
int* pnOut, void** ppOut /* OUT: Inverse of input */
);
int sqlite3session_patchset(
sqlite3_session* pSession, /* Session object */
int* pnPatchset, /* OUT: Size of buffer at *ppPatchset */
void** ppPatchset /* OUT: Buffer containing patchset */
);
int sqlite3session_changeset(
sqlite3_session* pSession, /* Session object */
int* pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void** ppChangeset /* OUT: Buffer containing changeset */
);
int sqlite3session_isempty(sqlite3_session* pSession);
int sqlite3session_attach(sqlite3_session* pSession, /* Session object */
const sqlite3_char* zTab /* Table name */
);
int sqlite3session_diff(sqlite3_session* pSession, const sqlite3_char* zFromDb,
const sqlite3_char* zTbl, sqlite3_char** pzErrMsg);
================================================
FILE: sqlite3/assets/sqlite3_dart_wasm.h
================================================
#include "sqlite3.h"
// Additional bindings we need for WASM interop.
// These are implemented in sqlite3_wasm_build, this header is only used for
// ffigen.
typedef struct {
} externref;
void* dart_sqlite3_malloc(int size);
void dart_sqlite3_free(void* ptr);
int dart_sqlite3_bind_blob(sqlite3_stmt* stmt, int index, const void* buf,
int len);
int dart_sqlite3_bind_text(sqlite3_stmt* stmt, int index, const char* buf,
int len);
sqlite3_vfs* dart_sqlite3_register_vfs(const char* name, externref* vfs,
int makeDefault);
int dart_sqlite3_unregister_vfs(sqlite3_vfs* vfs);
int dart_sqlite3_create_function_v2(sqlite3* db, const char* zFunctionName,
int nArg, int eTextRep, int isAggregate,
externref* handlers);
int dart_sqlite3_create_window_function(sqlite3* db, const char* zFunctionName,
int nArg, int eTextRep,
externref* handlers);
void dart_sqlite3_updates(sqlite3* db, externref* callback);
void dart_sqlite3_commits(sqlite3* db, externref* callback);
void dart_sqlite3_rollbacks(sqlite3* db, externref* callback);
int dart_sqlite3_create_collation(sqlite3* db, const char* zName, int eTextRep,
externref* function);
int dart_sqlite3_db_config_int(sqlite3* db, int op, int arg);
int dart_sqlite3changeset_apply(sqlite3* db, int nChangeset, void* pChangeset,
externref* callbacks, int filter);
int dart_sqlite3_busy_handler(sqlite3* db, externref* callback);
================================================
FILE: sqlite3/build.yaml
================================================
targets:
# This setup exists so that the main entrypoint (web/main.dart) gets compiled
# with dartdevc for debug builds while the worker is compiled with dart2js
# (since workers don't support the JS moduled emitted by dartdevc).
# In release builds (`--release` on the CLI), both entrypoints are compiled
# with dart2js.
#
# If you're ok with compiling everything with dart2js, just use
# `compiler: dartj2s` on the options of the default target and ignore the two
# additional targets here.
dart2js_archives:
auto_apply_builders: false
dependencies: [":$default", ":worker"]
builders:
build_web_compilers:dart2js_archive_extractor:
enabled: true
worker:
auto_apply_builders: false
dependencies: [":$default"]
builders:
build_web_compilers:entrypoint:
enabled: true
generate_for:
- example/web/worker.dart
options:
compiler: dart2js
build_web_compilers:dart2js_archive_extractor:
enabled: false
$default:
sources:
include:
- lib/**
- example/web/**
builders:
build_web_compilers:entrypoint:
generate_for:
include:
- "example/web/**"
# This one is compiled in the other target
exclude:
- "example/web/worker.dart"
# We have a designated target for this step.
build_web_compilers:dart2js_archive_extractor:
enabled: false
================================================
FILE: sqlite3/dart_test.yaml
================================================
tags:
ffi:
test_on: dart-vm
wasm:
test_on: browser
ci_only:
skip: "This test requires special setup and only runs in the GitHub CI action"
platforms: [vm]
override_platforms:
firefox:
settings:
arguments: "-headless"
chrome:
settings:
executable: google-chrome-stable
arguments: "--enable-features=SharedArrayBuffer"
edge:
settings:
arguments: "--enable-features=SharedArrayBuffer"
presets:
full:
platforms: [vm, chrome, firefox]
compilers: [dart2js, dart2wasm]
on_os:
windows:
platforms: [vm, chrome, firefox, edge]
web:
platforms: [chrome, firefox]
on_os:
windows:
platforms: [chrome, firefox, edge]
wasm-only:
add_presets: [web]
compilers: [dart2wasm]
web-full:
add_presets: [web]
compilers: [dart2js, dart2wasm]
ci:
tags:
ci_only:
skip: false
================================================
FILE: sqlite3/dartdoc_options.yaml
================================================
dartdoc:
categories:
"common":
markdown: doc/common.md
displayName: Cross-platform definitions
"native":
markdown: doc/native.md
displayName: Native only
"wasm":
markdown: doc/wasm.md
displayName: Web only
"hook":
markdown: doc/hook.md
displayName: Build hook options
================================================
FILE: sqlite3/doc/common.md
================================================
Definitions and common interfaces that are implemented by both the native
and the web-specific bindings to SQLite.
Restricting your usage of the sqlite3 package to `package:sqlite3/common.dart`
means that your code can run on all platforms.
However, this doesn't give you access to the actual implementations that are part
of the native and web implementations.
You can write most of your database code with the common definitions and then use
conditional imports to make an implementation available. For this, create three files:
1. `database_stub.dart`.
2. `database_native.dart`.
3. `datbaase_web.dart`.
The content of these files depends on your needs, but could look like this:
```dart
// database_stub.dart
import 'package:sqlite3/common.dart';
Future openDatabase() async {
throw UnsupportedError('Unknown platform');
}
```
```dart
// database_native.dart
import 'package:sqlite3/sqlite3.dart';
Future openDatabase() async {
final path = await pickDatabasePath(); // e.g. with package:path_provider
return sqlite3.open(path);
}
```
```dart
// database_web.dart
import 'package:sqlite3/wasm.dart';
Future openDatabase() async {
final sqlite = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3.wasm'));
final fs = await IndexedDbFileSystem.open(dbName: 'app.db');
sqlite.registerVirtualFileSystem(fs, makeDefault: true);
return sqlite.open('/app.db');
}
```
With those files, you can use a conditional imports to support both web and native platforms:
```dart
import 'database_stub.dart'
if (dart.library.io) 'database_native.dart'
if (dart.library.js_interop) 'database_web.dart';
```
================================================
FILE: sqlite3/doc/hook.md
================================================
Most operating systems make copies of SQLite as a native library available to applications.
However, these libraries are inconsistent in their compile-time options (resulting in different
SQLite features being available on different platforms) and are often outdated.
To avoid this inconsistency, `package:sqlite3/` bundles a copy of SQLite with your application
by default, and it will prefer to use that copy over the one from the operating system.
To do that, it uses a new Dart and Flutter feature called [hooks](https://dart.dev/tools/hooks).
More information on hooks is available under that link, this page describes options relevant to
`package:sqlite3`.
## Default binaries
Each [GitHub release](https://github.com/simolus3/sqlite3.dart/releases) of the SQLite package
contains pre-compiled SQLite versions as shared libraries for all platforms supported by Dart.
These binaries are compiled directly from upstream sources in GitHub actions, and the version of
`package:sqlite3` published to pub.dev contains sha256 references that are compared against
downloaded files.
These binaries use the following compile-time options:
```
SQLITE_ENABLE_DBSTAT_VTAB
SQLITE_ENABLE_FTS5
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_MATH_FUNCTIONS
SQLITE_DQS=0
SQLITE_DEFAULT_MEMSTATUS=0
SQLITE_TEMP_STORE=2
SQLITE_MAX_EXPR_DEPTH=0
SQLITE_STRICT_SUBTYPE=1
SQLITE_OMIT_AUTHORIZATION
SQLITE_OMIT_DECLTYPE
SQLITE_OMIT_DEPRECATED
SQLITE_OMIT_PROGRESS_CALLBACK
SQLITE_OMIT_SHARED_CACHE
SQLITE_OMIT_TCL_VARIABLE
SQLITE_OMIT_TRACE
SQLITE_USE_ALLOCA
SQLITE_ENABLE_SESSION
SQLITE_ENABLE_PREUPDATE_HOOK
SQLITE_UNTESTABLE
SQLITE_HAVE_ISNAN
SQLITE_HAVE_LOCALTIME_R
SQLITE_HAVE_LOCALTIME_S
SQLITE_HAVE_MALLOC_USABLE_SIZE
SQLITE_HAVE_STRCHRNUL
```
For each platform, two sets of binaries are available:
- [Upstream SQLite](https://sqlite.org/download.html).
- The [SQLite3MultipleCiphers build](https://github.com/utelle/SQLite3MultipleCiphers/releases)
providing encryption support.
SQLite is used by default, but SQLite3MultipleCiphers can be selected through user defines, e.g.
by adding this to `pubspec.yaml`:
```yaml
hooks:
user_defines:
sqlite3:
source: sqlite3mc # for SQLite3MultipleCiphers, default is sqlite3
```
## System-provided SQLite
Depending on how you distribute your app, you may want to use the SQLite version shipped with
the operating system.
To do so, use the following user defines:
```yaml
hooks:
user_defines:
sqlite3:
source: system # or "process", or "excutable"
```
These options behave as follows:
1. "system" instructs the Dart embedder to lookup SQLite from the operating system, e.g. with a
`dlopen("libsqlite3.so")` on Linux.
When using `source: system`, you can also add a `name` key to customize the name of the library.
For instance, `name: sqlcipher` would load `libsqlcipher.dylib` on macOS.
2. "process" looks for SQLite symbols in the current [process](https://api.dart.dev/dart-ffi/DynamicLibrary/DynamicLibrary.process.html), which can be useful when your executable already depends on
SQLite (instead of explicitly requesting it with `dlopen`).
3. "executable" looks for SQLite symbols in the current [executable](https://api.dart.dev/dart-ffi/DynamicLibrary/DynamicLibrary.executable.html), which is useful when linking SQLite statically.
### With custom library names
When using `source: system`, you can also add a `name` key to customize the name of the name of the
library.
For instance, `name: sqlcipher` would load `libsqlcipher.dylib` on macOS, `libsqlcipher.so` on Linux
and `sqlcipher.dll` on Windows.
To further customize the name for specific operating systems, you can use `name_$os` keys, where `$os`
is the [target operating system](https://pub.dev/documentation/code_assets/latest/code_assets/OS-class.html)
passed to hooks:
```yaml
hooks:
user_defines:
sqlite3:
source: system
# Use winsqlite3.dll on Windows, libsqlite3.{so,dylib} on Linux and macOS
name_windows: winsqlite3
name: sqlite3
```
## Custom SQLite builds
If you want to customize the SQLite build to use with `package:sqlite3`, you can
also use user defines for that.
First, download the `sqlite3.c` file you want to use into your workspace. Then,
add this section to your pubspec:
```yaml
hooks:
user_defines:
sqlite3:
source: source
path: path/to/sqlite3.c # relative to your workspace root
defines: # optional
default_options: false # optional, to disable default compile-time options used by package:sqlite3
defines:
- SQLITE_THREADSAFE=1
- SQLITE_LIKE_DOESNT_MATCH_BLOBS
```
### Alternatives
Using the `source` mode to compile SQLite from sources in build hook can't
cover all customization needs you may have. When building SQLCipher for
instance, you may want to pass custom linker options to the build process.
There is no good way to support arbitrary customization in build hooks today.
However, `package:sqlite3` will work with all SQLite builds that are ABI-compatible
with standard SQLite (it also runs checks at runtime before using methods that
are not commonly enabled on all builds).
If you control the build process of your application, you can use an external
build system (like SwiftPM or CMake) to statically link SQLite into your application.
Then, use `source: executable` to make `package:sqlite3` use that copy instead
of building its own.
================================================
FILE: sqlite3/doc/native.md
================================================
Libraries related to accessing SQLite functions via `dart:ffi` on native platforms.
================================================
FILE: sqlite3/doc/releasing.md
================================================
## Releasing `package:sqlite3`.
Because each release contains native SQLite binaries whose hashes are referenced in Dart,
adding a new release requires some setup.
1. Run the full actions test pipeline for all changes to include.
2. From that run, download the `asset_hashes.dart` file and copy it to
`sqlite3/lib/src/hook/asset_hashes.dart`.
3. In that file, set `releaseTag` to `sqlite3-<$newVersion>`.
4. In `sqlite3/pubspec.yaml`, set `version` to `$newVersion`.
5. Commit and create a git tag `sqlite3-<$newVersion>`.
6. Push that tag and approve the pub.dev publishing workflow.
================================================
FILE: sqlite3/doc/wasm.md
================================================
APIs for using SQLite in web contexts, accessing SQLite through a WebAssembly module.
================================================
FILE: sqlite3/example/custom_extension/README.md
================================================
This shows how a custom SQLite extension can be linked with native assets.
The extension (https://github.com/asg017/sqlite-vec) is built with a code asset that will download
the extension as a prebuilt file from its GitHub releases.
SQLite extensions are shared libraries that have a function called `sqlite3_$extensionName_init`.
With the hook linking the extension, you can bind to that function with Dart:
```dart
@Native, Pointer, Pointer)>()
external int sqlite3_vec_init(
Pointer db,
Pointer pzErrMsg,
Pointer pApi,
);
```
This will then allow linking the extension:
```dart
extension LoadVectorExtension on Sqlite3 {
void loadSqliteVectorExtension() {
ensureExtensionLoaded(
SqliteExtension(
Native.addressOf<
NativeFunction<
Int Function(Pointer, Pointer, Pointer)
>
>(sqlite3_vec_init).cast(),
),
);
}
}
```
To try this example, run `dart run example/main.dart`.
================================================
FILE: sqlite3/example/custom_extension/example/main.dart
================================================
import 'package:custom_extension/sqlite_vec.dart';
import 'package:sqlite3/sqlite3.dart';
void main() {
sqlite3.loadSqliteVectorExtension();
final db = sqlite3.openInMemory();
db.execute('''
create virtual table vec_examples using vec0(
sample_embedding float[8]
);
insert into vec_examples(rowid, sample_embedding)
values
(1, '[-0.200, 0.250, 0.341, -0.211, 0.645, 0.935, -0.316, -0.924]'),
(2, '[0.443, -0.501, 0.355, -0.771, 0.707, -0.708, -0.185, 0.362]'),
(3, '[0.716, -0.927, 0.134, 0.052, -0.669, 0.793, -0.634, -0.162]'),
(4, '[-0.710, 0.330, 0.656, 0.041, -0.990, 0.726, 0.385, -0.958]');
''');
print(
db.select('''
select
rowid,
distance
from vec_examples
where sample_embedding match '[0.890, 0.544, 0.825, 0.961, 0.358, 0.0196, 0.521, 0.175]'
order by distance
limit 2;
'''),
);
}
================================================
FILE: sqlite3/example/custom_extension/hook/build.dart
================================================
import 'dart:io';
import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:http/http.dart';
import 'package:tar/tar.dart';
void main(List args) {
build(args, (input, output) async {
final targetOS = input.config.code.targetOS;
final arch = input.config.code.targetArchitecture;
final (osName, fileName) = switch (targetOS) {
OS.linux => ('linux', 'vec0.so'),
OS.macOS => ('macos', 'vec0.dylib'),
OS.windows => ('windows', 'vec0.dll'),
_ => throw UnsupportedError('Unsupported target os $targetOS'),
};
final archName = switch (arch) {
Architecture.x64 => 'x86_64',
Architecture.arm64 => 'aarch64',
_ => throw UnsupportedError('Unsupported target architecture $arch'),
};
final client = Client();
final uri = Uri.parse(
'https://github.com/asg017/sqlite-vec/releases/download/v$version/sqlite-vec-$version-loadable-$osName-$archName.tar.gz',
);
final response = await client.send(
Request('GET', uri)..followRedirects = true,
);
if (response.statusCode != 200) {
throw StateError(
'Unexpected status code ${response.statusCode} for $uri',
);
}
final reader = TarReader(response.stream.transform(gzip.decoder));
var foundFile = false;
while (await reader.moveNext()) {
final current = reader.current;
if (current.name == fileName) {
final targetFilePath = input.outputDirectory.resolve(fileName);
final targetFile = File(targetFilePath.toFilePath());
await current.contents.pipe(targetFile.openWrite());
output.assets.code.add(
CodeAsset(
package: 'custom_extension',
name: 'sqlite_vec.dart',
file: targetFilePath,
linkMode: DynamicLoadingBundled(),
),
);
foundFile = true;
break;
}
}
if (!foundFile) {
throw 'Could not find $fileName in $uri';
}
await reader.cancel();
client.close();
});
}
const version = '0.1.6';
================================================
FILE: sqlite3/example/custom_extension/lib/sqlite_vec.dart
================================================
// ignore_for_file: non_constant_identifier_names
import 'dart:ffi';
import 'package:sqlite3/sqlite3.dart';
@Native, Pointer, Pointer)>()
external int sqlite3_vec_init(
Pointer db,
Pointer pzErrMsg,
Pointer pApi,
);
extension LoadVectorExtension on Sqlite3 {
void loadSqliteVectorExtension() {
ensureExtensionLoaded(
SqliteExtension(
Native.addressOf<
NativeFunction<
Int Function(Pointer, Pointer, Pointer)
>
>(sqlite3_vec_init).cast(),
),
);
}
}
================================================
FILE: sqlite3/example/custom_extension/pubspec.yaml
================================================
name: custom_extension
publish_to: none
resolution: workspace
environment:
sdk: '>=3.7.0 <4.0.0'
dependencies:
sqlite3:
code_assets: ^1.0.0
hooks: ^1.0.0
http: ^1.5.0
tar: ^2.0.0
dev_dependencies:
test: ^1.26.0
================================================
FILE: sqlite3/example/custom_extension/test/extension_test.dart
================================================
import 'package:custom_extension/sqlite_vec.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:test/test.dart';
void main() {
setUpAll(() {
sqlite3.loadSqliteVectorExtension();
});
test('can use vec0', () {
final db = sqlite3.openInMemory();
addTearDown(db.close);
db.execute(
'create virtual table vec_examples using vec0(sample_embedding float[8])',
);
});
}
================================================
FILE: sqlite3/example/custom_wasm_build/.cargo/config.toml
================================================
[build]
rustflags = ["-C", "linker-plugin-lto"]
================================================
FILE: sqlite3/example/custom_wasm_build/.gitignore
================================================
target/
Cargo.lock
================================================
FILE: sqlite3/example/custom_wasm_build/Cargo.toml
================================================
[package]
name = "custom_wasm_build"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
[build-dependencies]
cc = "1.0.46"
cmake = "0.1.50"
[profile.release]
opt-level = "z"
lto=true
================================================
FILE: sqlite3/example/custom_wasm_build/README.md
================================================
## custom wasm modules
This example demonstrates how to build a custom `sqlite3.wasm` module than can be
used with `package:sqlite3`.
Using custom wasm modules is useful to include additional extensions in sqlite3, or to
use different compile-time options.
This example uses existing C source files also used by the default configuration:
- `sqlite3.c` for the actual SQLite library.
- [`helpers.c`](https://github.com/simolus3/sqlite3.dart/blob/main/sqlite3/assets/wasm/helpers.c) from this repository, which defines a VFS wrapper for virtual filesystem implementations provided from Dart.
- Our `os_web.c` file is _not_ included. It contains the implementation for
`sqlite3_os_init` and `sqlite3_os_end`, which are implemented in this custom
extension instead. `sqlite3_os_init` is a suitable hook to load your sqlite3
extensions.
In this example, the extension is a simple Rust library printing a hello message
to the web console when the module is loaded.
## Setup
We're currently using the libc from [WASI](https://wasi.dev/) to compile sqlite3,
so the easiest approach is to compile your custom extensions with that as well:
```
rustup target add wasm32-wasi
```
Additionally, you need to download WASI compiler builtins and the associated libc
as described in the [build instructions](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3#compiling).
## Building
The `build.rs` file from this example is responsible for compiling sqlite3 to
WebAssembly object files. We're not using a static library because that seems to
break the `--export-dynamic` option used in the final linking step to expose the
relevant functions.
To download and compile sqlite3 as well as the patched `sqlite3_os_init` function
for this example, run
```
WASI_SYSROOT=/path/to/wasi/ CC=/path/to/clang cargo build --target wasm32-unknown-unknown
```
Or, to compile a release build optimized for size:
```
WASI_SYSROOT=/path/to/wasi/ CC=/path/to/clang cargo build --target wasm32-unknown-unknown --release
```
Cargo compiles sqlite3 to WASM object files, the Rust part is compiled into a static
library.
A Dart script (`link.dart`) can be used to link them together into a `sqlite3.wasm`
file loadable by the `sqlite3` package:
```
CC=/path/to/clang dart run link.dart target/wasm32-unknown-unknown/debug
CC=/path/to/clang dart run link.dart target/wasm32-unknown-unknown/release
```
As an additional transformation step, running `wasm-opt -O4` on the resulting
WASM file may optimize it further.
Similarly, running `dart run tool/wasm_dce.dart ` in
the `sqlite3` source directory will remove functions not directly or indirectly
used by the Dart package, reduzing bundle size.
================================================
FILE: sqlite3/example/custom_wasm_build/build.rs
================================================
use std::{env, path::PathBuf};
use cmake::Config;
fn main() {
let sysroot =
env::var("WASI_SYSROOT").unwrap_or_else(|_| "/usr/share/wasi-sysroot".to_string());
let cmake_dir = Config::new("../../../sqlite3_wasm_build/src/")
.define("wasi_sysroot", &sysroot)
.define("CMAKE_C_COMPILER_WORKS", "1")
.build_target("sqlite3_opt_lib")
.build_target("help") // We only need the sources
.build();
let sqlite3_src = cmake_dir.join("build/_deps/sqlite3-src/");
let mut c_build = cc::Build::new();
let objects = c_build
.target("wasm32-unknown-wasi")
.cargo_warnings(false)
.std("c23")
.flag("--sysroot")
.flag(&sysroot)
.file(sqlite3_src.join("sqlite3.c"))
.file("../../../sqlite3_wasm_build/src/helpers.c")
.flag("-flto=thin")
.include(&sqlite3_src)
.include("../../../sqlite3_wasm_build/src/")
.define("SQLITE_ENABLE_SESSION", None)
.define("SQLITE_ENABLE_PREUPDATE_HOOK", None)
.define("_HAVE_SQLITE_CONFIG_H", None)
.define("SQLITE_API", "__attribute__((visibility(\"default\")))")
// Ideally we should be able to compile this into a static library and use that one, but
// for some reasons that drops all exported symbols. So we're compiling to objects and
// we only compile Rust code to a static library. Then we use the clang driver to link
// these objects and the static Rust library in one go.
.compile_intermediates();
let output_dir = get_output_path();
for object in objects {
// The file name is something like -sqlite3.o
let file_name = object.file_name().unwrap().to_str().unwrap().to_owned();
let (_, file_name) = file_name.split_once("-").unwrap();
std::fs::copy(object, output_dir.join(file_name)).unwrap();
}
}
fn get_output_path() -> PathBuf {
let mut out = PathBuf::from(env::var("OUT_DIR").unwrap());
loop {
match out.file_name() {
Some(name) if name == "build" => {
break;
}
_ => out = out.parent().unwrap().to_path_buf(),
}
}
out.parent().unwrap().to_path_buf()
}
================================================
FILE: sqlite3/example/custom_wasm_build/link.dart
================================================
import 'dart:io';
void main(List args) {
if (args.length != 1) {
print("Usage: dart link.dart target/wasm32-wasi/");
}
final directory = Directory(args[0]);
final entries = [];
for (final entry in directory.listSync()) {
if (entry.path.endsWith('.o') || entry.path.endsWith('.a')) {
entries.add(entry.path);
}
}
final clang = Platform.environment['CC'] ?? 'clang';
final sysroot =
Platform.environment['WASI_SYSROOT'] ?? '/usr/share/wasi-sysroot';
final process = Process.runSync(clang, [
'--target=wasm32-unknown-wasi',
'--sysroot=$sysroot',
'-flto',
...entries,
'-o',
'sqlite3.wasm',
'-nostartfiles',
'-Wl,--no-entry',
'-Wl,--export-dynamic',
'-Wl,--import-memory',
'-v',
]);
if (process.exitCode != 0) {
print(
'Could not link: ${process.exitCode}, ${process.stderr}, ${process.stdout}',
);
}
}
================================================
FILE: sqlite3/example/custom_wasm_build/src/lib.rs
================================================
use std::ffi::c_int;
#[no_mangle]
pub extern "C" fn sqlite3_os_init() -> c_int {
// This would be a good place to set up extensions.
unsafe {
// package:sqlite3 provides access to Dart's print function via dart.error_log
wasm::dartLogError("Hello from a custom Rust build!".as_ptr().cast());
}
return 0;
}
#[no_mangle]
pub extern "C" fn sqlite3_os_end() -> c_int {
return 0;
}
mod wasm {
use std::ffi::c_char;
#[link(wasm_import_module = "dart")]
extern "C" {
#[link_name = "error_log"]
pub fn dartLogError(msg: *const c_char);
}
}
================================================
FILE: sqlite3/example/jsonb.dart
================================================
import 'package:sqlite3/sqlite3.dart';
void main() {
final database = sqlite3.openInMemory()
..execute('CREATE TABLE entries (entry BLOB NOT NULL) STRICT;')
// You can insert JSONB-formatted values directly
..execute('INSERT INTO entries (entry) VALUES (?)', [
jsonb.encode({'hello': 'dart'}),
]);
// And use them with JSON operators in SQLite without a further conversion:
print(database.select('SELECT entry ->> ? AS r FROM entries;', [r'$.hello']));
}
================================================
FILE: sqlite3/example/main.dart
================================================
import 'dart:io';
import 'package:sqlite3/sqlite3.dart';
void main() {
print('Using sqlite3 ${sqlite3.version}');
// Create a new in-memory database. To use a database backed by a file, you
// can replace this with sqlite3.open(yourFilePath).
final db = sqlite3.openInMemory();
// Create a table and insert some data
db.execute('''
CREATE TABLE artists (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);
''');
// Prepare a statement to run it multiple times:
final stmt = db.prepare('INSERT INTO artists (name) VALUES (?)');
stmt
..execute(['The Beatles'])
..execute(['Led Zeppelin'])
..execute(['The Who'])
..execute(['Nirvana']);
// Dispose a statement when you don't need it anymore to clean up resources.
stmt.close();
// You can run select statements with PreparedStatement.select, or directly
// on the database:
final ResultSet resultSet = db.select(
'SELECT * FROM artists WHERE name LIKE ?',
['The %'],
);
// You can iterate on the result set in multiple ways to retrieve Row objects
// one by one.
for (final Row row in resultSet) {
print('Artist[id: ${row['id']}, name: ${row['name']}]');
}
// Register a custom function we can invoke from sql:
db.createFunction(
functionName: 'dart_version',
argumentCount: const AllowedArgumentCount(0),
function: (args) => Platform.version,
);
print(db.select('SELECT dart_version()'));
// Don't forget to dispose the database to avoid memory leaks (optional on
// native platforms).
db.close();
}
================================================
FILE: sqlite3/example/web/README.md
================================================
## sqlite3 web example
This folder contains a very simple example demonstrating how to load a sqlite3 database in the
web.
To run this example, first obtain a `sqlite3.debug.wasm` file from the [releases](https://github.com/simolus3/sqlite3.dart/releases)
of this package and put it in this `web/` folder.
In a real app, you'll want to use the `sqlite3.wasm` file from the releases, but the debug variant
prints more log messages which are relevant for the example.
In the `sqlite3/` folder (`../..`), run `dart run build_runner serve example:8080`.
Then, you can visit the example at http://localhost:8080/web/.
------
For larger applications using sqlite3, you may want to try out a database framework such as
[drift](https://drift.simonbinder.eu/web/), which takes care of the complex setup steps for you.
It automatically determines features supported by the current browser to choose a suitable filesystem
implementation.
================================================
FILE: sqlite3/example/web/index.html
================================================
sqlite on the web
sqlite3 web demo
This page can be used to launch a sqlite3 database on the web in two different configurations:
With an IndexedDb-based storage implementation (doesn't require web workers): Start demo!
With an Origin-Private FileSystem (OPFS)-based storage implementation. Note that this requires two workers and a special header
that is not available with build_runner serve, but it will work when launching this website with dart run tool/example_server.dart Start demo!
With an in-memory test (using SQLite3 Multiple Ciphers for encryption): Start encryption!
After launching the example, you can check the console and the code in main.dart (or worker.dart for the OPFS example)
for details.
================================================
FILE: sqlite3/example/web/main.dart
================================================
import 'dart:js_interop';
import 'package:web/web.dart';
import 'package:sqlite3/wasm.dart';
Future main() async {
final startIndexedDb = document.getElementById('start-idb')!;
final startOpfs = document.getElementById('start-opfs')!;
final startEncryption = document.getElementById('start-encryption')!;
startIndexedDb.onClick.listen((_) async {
startIndexedDb.remove();
final sqlite3 = await WasmSqlite3.loadFromUrl(
Uri.parse('sqlite3.debug.wasm'),
);
print(sqlite3.version);
sqlite3.registerVirtualFileSystem(
await IndexedDbFileSystem.open(dbName: 'sqlite3-example'),
makeDefault: true,
);
sqlite3.open('/database')
..execute('pragma user_version = 1')
..execute('CREATE TABLE foo (bar INTEGER NOT NULL);')
..execute('INSERT INTO foo (bar) VALUES (?)', [3])
..close();
final db = sqlite3.open('/database');
print(db.select('SELECT * FROM foo'));
});
startOpfs.onClick.listen((_) async {
startOpfs.remove();
final worker = Worker('worker.dart.js'.toJS);
worker.postMessage('start'.toJS);
});
startEncryption.onClick.listen((_) async {
startEncryption.remove();
final sqlite3 = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3mc.wasm'));
sqlite3.registerVirtualFileSystem(InMemoryFileSystem(name: 'testing'));
sqlite3.open('/database', vfs: 'multipleciphers-testing')
..execute("pragma key = 'test';")
..execute('pragma user_version = 1')
..execute('CREATE TABLE foo (bar INTEGER NOT NULL);')
..execute('INSERT INTO foo (bar) VALUES (?)', [3])
..close();
final db = sqlite3.open('/database', vfs: 'multipleciphers-testing');
try {
db.select('SELECT * FROM foo');
} on SqliteException {
print('database call failed (expected due to missing key)');
}
db.execute("pragma key = 'test';");
print(db.select('SELECT * FROM foo'));
});
}
================================================
FILE: sqlite3/example/web/worker.dart
================================================
import 'dart:js_interop';
import 'package:sqlite3/wasm.dart';
import 'package:web/web.dart' as web;
@JS()
external bool get crossOriginIsolated;
void main() {
print('worker main');
final self = (globalContext as web.DedicatedWorkerGlobalScope);
if (!WasmVfs.supportsAtomicsAndSharedMemory) {
throw UnsupportedError(
'Missing support for Atomics or SharedArrayBuffer! Isolated: $crossOriginIsolated',
);
}
Future handleEvent(web.MessageEvent event) async {
final data = event.data;
if (data.equals('start'.toJS).toDart) {
final options = WasmVfs.createOptions();
final worker = web.Worker(''.toJS); // Clone this worker
worker.postMessage(options);
// Now, wait for the worker to report that it has been initialized.
await web.EventStreamProviders.messageEvent.forTarget(worker).first;
final sqlite3 = await WasmSqlite3.loadFromUrl(
Uri.parse('sqlite3.debug.wasm'),
);
sqlite3.registerVirtualFileSystem(
await SimpleOpfsFileSystem.loadFromStorage('worker-test'),
makeDefault: true,
);
sqlite3.open('/database')
..execute('pragma user_version = 1')
..execute('CREATE TABLE foo (bar INTEGER NOT NULL);')
..execute('INSERT INTO foo (bar) VALUES (?)', [3])
..close();
final db = sqlite3.open('/database');
print(db.select('SELECT * FROM foo'));
} else {
final message = data as WorkerOptions;
final worker = await VfsWorker.create(message);
self.postMessage(true.toJS);
await worker.start();
}
}
self.onmessage = (web.MessageEvent event) {
handleEvent(event);
}.toJS;
}
================================================
FILE: sqlite3/hook/build.dart
================================================
import 'dart:io';
import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:path/path.dart' as p;
import 'package:sqlite3/src/hook/description.dart';
import 'package:sqlite3/src/hook/used_symbols.dart';
void main(List args) async {
await build(args, (input, output) async {
if (!input.config.buildCodeAssets) {
return;
}
final sqlite = SqliteBinary.forBuild(input);
switch (sqlite) {
case PrecompiledBinary():
final library = sqlite.resolveLibrary(input.config.code);
library.checkSupported();
final downloaded = await sqlite.downloadIntoOutputDirectoryShared(
input,
output,
library,
);
output.assets.code.add(
CodeAsset(
package: package,
name: name,
linkMode: DynamicLoadingBundled(),
file: downloaded.uri,
),
);
case CompileSqlite(:final sourceFile, :final defines):
// With Flutter on Linux (which already dynamically links SQLite through
// its libgtk dependency), we run into issues where loading our SQLite
// build causes internal symbols to be resolved against the already
// loaded library from the system.
// This is terrible and not what we ever want. A proper solution may be
// to use namespaces or RTLD_DEEPBIND, but hooks don't support that yet.
// An alternative that seems to work is to pass -Bsymbolic-functions to
// the linker.
// For the full discussion, see https://github.com/dart-lang/native/issues/2724
String? linkerScript;
if (input.config.code.targetOS == OS.linux) {
linkerScript = input.outputDirectory.resolve('sqlite.map').path;
await File(linkerScript).writeAsString('''
{
global:
${usedSqliteSymbols.map((symbol) => ' $symbol;').join('\n')}
local:
*;
};
''');
}
final library = CBuilder.library(
name: 'sqlite3',
packageName: 'sqlite3',
assetName: name,
sources: [sourceFile],
includes: [p.dirname(sourceFile)],
defines: defines,
flags: [
if (input.config.code.targetOS == OS.linux) ...[
// This avoids loading issues on Linux, see comment above.
'-Wl,-Bsymbolic',
// And since we already have a designated list of symbols to
// export, we might as well strip the rest.
// TODO: Port this to other targets too.
'-Wl,--version-script=$linkerScript',
'-ffunction-sections',
'-fdata-sections',
'-Wl,--gc-sections',
],
if (input.config.code.targetOS case OS.iOS || OS.macOS) ...[
'-headerpad_max_install_names',
// clang would use the temporary directory passed by
// native_toolchain_c otherwise. So this makes improves
// reproducibility.
'-install_name',
'@rpath/libsqlite3.dylib',
],
],
libraries: [
if (input.config.code.targetOS == OS.android)
// We need to link the math library on Android.
'm',
],
);
await library.run(input: input, output: output);
case ExternalSqliteBinary():
output.assets.code.add(
CodeAsset(
package: package,
name: name,
linkMode: sqlite.resolveLinkMode(input),
),
);
}
});
}
const package = 'sqlite3';
const name = 'src/ffi/libsqlite3.g.dart';
================================================
FILE: sqlite3/lib/common.dart
================================================
/// Exports common interfaces that are implemented by both the `dart:ffi` and
/// the `dart:js` WASM version of this library.
///
/// {@category common}
/// {@canonicalFor database.CommonDatabase}
/// {@canonicalFor statement.CommonPreparedStatement}
library;
export 'src/constants.dart';
export 'src/database.dart';
export 'src/session.dart';
export 'src/exception.dart';
export 'src/functions.dart';
export 'src/in_memory_vfs.dart' show InMemoryFileSystem;
export 'src/jsonb.dart';
export 'src/result_set.dart';
export 'src/sqlite3.dart';
export 'src/statement.dart'
show CommonPreparedStatement, StatementParameters, CustomStatementParameter;
export 'src/vfs.dart';
================================================
FILE: sqlite3/lib/sqlite3.dart
================================================
/// Dart bindings to `sqlite3`.
///
/// {@category native}
/// {@category hook}
library;
// Hide common base classes that have more specific ffi-APIs.
export 'common.dart' hide CommonPreparedStatement, CommonDatabase;
export 'src/ffi/api.dart';
================================================
FILE: sqlite3/lib/src/constants.dart
================================================
// ignore_for_file: constant_identifier_names
/// Common result codes, https://www.sqlite.org/rescode.html
/// Result Codes
///
/// Many SQLite functions return an integer result code from the set shown
/// here in order to indicates success or failure.
///
/// New error codes may be added in future versions of SQLite.
///
/// See also: SQLITE_IOERR_READ | extended result codes,
/// sqlite3_vtab_on_conflictstatic const int ) SQLITE_ROLLBACK | result codes.
/// {@category common}
final class SqlError {
/// Successful result
static const int SQLITE_OK = 0;
/// Generic error
static const int SQLITE_ERROR = 1;
/// Internal logic error in SQLite
static const int SQLITE_INTERNAL = 2;
/// Access permission denied
static const int SQLITE_PERM = 3;
/// Callback routine requested an abort
static const int SQLITE_ABORT = 4;
/// The database file is locked
static const int SQLITE_BUSY = 5;
/// A table in the database is locked
static const int SQLITE_LOCKED = 6;
/// A mallocstatic const int ) failed
static const int SQLITE_NOMEM = 7;
/// Attempt to write a readonly database
static const int SQLITE_READONLY = 8;
/// Operation terminated by sqlite3_interruptstatic const int )
static const int SQLITE_INTERRUPT = 9;
/// Some kind of disk I/O error occurred
static const int SQLITE_IOERR = 10;
/// The database disk image is malformed
static const int SQLITE_CORRUPT = 11;
/// Unknown opcode in sqlite3_file_controlstatic const int )
static const int SQLITE_NOTFOUND = 12;
/// Insertion failed because database is full
static const int SQLITE_FULL = 13;
/// Unable to open the database file
static const int SQLITE_CANTOPEN = 14;
/// Database lock protocol error
static const int SQLITE_PROTOCOL = 15;
/// Internal use only
static const int SQLITE_EMPTY = 16;
/// The database schema changed
static const int SQLITE_SCHEMA = 17;
/// String or BLOB exceeds size limit
static const int SQLITE_TOOBIG = 18;
/// Abort due to constraint violation
static const int SQLITE_CONSTRAINT = 19;
/// Data type mismatch
static const int SQLITE_MISMATCH = 20;
/// Library used incorrectly
static const int SQLITE_MISUSE = 21;
/// Uses OS features not supported on host
static const int SQLITE_NOLFS = 22;
/// Authorization denied
static const int SQLITE_AUTH = 23;
/// Not used
static const int SQLITE_FORMAT = 24;
/// 2nd parameter to sqlite3_bind out of range
static const int SQLITE_RANGE = 25;
/// File opened that is not a database file
static const int SQLITE_NOTADB = 26;
/// Notifications from sqlite3_logstatic const int )
static const int SQLITE_NOTICE = 27;
/// Warnings from sqlite3_logstatic const int )
static const int SQLITE_WARNING = 28;
/// sqlite3_stepstatic const int ) has another row ready
static const int SQLITE_ROW = 100;
/// sqlite3_stepstatic const int ) has finished executing
static const int SQLITE_DONE = 101;
}
/// Extended Result Codes, https://www.sqlite.org/rescode.html
///
/// Result codes are signed 32-bit integers. The least significant 8 bits of the result code define a broad category and are called the "primary result code". More significant bits provide more detailed information about the error and are called the "extended result code"
///
/// Note that the primary result code is always a part of the extended result code. Given a full 32-bit extended result code, the application can always find the corresponding primary result code merely by extracting the least significant 8 bits of the extended result code.
///
/// All extended result codes are also error codes. Hence the terms "extended result code" and "extended error code" are interchangeable.
/// {@category common}
final class SqlExtendedError {
/// The sqlite3_load_extension() interface loads an extension into a single database connection.
///
/// The default behavior is for that extension to be automatically unloaded when the database connection closes. However, if the extension entry point returns SQLITE_OK_LOAD_PERMANENTLY instead of SQLITE_OK, then the extension remains loaded into the process address space after the database connection closes. In other words, the xDlClose methods of the sqlite3_vfs object is not called for the extension when the database connection closes.
///
/// The SQLITE_OK_LOAD_PERMANENTLY return code is useful to loadable extensions that register new VFSes, for example.
static const int SQLITE_OK_LOAD_PERMANENTLY = 256;
/// The SQLITE_ERROR_MISSING_COLLSEQ result code means that an SQL statement could not be prepared because a collating sequence named in that SQL statement could not be located.
///
/// Sometimes when this error code is encountered, the sqlite3_prepare_v2static const int ) routine will convert the error into SQLITE_ERROR_RETRY and try again to prepare the SQL statement using a different query plan that does not require the use of the unknown collating sequence.
static const int SQLITE_ERROR_MISSING_COLLSEQ = 257;
/// The SQLITE_BUSY_RECOVERY error code is an extended error code for SQLITE_BUSY that indicates that an operation could not continue because another process is busy recovering a WAL mode database file following a crash. The SQLITE_BUSY_RECOVERY error code only occurs on WAL mode databases.
static const int SQLITE_BUSY_RECOVERY = 261;
/// The SQLITE_LOCKED_SHAREDCACHE result code indicates that access to an SQLite data record is blocked by another database connection that is using the same record in shared cache mode.
///
/// When two or more database connections share the same cache and one of the connections is in the middle of modifying a record in that cache, then other connections are blocked from accessing that data while the modifications are on-going in order to prevent the readers from seeing a corrupt or partially completed change.
static const int SQLITE_LOCKED_SHAREDCACHE = 262;
/// The SQLITE_READONLY_RECOVERY error code is an extended error code for SQLITE_READONLY. The SQLITE_READONLY_RECOVERY error code indicates that a WAL mode database cannot be opened because the database file needs to be recovered and recovery requires write access but only read access is available.
static const int SQLITE_READONLY_RECOVERY = 264;
/// The SQLITE_IOERR_READ error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to read from a file on disk. This error might result from a hardware malfunction or because a filesystem came unmounted while the file was open.
static const int SQLITE_IOERR_READ = 266;
/// The SQLITE_CORRUPT_VTAB error code is an extended error code for SQLITE_CORRUPT used by virtual tables. A virtual table might return SQLITE_CORRUPT_VTAB to indicate that content in the virtual table is corrupt.
static const int SQLITE_CORRUPT_VTAB = 267;
/// The SQLITE_CANTOPEN_NOTEMPDIR error code is no longer used.
static const int SQLITE_CANTOPEN_NOTEMPDIR = 270;
/// The SQLITE_CONSTRAINT_CHECK error code is an extended error code for SQLITE_CONSTRAINT indicating that a CHECK constraint failed.
static const int SQLITE_CONSTRAINT_CHECK = 275;
/// The SQLITE_NOTICE_RECOVER_WAL result code is passed to the callback of sqlite3_logstatic const int ) when a WAL mode database file is recovered.
static const int SQLITE_NOTICE_RECOVER_WAL = 283;
/// The SQLITE_WARNING_AUTOINDEX result code is passed to the callback of sqlite3_logstatic const int ) whenever automatic indexing is used. This can serve as a warning to application designers that the database might benefit from additional indexes.
static const int SQLITE_WARNING_AUTOINDEX = 284;
/// The SQLITE_ERROR_RETRY is used internally to provoke sqlite3_prepare_v2static const int ) static const int or one of its sibling routines for creating prepared statements) to try again to prepare a statement that failed with an error on the previous attempt.
static const int SQLITE_ERROR_RETRY = 513;
/// The SQLITE_ABORT_ROLLBACK error code is an extended error code for SQLITE_ABORT indicating that an SQL statement aborted because the transaction that was active when the SQL statement first started was rolled back. Pending write operations always fail with this error when a rollback occurs. A ROLLBACK will cause a pending read operation to fail only if the schema was changed within the transaction being rolled back.
static const int SQLITE_ABORT_ROLLBACK = 516;
/// The SQLITE_BUSY_SNAPSHOT error code is an extended error code for SQLITE_BUSY that occurs on WAL mode databases when a database connection tries to promote a read transaction into a write transaction but finds that another database connection has already written to the database and thus invalidated prior reads.
///
///
/// The following scenario illustrates how an SQLITE_BUSY_SNAPSHOT error might arise:
///
/// Process A starts a read transaction on the database and does one or more SELECT statement. Process A keeps the transaction open.
///
/// Process B updates the database, changing values previous read by process A.
///
/// Process A now tries to write to the database. But process A's view of the database content is now obsolete because process B has modified the database file after process A read from it. Hence process A gets an SQLITE_BUSY_SNAPSHOT error.
static const int SQLITE_BUSY_SNAPSHOT = 517;
/// The SQLITE_LOCKED_VTAB result code is not used by the SQLite core, but it is available for use by extensions. Virtual table implementations can return this result code to indicate that they cannot complete the current operation because of locks held by other threads or processes.
/// The R-Tree extension returns this result code when an attempt is made to update the R-Tree while another prepared statement is actively reading the R-Tree.
///
/// The update cannot proceed because any change to an R-Tree might involve reshuffling and rebalancing of nodes, which would disrupt read cursors, causing some rows to be repeated and other rows to be omitted.
static const int SQLITE_LOCKED_VTAB = 518;
/// The SQLITE_READONLY_CANTLOCK error code is an extended error code for SQLITE_READONLY. The SQLITE_READONLY_CANTLOCK error code indicates that SQLite is unable to obtain a read lock on a WAL mode database because the shared-memory file associated with that database is read-only.
static const int SQLITE_READONLY_CANTLOCK = 520;
/// The SQLITE_IOERR_SHORT_READ error code is an extended error code for SQLITE_IOERR indicating that a read attempt in the VFS layer was unable to obtain as many bytes as was requested. This might be due to a truncated file.
static const int SQLITE_IOERR_SHORT_READ = 522;
/// The SQLITE_CORRUPT_SEQUENCE result code means that the schema of the sqlite_sequence table is corrupt. The sqlite_sequence table is used to help implement the AUTOINCREMENT feature. The sqlite_sequence table should have the following format:
///
/// CREATE TABLE sqlite_sequencestatic const int name,seq);
///
/// If SQLite discovers that the sqlite_sequence table has any other format, it returns the SQLITE_CORRUPT_SEQUENCE error.
static const int SQLITE_CORRUPT_SEQUENCE = 523;
/// The SQLITE_CANTOPEN_ISDIR error code is an extended error code for SQLITE_CANTOPEN indicating that a file open operation failed because the file is really a directory.
static const int SQLITE_CANTOPEN_ISDIR = 526;
/// The SQLITE_CONSTRAINT_COMMITHOOK error code is an extended error code for SQLITE_CONSTRAINT indicating that a commit hook callback returned non-zero that thus caused the SQL statement to be rolled back.
static const int SQLITE_CONSTRAINT_COMMITHOOK = 531;
/// The SQLITE_NOTICE_RECOVER_ROLLBACK result code is passed to the callback of sqlite3_logstatic const int ) when a hot journal is rolled back.
static const int SQLITE_NOTICE_RECOVER_ROLLBACK = 539;
/// The SQLITE_ERROR_SNAPSHOT result code might be returned when attempting to start a read transaction on an historical version of the database by using the sqlite3_snapshot_openstatic const int ) interface.
///
/// If the historical snapshot is no longer available, then the read transaction will fail with the SQLITE_ERROR_SNAPSHOT. This error code is only possible if SQLite is compiled with -DSQLITE_ENABLE_SNAPSHOT.
static const int SQLITE_ERROR_SNAPSHOT = 769;
/// The SQLITE_BUSY_TIMEOUT error code indicates that a blocking Posix advisory file lock request in the VFS layer failed due to a timeout. Blocking Posix advisory locks are only available as a proprietary SQLite extension and even then are only supported if SQLite is compiled with the SQLITE_EANBLE_SETLK_TIMEOUT compile-time option.
static const int SQLITE_BUSY_TIMEOUT = 773;
/// The SQLITE_READONLY_ROLLBACK error code is an extended error code for SQLITE_READONLY. The SQLITE_READONLY_ROLLBACK error code indicates that a database cannot be opened because it has a hot journal that needs to be rolled back but cannot because the database is readonly.
static const int SQLITE_READONLY_ROLLBACK = 776;
/// The SQLITE_IOERR_WRITE error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to write into a file on disk.
///
/// This error might result from a hardware malfunction or because a filesystem came unmounted while the file was open. This error should not occur if the filesystem is full as there is a separate error code static const int SQLITE_FULL) for that purpose.
static const int SQLITE_IOERR_WRITE = 778;
/// The SQLITE_CORRUPT_INDEX result code means that SQLite detected an entry is or was missing from an index. This is a special case of the SQLITE_CORRUPT error code that suggests that the problem might be resolved by running the REINDEX command, assuming no other problems exist elsewhere in the database file.
static const int SQLITE_CORRUPT_INDEX = 779;
/// The SQLITE_CANTOPEN_FULLPATH error code is an extended error code for SQLITE_CANTOPEN indicating that a file open operation failed because the operating system was unable to convert the filename into a full pathname.
static const int SQLITE_CANTOPEN_FULLPATH = 782;
/// The SQLITE_CONSTRAINT_FOREIGNKEY error code is an extended error code for SQLITE_CONSTRAINT indicating that a foreign key constraint failed.
static const int SQLITE_CONSTRAINT_FOREIGNKEY = 787;
/// The SQLITE_READONLY_DBMOVED error code is an extended error code for SQLITE_READONLY.
///
/// The SQLITE_READONLY_DBMOVED error code indicates that a database cannot be modified because the database file has been moved since it was opened, and so any attempt to modify the database might result in database corruption if the processes crashes because the rollback journal would not be correctly named.
static const int SQLITE_READONLY_DBMOVED = 1032;
/// The SQLITE_IOERR_FSYNC error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to flush previously written content out of OS and/or disk-control buffers and into persistent storage.
///
/// In other words, this code indicates a problem with the fsyncstatic const int ) system call in unix or the FlushFileBuffersstatic const int ) system call in windows.
static const int SQLITE_IOERR_FSYNC = 1034;
/// The SQLITE_CANTOPEN_CONVPATH error code is an extended error code for SQLITE_CANTOPEN used only by Cygwin VFS and indicating that the cygwin_conv_pathstatic const int ) system call failed while trying to open a file. See also: SQLITE_IOERR_CONVPATH
static const int SQLITE_CANTOPEN_CONVPATH = 1038;
/// The SQLITE_CONSTRAINT_FUNCTION error code is not currently used by the SQLite core. However, this error code is available for use by extension functions.
static const int SQLITE_CONSTRAINT_FUNCTION = 1043;
/// The SQLITE_READONLY_CANTINIT result code originates in the xShmMap method of a VFS to indicate that the shared memory region used by WAL mode exists buts its content is unreliable and unusable by the current process since the current process does not have write permission on the shared memory region.
///
/// static const int The shared memory region for WAL mode is normally a file with a "-wal" suffix that is mmapped into the process space. If the current process does not have write permission on that file, then it cannot write into shared memory.)
///
/// Higher level logic within SQLite will normally intercept the error code and create a temporary in-memory shared memory region so that the current process can at least read the content of the database. This result code should not reach the application interface layer.
static const int SQLITE_READONLY_CANTINIT = 1288;
/// The SQLITE_IOERR_DIR_FSYNC error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to invoke fsyncstatic const int ) on a directory.
///
/// The unix VFS attempts to fsyncstatic const int ) directories after creating or deleting certain files to ensure that those files will still appear in the filesystem following a power loss or system crash.
///
/// This error code indicates a problem attempting to perform that fsyncstatic const int ).
static const int SQLITE_IOERR_DIR_FSYNC = 1290;
/// The SQLITE_CANTOPEN_DIRTYWAL result code is not used at this time.
static const int SQLITE_CANTOPEN_DIRTYWAL = 1294;
/// The SQLITE_CONSTRAINT_NOTNULL error code is an extended error code for SQLITE_CONSTRAINT indicating that a NOT NULL constraint failed.
static const int SQLITE_CONSTRAINT_NOTNULL = 1299;
/// The SQLITE_READONLY_DIRECTORY result code indicates that the database is read-only because process does not have permission to create a journal file in the same directory as the database and the creation of a journal file is a prerequisite for writing.
static const int SQLITE_READONLY_DIRECTORY = 1544;
/// The SQLITE_IOERR_TRUNCATE error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to truncate a file to a smaller size.
static const int SQLITE_IOERR_TRUNCATE = 1546;
/// The SQLITE_CANTOPEN_SYMLINK result code is returned by the sqlite3_openstatic const int ) interface and its siblings when the SQLITE_OPEN_NOFOLLOW flag is used and the database file is a symbolic link.
static const int SQLITE_CANTOPEN_SYMLINK = 1550;
/// The SQLITE_CONSTRAINT_PRIMARYKEY error code is an extended error code for SQLITE_CONSTRAINT indicating that a PRIMARY KEY constraint failed.
static const int SQLITE_CONSTRAINT_PRIMARYKEY = 1555;
/// The SQLITE_IOERR_FSTAT error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to invoke fstatstatic const int ) static const int or the equivalent) on a file in order to determine information such as the file size or access permissions.
static const int SQLITE_IOERR_FSTAT = 1802;
/// The SQLITE_CONSTRAINT_TRIGGER error code is an extended error code for SQLITE_CONSTRAINT indicating that a RAISE function within a trigger fired, causing the SQL statement to abort.
static const int SQLITE_CONSTRAINT_TRIGGER = 1811;
/// The SQLITE_IOERR_UNLOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error within xUnlock method on the sqlite3_io_methods object.
static const int SQLITE_IOERR_UNLOCK = 2058;
/// The SQLITE_CONSTRAINT_UNIQUE error code is an extended error code for SQLITE_CONSTRAINT indicating that a UNIQUE constraint failed.
static const int SQLITE_CONSTRAINT_UNIQUE = 2067;
/// The SQLITE_IOERR_UNLOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error within xLock method on the sqlite3_io_methods object while trying to obtain a read lock.
static const int SQLITE_IOERR_RDLOCK = 2314;
/// The SQLITE_CONSTRAINT_VTAB error code is not currently used by the SQLite core. However, this error code is available for use by application-defined virtual tables.
static const int SQLITE_CONSTRAINT_VTAB = 2323;
/// The SQLITE_IOERR_UNLOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error within xDelete method on the sqlite3_vfs object.
static const int SQLITE_IOERR_DELETE = 2570;
/// The SQLITE_CONSTRAINT_ROWID error code is an extended error code for SQLITE_CONSTRAINT indicating that a rowid is not unique.
static const int SQLITE_CONSTRAINT_ROWID = 2579;
/// The SQLITE_IOERR_BLOCKED error code is no longer used.
static const int SQLITE_IOERR_BLOCKED = 2826;
/// The SQLITE_CONSTRAINT_PINNED error code is an extended error code for SQLITE_CONSTRAINT indicating that an UPDATE trigger attempted do delete the row that was being updated in the middle of the update.
static const int SQLITE_CONSTRAINT_PINNED = 2835;
/// The SQLITE_IOERR_NOMEM error code is sometimes returned by the VFS layer to indicate that an operation could not be completed due to the inability to allocate sufficient memory. This error code is normally converted into SQLITE_NOMEM by the higher layers of SQLite before being returned to the application.
static const int SQLITE_IOERR_NOMEM = 3082;
/// The SQLITE_IOERR_ACCESS error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xAccess method on the sqlite3_vfs object.
static const int SQLITE_IOERR_ACCESS = 3338;
/// The SQLITE_IOERR_CHECKRESERVEDLOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xCheckReservedLock method on the sqlite3_io_methods object.
static const int SQLITE_IOERR_CHECKRESERVEDLOCK = 3594;
/// The SQLITE_IOERR_LOCK error code is an extended error code for SQLITE_IOERR indicating an I/O error in the advisory file locking logic. Usually an SQLITE_IOERR_LOCK error indicates a problem obtaining a PENDING lock. However it can also indicate miscellaneous locking errors on some of the specialized VFSes used on Macs.
static const int SQLITE_IOERR_LOCK = 3850;
/// The SQLITE_IOERR_ACCESS error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xClose method on the sqlite3_io_methods object.
static const int SQLITE_IOERR_CLOSE = 4106;
/// The SQLITE_IOERR_DIR_CLOSE error code is no longer used.
static const int SQLITE_IOERR_DIR_CLOSE = 4362;
/// The SQLITE_IOERR_SHMOPEN error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xShmMap method on the sqlite3_io_methods object while trying to open a new shared memory segment.
static const int SQLITE_IOERR_SHMOPEN = 4618;
/// The SQLITE_IOERR_SHMSIZE error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xShmMap method on the sqlite3_io_methods object while trying to enlarge a "shm" file as part of WAL mode transaction processing. This error may indicate that the underlying filesystem volume is out of space.
static const int SQLITE_IOERR_SHMSIZE = 4874;
/// The SQLITE_IOERR_SHMLOCK error code is no longer used.
static const int SQLITE_IOERR_SHMLOCK = 5310;
/// The SQLITE_IOERR_SHMMAP error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xShmMap method on the sqlite3_io_methods object while trying to map a shared memory segment into the process address space.
static const int SQLITE_IOERR_SHMMAP = 5386;
/// The SQLITE_IOERR_SEEK error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xRead or xWrite methods on the sqlite3_io_methods object while trying to seek a file descriptor to the beginning point of the file where the read or write is to occur.
static const int SQLITE_IOERR_SEEK = 5642;
/// The SQLITE_IOERR_DELETE_NOENT error code is an extended error code for SQLITE_IOERR indicating that the xDelete method on the sqlite3_vfs object failed because the file being deleted does not exist.
static const int SQLITE_IOERR_DELETE_NOENT = 5898;
/// The SQLITE_IOERR_MMAP error code is an extended error code for SQLITE_IOERR indicating an I/O error within the xFetch or xUnfetch methods on the sqlite3_io_methods object while trying to map or unmap part of the database file into the process address space.
static const int SQLITE_IOERR_MMAP = 6154;
/// The SQLITE_IOERR_GETTEMPPATH error code is an extended error code for SQLITE_IOERR indicating that the VFS is unable to determine a suitable directory in which to place temporary files.
static const int SQLITE_IOERR_GETTEMPPATH = 6410;
/// The SQLITE_IOERR_CONVPATH error code is an extended error code for SQLITE_IOERR used only by Cygwin VFS and indicating that the cygwin_conv_pathstatic const int ) system call failed. See also: SQLITE_CANTOPEN_CONVPATH
static const int SQLITE_IOERR_CONVPATH = 6666;
/// The SQLITE_IOERR_VNODE error code is a code reserved for use by extensions. It is not used by the SQLite core.
static const int SQLITE_IOERR_VNODE = 6922;
/// The SQLITE_IOERR_AUTH error code is a code reserved for use by extensions. It is not used by the SQLite core.
static const int SQLITE_IOERR_AUTH = 7178;
/// The SQLITE_IOERR_BEGIN_ATOMIC error code indicates that the underlying operating system reported and error on the SQLITE_FCNTL_BEGIN_ATOMIC_WRITE file-control. This only comes up when SQLITE_ENABLE_ATOMIC_WRITE is enabled and the database is hosted on a filesystem that supports atomic writes.
static const int SQLITE_IOERR_BEGIN_ATOMIC = 7434;
/// The SQLITE_IOERR_COMMIT_ATOMIC error code indicates that the underlying operating system reported and error on the SQLITE_FCNTL_COMMIT_ATOMIC_WRITE file-control. This only comes up when SQLITE_ENABLE_ATOMIC_WRITE is enabled and the database is hosted on a filesystem that supports atomic writes.
static const int SQLITE_IOERR_COMMIT_ATOMIC = 7690;
/// The SQLITE_IOERR_ROLLBACK_ATOMIC error code indicates that the underlying operating system reported and error on the SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE file-control. This only comes up when SQLITE_ENABLE_ATOMIC_WRITE is enabled and the database is hosted on a filesystem that supports atomic writes.
static const int SQLITE_IOERR_ROLLBACK_ATOMIC = 7946;
/// The SQLITE_IOERR_DATA error code is an extended error code for SQLITE_IOERR used only by checksum VFS shim to indicate that the checksum on a page of the database file is incorrect.
static const int SQLITE_IOERR_DATA = 8202;
}
/// Flags for file open operations, https://www.sqlite.org/c3ref/c_open_autoproxy.html
/// Flags For File Open Operations
///
/// These bit values are intended for use in the
/// 3rd parameter to the [sqlite3_open_v2static const int )] interface and
/// in the 4th parameter to the `xopen` method.
/// {@category common}
final class SqlFlag {
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_READONLY = 0x00000001;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_READWRITE = 0x00000002;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_CREATE = 0x00000004;
/// VFS only
static const int SQLITE_OPEN_DELETEONCLOSE = 0x00000008;
/// VFS only
static const int SQLITE_OPEN_EXCLUSIVE = 0x00000010;
/// VFS only
static const int SQLITE_OPEN_AUTOPROXY = 0x00000020;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_URI = 0x00000040;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_MEMORY = 0x00000080;
/// VFS only
static const int SQLITE_OPEN_MAIN_DB = 0x00000100;
/// VFS only
static const int SQLITE_OPEN_TEMP_DB = 0x00000200;
/// VFS only
static const int SQLITE_OPEN_TRANSIENT_DB = 0x00000400;
/// VFS only
static const int SQLITE_OPEN_MAIN_JOURNAL = 0x00000800;
/// VFS only
static const int SQLITE_OPEN_TEMP_JOURNAL = 0x00001000;
/// VFS only
static const int SQLITE_OPEN_SUBJOURNAL = 0x00002000;
/// VFS only
static const int SQLITE_OPEN_MASTER_JOURNAL = 0x00004000;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_NOMUTEX = 0x00008000;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_FULLMUTEX = 0x00010000;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_SHAREDCACHE = 0x00020000;
/// Ok for sqlite3_open_v2static const int )
static const int SQLITE_OPEN_PRIVATECACHE = 0x00040000;
/// VFS only
static const int SQLITE_OPEN_WAL = 0x00080000;
}
/// Prepare flags, https://www.sqlite.org/c3ref/c_prepare_normalize.html
///
/// {@category common}
final class SqlPrepareFlag {
///The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner that the prepared statement will be retained for a long time and probably reused many times.
/// Without this flag, sqlite3_prepare_v3static const int ) and sqlite3_prepare16_v3static const int ) assume that the prepared statement will be used just once or at most a few times and then destroyed using sqlite3_finalizestatic const int ) relatively soon.
/// The current implementation acts on this hint by avoiding the use of lookaside memory so as not to deplete the limited store of lookaside memory.
///Future versions of SQLite may act on this hint differently.
static const int SQLITE_PREPARE_PERSISTENT = 0x01;
///The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used to be required for any prepared statement that wanted to use the sqlite3_normalized_sqlstatic const int ) interface.
/// However, the sqlite3_normalized_sqlstatic const int ) interface is now available to all prepared statements, regardless of whether or not they use this flag.
static const int SQLITE_PREPARE_NORMALIZE = 0x02;
///the SQL compiler to return an error static const int error code SQLITE_ERROR) if the statement uses any virtual tables
static const int SQLITE_PREPARE_NO_VTAB = 0x04;
}
/// Datatypes, https://sqlite.org/c3ref/c_blob.html
///
/// {@category common}
final class SqlType {
static const int SQLITE_INTEGER = 1;
static const int SQLITE_FLOAT = 2;
static const int SQLITE_TEXT = 3;
static const int SQLITE_BLOB = 4;
static const int SQLITE_NULL = 5;
}
/// Text Encodings, https://www.sqlite.org/c3ref/c_any.html
/// These constant define integer codes that represent the various text encodings supported by SQLite.
///
/// {@category common}
final class SqlTextEncoding {
///IMP: R-37514-35566
static const int SQLITE_UTF8 = 1;
///IMP: R-03371-37637
static const int SQLITE_UTF16LE = 2;
///IMP: R-51971-34154
static const int SQLITE_UTF16BE = 3;
///Use native byte order
static const int SQLITE_UTF16 = 4;
///Deprecated
static const int SQLITE_ANY = 5;
///qlite3_create_collation only
static const int SQLITE_UTF16_ALIGNED = 8;
}
/// File lock levels, https://www.sqlite.org/c3ref/c_lock_exclusive.html
///
/// {@category common}
final class SqlFileLockingLevels {
static const SQLITE_LOCK_NONE = 0;
static const SQLITE_LOCK_SHARED = 1;
static const SQLITE_LOCK_RESERVED = 2;
static const SQLITE_LOCK_PENDING = 3;
static const SQLITE_LOCK_EXCLUSIVE = 4;
}
/// Special destructors, https://www.sqlite.org/c3ref/c_static.html
///
/// {@category common}
final class SqlSpecialDestructor {
/// it means that the content pointer is constant and will never change, It does not need to be destroyed
static const SQLITE_STATIC = 0;
///The SQLITE_TRANSIENT value means that the content will likely change in the near future
/// and that SQLite should make its own private copy of the content before returning.
static const SQLITE_TRANSIENT = -1;
}
/// Function flags, https://www.sqlite.org/c3ref/c_deterministic.html
///
/// {@category common}
final class SqlFunctionFlag {
/// The SQLITE_DETERMINISTIC flag means that the new function always gives the same output when the input parameters are the same
static const SQLITE_DETERMINISTIC = 0x000000800;
///he SQLITE_DIRECTONLY flags is a security feature which is recommended for all application-defined SQL functions,
/// and especially for functions that have side-effects or that could potentially leak sensitive information.
static const SQLITE_DIRECTONLY = 0x000080000;
///The SQLITE_SUBTYPE flag indicates to SQLite that a function may call sqlite3_value_subtypestatic const int ) to inspect the sub-types of its arguments.
static const SQLITE_SUBTYPE = 0x000100000;
/// The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call sqlite3_result_subtype to cause a sub-type to be associated with its result.
static const SQLITE_RESULT_SUBTYPE = 0x001000000;
///The SQLITE_INNOCUOUS flag means that the function is unlikely to cause problems even if misused.
static const SQLITE_INNOCUOUS = 0x000200000;
}
final class SqlDeviceCharacteristics {
static const SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 0x00000800;
}
const SQLITE_DELETE = 9;
const SQLITE_INSERT = 18;
const SQLITE_UPDATE = 23;
final bigIntMinValue64 = BigInt.parse('-9223372036854775808');
final bigIntMaxValue64 = BigInt.parse('9223372036854775807');
// Connection config options https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
const SQLITE_DBCONFIG_DQS_DML = 1013;
const SQLITE_DBCONFIG_DQS_DDL = 1014;
================================================
FILE: sqlite3/lib/src/database.dart
================================================
import 'functions.dart';
import 'result_set.dart';
import 'statement.dart';
import 'constants.dart';
/// An opened sqlite3 database.
///
/// {@category common}
abstract class CommonDatabase {
/// Configuration for the database connection.
///
/// __Note__: On the web, the [DatabaseConfig] class only works when using a
/// version of `sqlite3.wasm` shipped with version 2.1.0 of the `sqlite3`
/// Dart package. In previous WASM builds, all setters on the config will
/// throw an exception.
DatabaseConfig get config;
/// The application defined version of this database.
abstract int userVersion;
/// The row id of the most recent successful insert statement on this database
/// connection.
///
/// This does not consider `WITHOUT ROWID` tables and won't reliably detect
/// inserts made by triggers. For details, see the [sqlite3 docs](https://sqlite.org/c3ref/last_insert_rowid.html).
int get lastInsertRowId;
/// The amount of rows inserted, updated or deleted by the last `INSERT`,
/// `UPDATE` or `DELETE` statement, respectively.
///
/// For more details, see the [sqlite3 docs](https://sqlite.org/c3ref/changes.html).
int get updatedRows;
/// The amount of rows affected by the last `INSERT`, `UPDATE` or `DELETE`
/// statement.
@Deprecated('Use updatedRows instead')
int getUpdatedRows();
/// An async stream of data changes happening on this database.
///
/// Listening to this stream will register an "update hook" on the native
/// database. Each update that sqlite3 reports through that hook will then
/// be added to the stream.
///
/// Note that the stream reports updates _asynchronously_, e.g. one event
/// loop iteration after sqlite reports them.
/// Also, be aware that not every update to the database will be reported.
/// In particular, updates to internal system tables like `sqlite_sequence`
/// are not reported. Further, updates to `WITHOUT ROWID` tables or truncating
/// deletes (without a `WHERE` clause) will not report updates either.
///
/// See also:
/// - [Data Change Notification Callbacks](https://www.sqlite.org/c3ref/update_hook.html)
/// - [updatesSync], a synchronous stream.
Stream get updates;
/// A _synchronous_ stream of data changes happening on this database.
///
/// This stream behaves similarly to [updates], except that listeners are
/// invoked synchronously (before the update completes).
///
/// The purpose of this stream is to avoid a large internal buffer when a
/// transaction updates a large amount of rows - instead, the updates can be
/// handled one-by-one with this.
///
/// It is crucial that listeners on this stream don't modify the database.
Stream get updatesSync;
/// The [VoidPredicate] that is used to filter out transactions before commiting.
///
/// This is run before every commit, i.e. before the end of an explicit
/// transaction and before the end of an implicit transactions created by
/// an insert / update / delete operation.
///
/// If the filter returns `false`, the commit is converted into a rollback.
///
/// The function should not do anything that modifies the database connection,
/// e.g. run SQL statements, prepare statements or step.
///
/// See also:
/// - [Commit Hooks](https://www.sqlite.org/c3ref/commit_hook.html)
VoidPredicate? get commitFilter;
set commitFilter(VoidPredicate? commitFilter);
/// An async stream that fires after each commit.
///
/// Listening to this stream will register a "commit hook" on the native
/// database. Each commit that sqlite3 reports through that hook will then
/// be added to the stream.
///
/// Note that the stream reports updates _asynchronously_, e.g. one event
/// loop iteration after sqlite reports them.
///
/// Also note this works in conjunction with `commitFilter`. If the filter
/// function is not null and returns `false`, the commit will not occur and
/// this stream will not fire.
///
/// See also:
/// - [Commit Hooks](https://www.sqlite.org/c3ref/commit_hook.html)
Stream get commits;
/// An async stream that fires after each rollback.
///
/// Listening to this stream will register a "rollback hook" on the native
/// database. Each rollback that sqlite3 reports through that hook will then
/// be added to the stream.
///
/// Note that the stream reports updates _asynchronously_, e.g. one event
/// loop iteration after sqlite reports them.
///
/// See also:
/// - [Commit Hooks](https://www.sqlite.org/c3ref/commit_hook.html)
Stream get rollbacks;
/// Executes the [sql] statement(s) with the provided [parameters], ignoring
/// any rows returned by the statement(s).
///
/// For the types supported in [parameters], see [StatementParameters].
/// To view rows returned by a statement, run it with [select]. Statements
/// that aren't `SELECT`s in SQL but still return rows (such as updates with
/// a `RETURNING` clause) can still be safely executed with [select].
///
/// When no [parameters] are passed to [execute], [sql] is allowed to contain
/// multiple SQL statements (separated by a semicolon). Those statements will
/// be executed in order, but [execute] will not start a transaction for them
/// automatically. If any statement fails, that exception will be thrown and
/// subsequent statements will not be executed.
void execute(String sql, [List parameters = const []]);
/// Prepares the [sql] statement and runs it with the provided [parameters],
/// returning all rows returned by the statement.
///
/// For the types supported in [parameters], see [StatementParameters].
/// The statement doesn't have to be an SQL `SELECT` statement. Any statement
/// that returns rows (e.g. writes with a `RETURNING` clause) can be executed
/// with [select].
///
/// This method fully runs the statement, buffers all rows and then returns
/// them at once in a [ResultSet]. This package also supports stepping through
/// a result set row-by-row. To do that, first prepare the statement with
/// [prepare] and then call [CommonPreparedStatement.iterateWith].
ResultSet select(String sql, [List parameters = const []]);
/// Compiles the [sql] statement to execute it later.
///
/// The [persistent] flag can be used as a hint to the query planner that the
/// statement will be retained for a long time and probably reused many times.
/// Without this flag, sqlite assumes that the prepared statement will be used
/// just once or at most a few times before [CommonPreparedStatement.close]
/// is called.
/// If [vtab] is disabled (it defaults to `true`) and the statement references
/// a virtual table, [prepare] throws an exception.
/// For more information on the optional parameters, see
/// [the sqlite documentation](https://www.sqlite.org/c3ref/c_prepare_normalize.html)
/// If [checkNoTail] is enabled (it defaults to `false`) and the [sql] string
/// contains trailing data, an exception will be thrown and the statement will
/// not be executed.
CommonPreparedStatement prepare(
String sql, {
bool persistent = false,
bool vtab = true,
bool checkNoTail = false,
});
/// Compiles multiple statements from [sql] to be executed later.
///
/// Unlike [prepare], which can only compile a single statement,
/// [prepareMultiple] will return multiple statements if the source [sql]
/// string contains more than one statement.
/// For example, calling [prepareMultiple] with `SELECT 1; SELECT 2;` will
/// return `2` prepared statements.
///
/// For the [persistent] and [vtab] parameters, see [prepare].
List prepareMultiple(
String sql, {
bool persistent = false,
bool vtab = true,
});
/// Creates a collation that can be used from sql queries sent against
/// this database.
///
/// The [name] defines the (case insensitive) name of the collating in
/// sql. The utf8 encoding of [name] must not exceed a length of 255
/// bytes.
///
/// The [function] can be any Dart closure, it's not restricted to top-level
/// functions supported by `Pointer.fromFunction`. For more details on how
/// the sql function behaves, see the documentation on [CollatingFunction].
/// As it is a compare function, the [function] must return an integer value, and
/// receives two string parameters (**A** & **B**). [function] will return 0
/// if **A** and **B**
/// are considered equals. A negative value is returned if **A** is less than **B**,
/// but a positive if **A** is greater than **B**.
///
///
///
/// For more information, see https://www.sqlite.org/c3ref/create_collation.html.
void createCollation({
required String name,
required CollatingFunction function,
});
/// Creates a scalar function that can be called from sql queries sent against
/// this database.
///
/// The [functionName] defines the (case insensitive) name of the function in
/// sql. The utf8 encoding of [functionName] must not exceed a length of 255
/// bytes.
///
/// {@template sqlite3_function_flags}
/// The [argumentCount] parameter can be used to declare how many arguments a
/// function supports. If you need a function that can use multiple argument
/// counts, you can call [createFunction] multiple times.
/// The [deterministic] flag (defaults to `false`) can be set to indicate that
/// the function always gives the same output when the input parameters are
/// the same. This is a requirement for functions that are used in generated
/// columns or partial indexes. It also allows the query planner for optimize
/// by factoring invocations out of inner loops.
/// The [directOnly] flag (defaults to `true`) is a security measure. When
/// enabled, the function may only be invoked form top-level SQL, and cannot
/// be used in VIEWs or TRIGGERs nor in schema structures (such as CHECK,
/// DEFAULT, etc.). When [directOnly] is set to `false`, the function might
/// be invoked when opening a malicious database file. sqlite3 recommends
/// this flag for all application-defined functions, especially if they have
/// side-effects or if they could potentially leak sensitive information.
///
/// The [subtype] flag (defaults to `false`) indicates that the function can
/// receive subtypes in arguments (meaning that [SqliteArguments.subtypeOf]
/// can be used) and that the function can return values with subtypes (by
/// returning an [SubtypedValue]).
/// {@endtemplate}
///
/// The [function] can be any Dart closure, it's not restricted to top-level
/// functions supported by `Pointer.fromFunction`. For more details on how
/// the sql function behaves, see the documentation on [ScalarFunction].
///
/// To register aggregate or window functions, see [createAggregateFunction].
///
/// For more information, see https://www.sqlite.org/appfunc.html.
void createFunction({
required String functionName,
required ScalarFunction function,
AllowedArgumentCount argumentCount = const AllowedArgumentCount.any(),
bool deterministic = false,
bool directOnly = true,
bool subtype = false,
});
/// Creates an application-defined aggregate function that can be used from
/// sql queries sent against this database.
///
/// {@macro sqlite3_function_flags}
///
/// For more details on how to write aggregate functions (including an
/// example), see the documentation of [AggregateFunction].
///
/// If the given [function] implements the [WindowFunction] interface, a
/// window function is registered internally. Window functions support being
/// used in `OVER` expressions in sqlite3. For more information on writing
/// window functions in Dart, see the [WindowFunction] class. For details
/// on user-defined window functions in general, see sqlite3's documentation:
/// https://www.sqlite.org/windowfunctions.html#udfwinfunc
void createAggregateFunction({
required String functionName,
required AggregateFunction function,
AllowedArgumentCount argumentCount = const AllowedArgumentCount.any(),
bool deterministic = false,
bool directOnly = true,
bool subtype = false,
});
/// Installs a function to invoke whenever an attempt is made to access a
/// database table when another thread or process has the table locked.
///
/// The argument passed to the [handler] is the amount of times it has
/// previously been invoked for the same locking event.
/// The handler should return `true` if SQLite should make another attempt to
/// access the database, or `false` if SQLite should stop making attempts and
/// return `SQLITE_BUSY`.
///
/// Note that using the `busy_timeout` pragma will overwrite this handler.
///
/// See also: https://www.sqlite.org/c3ref/busy_handler.html
set busyHandler(bool Function(int count)? handler);
/// Checks whether the connection is in autocommit mode. The connection is in
/// autocommit by default, except when inside a transaction.
///
/// For details, see https://www.sqlite.org/c3ref/get_autocommit.html
bool get autocommit;
/// Closes this database and releases associated resources.
@Deprecated('Call close() instead')
void dispose();
/// Closes this database and releases associated resources.
///
/// On native platforms, a native finalizer will also close the connection
/// automatically. On the web, finalizers are less reliable. For this reason,
/// closing databases explicitly is still recommended.
void close();
}
/// The kind of an [SqliteUpdate] received through a [CommonDatabase.updates]
/// stream.
///
/// {@category common}
enum SqliteUpdateKind {
// Note: Changing the order of these fields is a breaking change, as they're
// used in the sqlite3_web protocol.
/// Notification for a new row being inserted into the database.
insert(SQLITE_INSERT),
/// Notification for a row being updated.
update(SQLITE_UPDATE),
/// Notification for a row being deleted.
delete(SQLITE_DELETE);
/// The raw code to identify this update kind.
final int code;
const SqliteUpdateKind(this.code);
/// Attempts to extract a [SqliteUpdateKind] from the raw [flags].
static SqliteUpdateKind? fromCode(int code) {
return switch (code) {
SQLITE_INSERT => insert,
SQLITE_UPDATE => update,
SQLITE_DELETE => delete,
_ => null,
};
}
}
/// A data change notification from sqlite.
///
/// {@category common}
final class SqliteUpdate {
/// The kind of write being reported.
final SqliteUpdateKind kind;
/// The table on which the update has happened.
final String tableName;
/// The id of the inserted, modified or deleted row.
final int rowId;
SqliteUpdate(this.kind, this.tableName, this.rowId);
@override
int get hashCode => Object.hash(kind, tableName, rowId);
@override
bool operator ==(Object other) {
return other is SqliteUpdate &&
other.kind == kind &&
other.tableName == tableName &&
other.rowId == rowId;
}
@override
String toString() {
return 'SqliteUpdate: $kind on $tableName, rowid = $rowId';
}
}
/// Make configuration changes to the database connection.
///
/// More information: https://www.sqlite.org/c3ref/db_config.html
/// Available options are documented in https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
///
/// {@category common}
abstract base class DatabaseConfig {
/// Update configuration that accepts an int value.
/// Would throw when the internal C call returns a non-zero value.
void setIntConfig(int key, int configValue);
/// Enable or disable SQLite support for double quotes as string literals.
///
/// More information: https://www.sqlite.org/compile.html#dqs
set doubleQuotedStringLiterals(bool value) {
final dqsValue = value ? 1 : 0;
setIntConfig(SQLITE_DBCONFIG_DQS_DML, dqsValue);
setIntConfig(SQLITE_DBCONFIG_DQS_DDL, dqsValue);
}
}
================================================
FILE: sqlite3/lib/src/exception.dart
================================================
import 'dart:typed_data';
/// Thrown by sqlite methods.
///
/// This is the only exception thrown by `package:sqlite3`. Additionally, errors
/// might be thrown on api misuse.
///
/// {@category common}
final class SqliteException implements Exception {
/// An error message indicating what went wrong.
final String message;
/// An optional explanation providing more detail on what went wrong.
final String? explanation;
/// SQLite extended result code.
///
/// As defined in https://sqlite.org/rescode.html, it represents an error
/// code, providing some idea of the cause of the failure.
final int extendedResultCode;
/// SQLite primary result code.
///
/// As defined in https://sqlite.org/rescode.html, it represents an error
/// code, providing some idea of the cause of the failure.
int get resultCode => extendedResultCode & 0xFF;
/// If this error is related to a syntex error in SQL, contains the byte
/// offset of the token associated with the error.
final int? offset;
/// An informal description of what the `sqlite3` package was attempting to do
/// when the exception occured, e.g. "preparing a statement",
/// "opening the database".
final String? operation;
/// The SQL statement triggering this exception.
///
/// This may be null when no prior statement is known.
final String? causingStatement;
/// If this exception has a [causingStatement], this list contains the
/// parameters used to run that statement.
final List? parametersToStatement;
SqliteException({
required this.extendedResultCode,
required this.message,
this.explanation,
this.causingStatement,
this.parametersToStatement,
this.operation,
this.offset,
});
@override
String toString() {
final buffer = StringBuffer('SqliteException(')
..write(extendedResultCode)
..write('): ')
..write(operation == null ? '' : 'while $operation, ')
..write(message);
if (explanation != null) {
buffer
..write(', ')
..write(explanation);
}
if (causingStatement != null) {
buffer
..writeln()
..write(' Causing statement')
..write(offset != null ? ' (at position $offset): ' : ': ')
..write(causingStatement);
if (parametersToStatement != null) {
final params = parametersToStatement!
.map((e) {
if (e is Uint8List) {
return 'blob (${e.length} bytes)';
} else {
return e.toString();
}
})
.join(', ');
buffer.write(', parameters: $params');
}
}
return buffer.toString();
}
}
================================================
FILE: sqlite3/lib/src/ffi/api.dart
================================================
import 'dart:ffi';
import '../database.dart';
import '../sqlite3.dart';
import '../statement.dart';
import 'libsqlite3.g.dart' as libsqlite3;
import 'implementation.dart';
/// Provides access to `sqlite3` functions, such as opening new databases.
///
/// {@category native}
const Sqlite3 sqlite3 = FfiSqlite3();
/// Provides access to `sqlite3` functions, such as opening new databases.
///
/// {@category native}
abstract interface class Sqlite3 implements CommonSqlite3 {
@override
Database open(
String filename, {
String? vfs,
OpenMode mode = OpenMode.readWriteCreate,
bool uri = false,
bool? mutex,
});
/// Creates a [Database] from an opened sqlite3 database connection.
///
/// The [database] must be a pointer towards an open sqlite3 database
/// connection [handle](https://www.sqlite.org/c3ref/sqlite3.html).
///
/// When [borrowed] is set (it defaults to `false`), the returned [Database]
/// connection acts as a view of the underlying `sqlite3*` pointer. The
/// library will not attach a native finalizer calling `sqlite3_close_v2`, and
/// calling [Database.close] in it will only prevent further interactions from
/// Dart.
Database fromPointer(Pointer database, {bool borrowed = false});
@override
Database openInMemory({String? vfs});
/// Opens a new in-memory database and copies another database into it
/// https://www.sqlite.org/c3ref/backup_finish.html
Database copyIntoMemory(Database restoreFrom);
/// Loads an extensions through the `sqlite3_auto_extension` mechanism.
///
/// For a more in-depth discussion, including links to an example, see the
/// documentation for [SqliteExtension].
void ensureExtensionLoaded(SqliteExtension extension);
/// Whether the option, specified by its name, was defined at compile-time.
///
/// The `SQLITE_` prefix may be omitted from the option [name].
///
/// See also: https://sqlite.org/c3ref/compileoption_get.html
bool usedCompileOption(String name);
/// An iterable over the list of options that were defined at compile time.
///
/// See also: https://sqlite.org/c3ref/compileoption_get.html
Iterable get compileOptions;
/// A function pointer to `sqlite3_close_v2`.
///
/// This typically shouldn't be used directly since this library attaches
/// native finalizers to databases by default, but can be used for custom
/// connection management if necessary.
///
/// See also: https://sqlite.org/c3ref/close.html
@Deprecated("Import 'package:sqlite3/unstable/ffi_bindings.dart' instead")
static Pointer)>>
get sqliteCloseV2 => libsqlite3.addresses.sqlite3_close_v2.cast();
}
/// Information used to load an extension through `sqlite3_auto_extension`,
/// exposed by [Sqlite3.ensureExtensionLoaded].
///
/// Note that this feature is __not__ a direct wrapper around sqlite3's dynamic
/// extension loading mechanism. In sqlite3 builds created through
/// `sqlite3_flutter_libs`, dynamic extensions are omitted from sqlite3 due to
/// security concerns.
///
/// However, if you want to manually load extensions, you can do that with a
/// [SqliteExtension] where the entrypoint is already known. This puts the
/// responsibility of dynamically loading code onto you.
///
/// For an example of how to write and load extensions, see
/// - this C file: https://github.com/simolus3/sqlite3.dart/blob/main/sqlite3/test/ffi/test_extension.c
/// - this Dart test loading it: https://github.com/simolus3/sqlite3.dart/blob/a9a379494c6b8d58a3c31cf04fe16e83b49130f1/sqlite3/test/ffi/sqlite3_test.dart#L35
/// - Or, alternatively, this Flutter example: https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3/example/custom_extension
///
/// {@category native}
abstract interface class SqliteExtension {
/// A sqlite extension having the given [extensionEntrypoint] as a function
/// pointer.
///
/// For the exact signature of [extensionEntrypoint], see
/// [sqlite3_auto_extension](https://www.sqlite.org/c3ref/auto_extension.html).
factory SqliteExtension(Pointer extensionEntrypoint) {
return SqliteExtensionImpl(() => extensionEntrypoint);
}
/// A sqlite extension from another library with a given symbol as an
/// entrypoint.
factory SqliteExtension.inLibrary(DynamicLibrary library, String symbol) {
return SqliteExtensionImpl(() => library.lookup(symbol));
}
}
/// An opened sqlite3 database with `dart:ffi`.
///
/// See [CommonDatabase] for the methods that are available on both the FFI and
/// the WebAssembly implementation.
///
/// {@category native}
abstract class Database extends CommonDatabase {
/// The native database connection handle from sqlite.
///
/// This returns a pointer towards the opaque sqlite3 structure as defined
/// [here](https://www.sqlite.org/c3ref/sqlite3.html).
///
/// Note that the connection is still owned by this Dart object, and will be
/// closed once it becomes unreachable. In other words, the returned handle is
/// a logical reference to this object.
/// To transfer ownership of the connection out of this object, use [leak]
/// instead.
Pointer get handle;
/// Like [handle], this returns the native `sqlite3*` pointer wrapped by this
/// instance.
///
/// Additionally, this also detaches native finalizers that would close the
/// connection once this object becomes unreachable.
///
/// This is an advanced and low-level API that can be used to transfer
/// ownership of connections originally opened in Dart to native code.
Pointer leak();
// override for more specific subtype
@override
PreparedStatement prepare(
String sql, {
bool persistent = false,
bool vtab = true,
bool checkNoTail = false,
});
@override
List prepareMultiple(
String sql, {
bool persistent = false,
bool vtab = true,
});
/// Creates a Dart [PreparedStatement] instance from the underlying
/// `sqlite3_stmt` pointer.
///
/// When [borrowed] is set (it defaults to `false`), the returned [Database]
/// connection acts as a view of the underlying `sqlite3_stmt*` pointer. The
/// library will not attach a native finalizer calling `sqlite3_finalize`, and
/// calling [PreparedStatement.close] in it will only prevent further
/// interactions from Dart.
PreparedStatement statementFromPointer({
required Pointer statement,
required String sql,
bool borrowed = false,
});
/// Create a backup of the current database (this) into another database
/// ([toDatabase]) on memory or disk.
///
/// The returned stream returns a rough estimate on the progress of the
/// backup, as a fraction between `0` and `1`. No progress is reported if
/// either this or [toDatabase] is an in-memory database.
///
/// To simply await the backup operation as a future, call [Stream.drain] on
/// the returned stream.
///
/// [nPage] is the number of pages backed-up in each backup step.
/// A larger value increase speed of backup, but will cause other connections to wait
/// longer to aquire locks on the source and destination databases. A value of -1
/// can be used to backup the entire database in a single step.
/// See https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep for details.
///
/// See https://www.sqlite.org/c3ref/backup_finish.html
Stream backup(Database toDatabase, {int nPage = 5});
}
/// A prepared statement.
///
/// {@category native}
abstract class PreparedStatement implements CommonPreparedStatement {
/// The underlying `sqlite3_stmt` pointer.
///
/// Obtains the raw [statement](https://www.sqlite.org/c3ref/stmt.html) from
/// the sqlite3 C-api that this [PreparedStatement] wraps.
///
/// Note that the statement is still owned by this Dart object, and will be
/// finalized once it becomes unreachable. In other words, the returned handle
/// is a logical reference to this object.
/// To transfer ownership of the statement out of this object, use [leak]
/// instead.
Pointer get handle;
/// Like [handle], this returns the native `sqlite3_stmt*` pointer wrapped by
/// this instance.
///
/// Additionally, this also detaches native finalizers that would close the
/// statement once this object becomes unreachable.
///
/// This is an advanced and low-level API that can be used to transfer
/// ownership of statements originally opened in Dart to native code.
Pointer leak();
}
================================================
FILE: sqlite3/lib/src/ffi/bindings.dart
================================================
// ignore_for_file: non_constant_identifier_names
import 'dart:collection';
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart' as ffi;
import '../constants.dart';
import '../exception.dart';
import '../functions.dart';
import '../implementation/bindings.dart';
import '../implementation/exception.dart';
import '../vfs.dart';
import 'libsqlite3.g.dart';
import 'libsqlite3.g.dart' as libsqlite3;
import 'memory.dart';
/// The only instance of [FfiBindings].
///
/// Since bindings are using native assets, these bindings don't hold any state
/// (unlike the WASM bindings, which require a `WebAssembly.Module` reference).
const ffiBindings = FfiBindings._();
// sqlite3_prepare_v3 was added in 3.20.0
const int _firstVersionForV3 = 3020000;
// sqlite3_error_offset was added in 3.38.0
const int _firstVersionForErrorOffset = 3038000;
final supportsPrepareV3 = sqlite3_libversion_number() >= _firstVersionForV3;
final supportsErrorOffset =
sqlite3_libversion_number() >= _firstVersionForErrorOffset;
final databaseFinalizer = NativeFinalizer(addresses.sqlite3_close_v2.cast());
final statementFinalizer = NativeFinalizer(addresses.sqlite3_finalize.cast());
final sessionDeleteFinalizer = NativeFinalizer(
addresses.sqlite3session_delete.cast(),
);
final changesetFinalizeFinalizer = NativeFinalizer(
addresses.sqlite3changeset_finalize.cast(),
);
final hasColumnMetadata =
ffiBindings.sqlite3_compileoption_used('ENABLE_COLUMN_METADATA') != 0;
final _vfsPointers = Expando<_RegisteredVfs>();
Pointer _globalTempDirectory = nullPtr();
final class FfiBindings implements RawSqliteBindings {
const FfiBindings._();
@override
RawSqliteSession sqlite3session_create(RawSqliteDatabase db, String name) {
final dbImpl = db as FfiDatabase;
final namePtr = Utf8Utils.allocateZeroTerminated(name);
final sessionPtr = allocate>();
final result = libsqlite3.sqlite3session_create(
dbImpl.db,
namePtr,
sessionPtr,
);
namePtr.free();
final sessionValue = sessionPtr.value;
sessionPtr.free();
if (result != 0) {
throw createExceptionOutsideOfDatabase(this, result);
}
return FfiSession(sessionValue);
}
@override
int sqlite3changeset_apply(
RawSqliteDatabase database,
Uint8List changeset,
int Function(String tableName)? filter,
int Function(int eConflict, RawChangesetIterator iter) conflict,
) {
final dbImpl = database as FfiDatabase;
final changesetPtr = allocateBytes(changeset);
final ctxPtr = dbImpl.db.cast();
final NativeCallable, Pointer)>?
filterImpl = filter == null
? null
: (NativeCallable.isolateLocal((Pointer ctx, Pointer zTab) {
final tbl = zTab.cast().readString();
return filter(tbl);
}, exceptionalReturn: 1)..keepIsolateAlive = true);
final NativeCallable<
Int Function(Pointer, Int, Pointer)
>
conflictImpl = (NativeCallable.isolateLocal((
Pointer ctx,
int eConflict,
Pointer p,
) {
final iter = FfiChangesetIterator(p, ownsIterator: false);
return conflict(eConflict, iter);
}, exceptionalReturn: 1)..keepIsolateAlive = true);
final result = libsqlite3.sqlite3changeset_apply(
dbImpl.db,
changeset.length,
changesetPtr.cast(),
filterImpl?.nativeFunction ?? nullPtr(),
conflictImpl.nativeFunction,
ctxPtr,
);
changesetPtr.free();
filterImpl?.close();
conflictImpl.close();
return result;
}
@override
RawChangesetIterator sqlite3changeset_start(Uint8List changeset) {
final (asPtr, region) = allocateBytesWithFinalizer(changeset);
final iteratorOut = allocate>();
final result = libsqlite3.sqlite3changeset_start(
iteratorOut,
changeset.length,
asPtr.cast(),
);
final iterator = iteratorOut.value;
iteratorOut.free();
if (result != SqlError.SQLITE_OK) {
asPtr.free();
throw createExceptionOutsideOfDatabase(this, result);
}
return FfiChangesetIterator(
iterator,
ownsIterator: true,
ownedChangesetBytes: region,
);
}
@override
Uint8List sqlite3changeset_invert(Uint8List changeset) {
final sessionPtr = allocateBytes(changeset).cast();
final outSize = allocate();
final outChangeset = allocate>();
try {
final result = libsqlite3.sqlite3changeset_invert(
changeset.length,
sessionPtr,
outSize,
outChangeset,
);
if (result != SqlError.SQLITE_OK) {
throw createExceptionOutsideOfDatabase(this, result);
}
final size = outSize.value;
final inverted = outChangeset.value.cast().asTypedList(
size,
finalizer: libsqlite3.addresses.sqlite3_free.cast(),
);
return inverted;
} finally {
sessionPtr.free();
outSize.free();
outChangeset.free();
}
}
@override
String? get sqlite3_temp_directory {
return libsqlite3.sqlite3_temp_directory.readNullableString();
}
@override
set sqlite3_temp_directory(String? value) {
final newPtr = value != null
? Utf8Utils.allocateZeroTerminated(value)
: nullPtr();
if (!_globalTempDirectory.isNullPointer && _globalTempDirectory != newPtr) {
// The previous value was set in Dart too, free that now to avoid leaking
// memory. There's still a possibility for leaks if sqlite3_temp_directory
// is called in different isolates, but we can't safely avoid that.
allocate.free(_globalTempDirectory);
}
_globalTempDirectory = newPtr;
libsqlite3.sqlite3_temp_directory = newPtr;
}
@override
int sqlite3_initialize() {
return libsqlite3.sqlite3_initialize();
}
@override
String sqlite3_errstr(int extendedErrorCode) {
return libsqlite3.sqlite3_errstr(extendedErrorCode).readString();
}
@override
String sqlite3_libversion() {
return libsqlite3.sqlite3_libversion().readString();
}
@override
int sqlite3_libversion_number() {
return libsqlite3.sqlite3_libversion_number();
}
@override
SqliteResult sqlite3_open_v2(
String name,
int flags,
String? zVfs,
) {
final namePtr = Utf8Utils.allocateZeroTerminated(name);
final outDb = allocate>();
final vfsPtr = zVfs == null
? nullPtr()
: Utf8Utils.allocateZeroTerminated(zVfs);
final resultCode = libsqlite3.sqlite3_open_v2(
namePtr,
outDb,
flags,
vfsPtr,
);
final result = (
resultCode: resultCode,
result: outDb.value.isNullPointer
? null
: FfiDatabase(outDb.value, borrowed: false),
);
namePtr.free();
outDb.free();
if (zVfs != null) vfsPtr.free();
return result;
}
@override
String sqlite3_sourceid() {
return libsqlite3.sqlite3_sourceid().readString();
}
@override
void registerVirtualFileSystem(VirtualFileSystem vfs, int makeDefault) {
final ptr = _RegisteredVfs.allocate(vfs);
final result = libsqlite3.sqlite3_vfs_register(ptr._vfsPtr, makeDefault);
if (result != SqlError.SQLITE_OK) {
ptr.deallocate();
throw SqliteException(
extendedResultCode: result,
message: 'Could not register VFS',
);
}
_vfsPointers[vfs] = ptr;
}
@override
void unregisterVirtualFileSystem(VirtualFileSystem vfs) {
final ptr = _vfsPointers[vfs];
if (ptr == null) {
throw StateError('vfs has not been registered');
}
final result = libsqlite3.sqlite3_vfs_unregister(ptr._vfsPtr);
if (result != SqlError.SQLITE_OK) {
throw SqliteException(
extendedResultCode: result,
message: 'Could not unregister VFS',
);
}
ptr.deallocate();
}
String? sqlite3_compileoption_get(int n) {
final ptr = libsqlite3.sqlite3_compileoption_get(n);
return ptr.readNullableString();
}
int sqlite3_compileoption_used(String optName) {
final namePtr = Utf8Utils.allocateZeroTerminated(optName);
final result = libsqlite3.sqlite3_compileoption_used(namePtr);
namePtr.free();
return result;
}
}
final class _RegisteredVfs {
static final Map _files = {};
static final Map _vfs = {};
static int _vfsCounter = 0;
static int _fileCounter = 0;
final Pointer _vfsPtr;
final Pointer _name;
_RegisteredVfs(this._vfsPtr, this._name);
factory _RegisteredVfs.allocate(VirtualFileSystem dartVfs) {
final name = Utf8Utils.allocateZeroTerminated(dartVfs.name).cast();
final id = _vfsCounter++;
final vfs = ffi.calloc();
vfs.ref
..iVersion =
2 // We don't support syscalls yet
..szOsFile = sizeOf<_DartFile>()
..mxPathname = 1024
..zName = name
..pAppData = Pointer.fromAddress(id)
..xOpen = Pointer.fromFunction(_xOpen, SqlError.SQLITE_ERROR)
..xDelete = Pointer.fromFunction(_xDelete, SqlError.SQLITE_ERROR)
..xAccess = Pointer.fromFunction(_xAccess, SqlError.SQLITE_ERROR)
..xFullPathname = Pointer.fromFunction(
_xFullPathname,
SqlError.SQLITE_ERROR,
)
..xDlOpen = nullPtr()
..xDlError = nullPtr()
..xDlSym = nullPtr()
..xDlClose = nullPtr()
..xRandomness = Pointer.fromFunction(_xRandomness, SqlError.SQLITE_ERROR)
..xSleep = Pointer.fromFunction(_xSleep, SqlError.SQLITE_ERROR)
..xCurrentTime = nullPtr()
..xGetLastError = nullPtr()
..xCurrentTimeInt64 = Pointer.fromFunction(
_xCurrentTime64,
SqlError.SQLITE_ERROR,
);
_vfs[id] = dartVfs;
return _RegisteredVfs(vfs, name);
}
void deallocate() {
_vfs.remove(_vfsPtr.ref.pAppData.address);
ffi.calloc.free(_vfsPtr);
_name.free();
}
static int _runVfs(
Pointer vfs,
void Function(VirtualFileSystem) body,
) {
final dartVfs = _vfs[vfs.ref.pAppData.address]!;
try {
body(dartVfs);
return SqlError.SQLITE_OK;
} on VfsException catch (e) {
return e.returnCode;
} on Object {
return SqlError.SQLITE_ERROR;
}
}
static int _xOpen(
Pointer vfsPtr,
Pointer zName,
Pointer file,
int flags,
Pointer pOutFlags,
) {
return _runVfs(vfsPtr, (vfs) {
final fileName = Sqlite3Filename(
zName.isNullPointer ? null : zName.cast().readString(),
);
final dartFilePtr = file.cast<_DartFile>();
final (file: dartFile, :outFlags) = vfs.xOpen(fileName, flags);
final fileId = _fileCounter++;
_files[fileId] = dartFile;
final ioMethods = ffi.calloc();
ioMethods.ref
..iVersion = 1
..xClose = Pointer.fromFunction(_xClose, SqlError.SQLITE_ERROR)
..xRead = Pointer.fromFunction(_xRead, SqlError.SQLITE_ERROR)
..xWrite = Pointer.fromFunction(_xWrite, SqlError.SQLITE_ERROR)
..xTruncate = Pointer.fromFunction(_xTruncate, SqlError.SQLITE_ERROR)
..xSync = Pointer.fromFunction(_xSync, SqlError.SQLITE_ERROR)
..xFileSize = Pointer.fromFunction(_xFileSize, SqlError.SQLITE_ERROR)
..xLock = Pointer.fromFunction(_xLock, SqlError.SQLITE_ERROR)
..xUnlock = Pointer.fromFunction(_xUnlock, SqlError.SQLITE_ERROR)
..xCheckReservedLock = Pointer.fromFunction(
_xCheckReservedLock,
SqlError.SQLITE_ERROR,
)
..xFileControl = Pointer.fromFunction(
_xFileControl,
SqlError.SQLITE_NOTFOUND,
)
..xSectorSize = Pointer.fromFunction(_xSectorSize, 4096)
..xDeviceCharacteristics = Pointer.fromFunction(
_xDeviveCharacteristics,
0,
);
if (!pOutFlags.isNullPointer) {
pOutFlags.value = outFlags;
}
dartFilePtr.ref
..pMethods = ioMethods
..dartFileId = fileId;
});
}
static int _xDelete(
Pointer vfsPtr,
Pointer zName,
int syncDir,
) {
return _runVfs(
vfsPtr,
(vfs) => vfs.xDelete(zName.cast().readString(), syncDir),
);
}
static int _xAccess(
Pointer vfsPtr,
Pointer zName,
int flags,
Pointer pResOut,
) {
return _runVfs(vfsPtr, (vfs) {
if (!pResOut.isNullPointer) {
pResOut.value = vfs.xAccess(
zName.cast().readString(),
flags,
);
}
});
}
static int _xFullPathname(
Pointer vfsPtr,
Pointer zName,
int nOut,
Pointer zOut,
) {
return _runVfs(vfsPtr, (vfs) {
final bytes = utf8.encode(
vfs.xFullPathName(zName.cast().readString()),
);
if (bytes.length >= nOut) {
throw VfsException(SqlError.SQLITE_TOOBIG);
}
final target = zOut.cast().asTypedList(nOut);
target.setAll(0, bytes);
target[bytes.length] = 0;
});
}
static int _xRandomness(
Pointer vfsPtr,
int nByte,
Pointer zOut,
) {
return _runVfs(vfsPtr, (vfs) {
vfs.xRandomness(zOut.cast().asTypedList(nByte));
});
}
static int _xSleep(Pointer vfsPtr, int microseconds) {
return _runVfs(
vfsPtr,
(vfs) => vfs.xSleep(Duration(microseconds: microseconds)),
);
}
static int _xCurrentTime64(Pointer vfsPtr, Pointer out) {
return _runVfs(vfsPtr, (vfs) {
if (!out.isNullPointer) {
// https://github.com/sqlite/sqlite/blob/8ee75f7c3ac1456b8d941781857be27bfddb57d6/src/os_unix.c#L6757
const unixEpoch = 24405875 * 8640000;
out.value = unixEpoch + vfs.xCurrentTime().millisecondsSinceEpoch;
}
});
}
static int _runFile(
Pointer file,
void Function(VirtualFileSystemFile) body,
) {
final id = file.cast<_DartFile>().ref.dartFileId;
final dartFile = _files[id]!;
try {
body(dartFile);
return SqlError.SQLITE_OK;
} on VfsException catch (e) {
return e.returnCode;
} on Object {
return SqlError.SQLITE_ERROR;
}
}
static int _xClose(Pointer ptr) {
return _runFile(ptr, (file) {
file.xClose();
final dartFile = ptr.cast<_DartFile>().ref;
_files.remove(dartFile.dartFileId);
ffi.calloc.free(dartFile.pMethods);
});
}
static int _xRead(
Pointer ptr,
Pointer target,
int amount,
int offset,
) {
return _runFile(ptr, (file) {
final buffer = target.cast().asTypedList(amount);
file.xRead(buffer, offset);
});
}
static int _xWrite(
Pointer ptr,
Pointer target,
int amount,
int offset,
) {
return _runFile(ptr, (file) {
final buffer = target.cast().asTypedList(amount);
file.xWrite(buffer, offset);
});
}
static int _xTruncate(Pointer ptr, int size) {
return _runFile(ptr, (file) => file.xTruncate(size));
}
static int _xSync(Pointer ptr, int flags) {
return _runFile(ptr, (file) => file.xSync(flags));
}
static int _xFileSize(Pointer ptr, Pointer pSize) {
return _runFile(ptr, (file) {
if (!pSize.isNullPointer) {
pSize.value = file.xFileSize();
}
});
}
static int _xLock(Pointer ptr, int flags) {
return _runFile(ptr, (file) => file.xLock(flags));
}
static int _xUnlock(Pointer ptr, int flags) {
return _runFile(ptr, (file) => file.xUnlock(flags));
}
static int _xCheckReservedLock(
Pointer ptr,
Pointer pResOut,
) {
return _runFile(ptr, (file) {
if (!pResOut.isNullPointer) {
pResOut.value = file.xCheckReservedLock();
}
});
}
static int _xFileControl(
Pointer ptr,
int op,
Pointer pArg,
) {
// We don't currently support filecontrol operations in the VFS.
return SqlError.SQLITE_NOTFOUND;
}
static int _xSectorSize(Pointer ptr) {
// We don't currently support custom sector sizes.
return 4096;
}
static int _xDeviveCharacteristics(Pointer ptr) {
return _runFile(ptr, (file) => file.xDeviceCharacteristics);
}
}
final class _DartFile extends Struct {
// extends sqlite3_file:
external Pointer pMethods;
// additional definitions
@Int64()
external int dartFileId;
}
final class FfiSession implements RawSqliteSession, Finalizable {
final Pointer session;
final Object detachToken = Object();
FfiSession(this.session) {
sessionDeleteFinalizer.attach(this, session.cast(), detach: detachToken);
}
@override
int sqlite3session_attach([String? name]) {
final namePtr = name == null
? nullPtr()
: Utf8Utils.allocateZeroTerminated(name);
final result = libsqlite3.sqlite3session_attach(session, namePtr);
if (name != null) {
namePtr.free();
}
return result;
}
Uint8List _handleChangesetResult(int result, int size, Pointer buffer) {
if (result != SqlError.SQLITE_OK) {
throw createExceptionOutsideOfDatabase(ffiBindings, result);
}
return buffer.cast().asTypedList(
size,
finalizer: libsqlite3.addresses.sqlite3_free,
);
}
@override
Uint8List sqlite3session_changeset() {
final outSize = allocate();
final outChangeset = allocate>();
final result = libsqlite3.sqlite3session_changeset(
session,
outSize,
outChangeset,
);
final size = outSize.value;
final changeset = outChangeset.value;
outSize.free();
outChangeset.free();
return _handleChangesetResult(result, size, changeset);
}
@override
Uint8List sqlite3session_patchset() {
final outSize = allocate();
final outPatchset = allocate>();
final result = libsqlite3.sqlite3session_patchset(
session,
outSize,
outPatchset,
);
final size = outSize.value;
final patchset = outPatchset.value;
outSize.free();
outPatchset.free();
return _handleChangesetResult(result, size, patchset);
}
@override
void sqlite3session_delete() {
sessionDeleteFinalizer.detach(detachToken);
libsqlite3.sqlite3session_delete(session);
}
@override
int sqlite3session_diff(String fromDb, String table) {
final fromDbPtr = Utf8Utils.allocateZeroTerminated(fromDb);
final tablePtr = Utf8Utils.allocateZeroTerminated(table);
final result = libsqlite3.sqlite3session_diff(
session,
fromDbPtr,
tablePtr,
nullPtr(),
);
fromDbPtr.free();
tablePtr.free();
return result;
}
@override
int sqlite3session_enable(int enable) {
return libsqlite3.sqlite3session_enable(session, enable);
}
@override
int sqlite3session_indirect(int indirect) {
return libsqlite3.sqlite3session_indirect(session, indirect);
}
@override
int sqlite3session_isempty() {
return libsqlite3.sqlite3session_isempty(session);
}
}
final class FfiChangesetIterator implements RawChangesetIterator, Finalizable {
final Pointer iterator;
final Object detachToken = Object();
/// An optional [Uint8List] backing the changeset we're iterating on with a
/// native finalizer attached to it.
///
/// This ensures that, as the iterator is GCed, so is the changeset.
final Uint8List? ownedChangesetBytes;
FfiChangesetIterator(
this.iterator, {
bool ownsIterator = true,
this.ownedChangesetBytes,
}) {
if (ownsIterator) {
changesetFinalizeFinalizer.attach(
this,
iterator.cast(),
detach: detachToken,
);
}
}
@override
int sqlite3changeset_finalize() {
changesetFinalizeFinalizer.detach(detachToken);
final result = libsqlite3.sqlite3changeset_finalize(iterator);
return result;
}
@override
SqliteResult sqlite3changeset_new(int columnNumber) {
final outValue = allocate>();
final result = libsqlite3.sqlite3changeset_new(
iterator,
columnNumber,
outValue,
);
final value = outValue.value;
outValue.free();
return (
resultCode: result,
result: value.isNullPointer ? null : FfiValue(value),
);
}
@override
int sqlite3changeset_next() {
return libsqlite3.sqlite3changeset_next(iterator);
}
@override
SqliteResult sqlite3changeset_old(int columnNumber) {
final outValue = allocate>();
final result = libsqlite3.sqlite3changeset_old(
iterator,
columnNumber,
outValue,
);
final value = outValue.value;
outValue.free();
return (
resultCode: result,
result: value.isNullPointer ? null : FfiValue(value),
);
}
@override
RawChangeSetOp sqlite3changeset_op() {
final tablePtr = allocate>();
final columnCountPtr = allocate();
final typePtr = allocate();
final indirectPtr = allocate();
final result = libsqlite3.sqlite3changeset_op(
iterator,
tablePtr,
columnCountPtr,
typePtr,
indirectPtr,
);
final tableValue = tablePtr.value;
final columnCountValue = columnCountPtr.value;
final typeValue = typePtr.value;
final indirectValue = indirectPtr.value;
tablePtr.free();
columnCountPtr.free();
typePtr.free();
indirectPtr.free();
if (result != SqlError.SQLITE_OK) {
throw createExceptionOutsideOfDatabase(ffiBindings, result);
}
final table = tableValue.readString();
return RawChangeSetOp(
tableName: table,
columnCount: columnCountValue,
operation: typeValue,
indirect: indirectValue,
);
}
}
/// For user-defined functions, SQLite hooks, or virtual file systems, we
/// register function pointers as [NativeCallable]s.
///
/// To avoid leaking resources, we should [NativeCallable.close] those once
/// they're no longer used. SQLite provides the `xDestroy` callback for this.
/// For a long time, this package used an additional callable for `xDestroy`
/// that closed the original callables and itself.
///
/// After migrating to native finalizers however, this approach stopped working.
/// Because native finalizers can run as the Dart isolate is shutting down, we
/// can't invoke Dart code anymore. There is no good way to close callables from
/// C (https://dartbug.com/61887), so we can't use `xDestroy` callbacks from
/// SQLite.
///
/// Instead, we:
///
/// - Manually close callables when the database is closed in Dart.
/// - Use (regular, non-native) finalizers to asynchronously close callbacks
/// for databases that haven't been closed manually.
final class _FunctionFinalizers {
final List _callables = [];
void closeAll() {
for (final callable in _callables) {
callable.close();
}
}
static final Finalizer<_FunctionFinalizers> finalizer = Finalizer(
(f) => f.closeAll(),
);
}
final class FfiDatabase implements RawSqliteDatabase, Finalizable {
final Pointer db;
final _FunctionFinalizers _functions = _FunctionFinalizers();
final Object _detachToken = Object();
NativeCallable<_UpdateHook>? _installedUpdateHook;
NativeCallable<_CommitHook>? _installedCommitHook;
NativeCallable<_RollbackHook>? _installedRollbackHook;
FfiDatabase(this.db, {required bool borrowed}) {
if (!borrowed) {
// This object owns the `sqlite3` connection, so close it once the object
// is GCed.
databaseFinalizer.attach(this, db.cast(), detach: _detachToken);
_FunctionFinalizers.finalizer.attach(
this,
_functions,
detach: _detachToken,
);
}
}
@override
int sqlite3_close_v2() {
final rc = libsqlite3.sqlite3_close_v2(db);
_functions.closeAll();
_FunctionFinalizers.finalizer.detach(_detachToken);
detachFinalizer();
return rc;
}
void detachFinalizer() {
databaseFinalizer.detach(_detachToken);
}
@override
String sqlite3_errmsg() {
return libsqlite3.sqlite3_errmsg(db).readString();
}
@override
int sqlite3_extended_errcode() {
return libsqlite3.sqlite3_extended_errcode(db);
}
@override
int sqlite3_error_offset() {
if (supportsErrorOffset) {
return libsqlite3.sqlite3_error_offset(db);
} else {
return -1;
}
}
@override
void sqlite3_extended_result_codes(int onoff) {
libsqlite3.sqlite3_extended_result_codes(db, onoff);
}
@override
int sqlite3_changes() => libsqlite3.sqlite3_changes(db);
@override
int sqlite3_exec(String sql) {
final sqlPtr = Utf8Utils.allocateZeroTerminated(sql);
final result = libsqlite3.sqlite3_exec(
db,
sqlPtr,
nullPtr(),
nullPtr(),
nullPtr(),
);
sqlPtr.free();
return result;
}
@override
int sqlite3_last_insert_rowid() {
return libsqlite3.sqlite3_last_insert_rowid(db);
}
@override
int sqlite3_create_collation_v2({
required Uint8List collationName,
required int eTextRep,
required RawCollation collation,
}) {
final name = allocateBytes(collationName, additionalLength: 1);
final compare = collation.toNative(_functions);
final result = libsqlite3.sqlite3_create_collation_v2(
db,
name.cast(),
eTextRep,
nullPtr(),
compare.nativeFunction,
nullPtr(),
);
name.free();
return result;
}
@override
int sqlite3_create_window_function({
required Uint8List functionName,
required int nArg,
required int eTextRep,
required RawXStep xStep,
required RawXFinal xFinal,
required RawXFinal xValue,
required RawXStep xInverse,
}) {
final functionNamePtr = allocateBytes(functionName, additionalLength: 1);
final step = xStep.toNative(_functions);
final $final = xFinal.toNative(clean: true, finalizers: _functions);
final value = xValue.toNative(clean: false, finalizers: _functions);
final inverse = xInverse.toNative(_functions);
final result = libsqlite3.sqlite3_create_window_function(
db,
functionNamePtr.cast(),
nArg,
eTextRep,
nullPtr(),
step.nativeFunction,
$final.nativeFunction,
value.nativeFunction,
inverse.nativeFunction,
nullPtr(),
);
functionNamePtr.free();
return result;
}
@override
int sqlite3_create_function_v2({
required Uint8List functionName,
required int nArg,
required int eTextRep,
RawXFunc? xFunc,
RawXStep? xStep,
RawXFinal? xFinal,
}) {
final functionNamePtr = allocateBytes(functionName, additionalLength: 1);
final func = xFunc?.toNative(_functions);
final step = xStep?.toNative(_functions);
final $final = xFinal?.toNative(clean: true, finalizers: _functions);
final result = libsqlite3.sqlite3_create_function_v2(
db,
functionNamePtr.cast(),
nArg,
eTextRep,
nullPtr(),
func?.nativeFunction ?? nullPtr(),
step?.nativeFunction ?? nullPtr(),
$final?.nativeFunction ?? nullPtr(),
nullPtr(),
);
functionNamePtr.free();
return result;
}
@override
void sqlite3_update_hook(RawUpdateHook? hook) {
final previous = _installedUpdateHook;
if (hook == null) {
_installedUpdateHook = null;
libsqlite3.sqlite3_update_hook(db, nullPtr(), nullPtr());
} else {
final native = _installedUpdateHook = hook.toNative(_functions);
libsqlite3.sqlite3_update_hook(db, native.nativeFunction, nullPtr());
}
previous?.close();
}
@override
void sqlite3_commit_hook(RawCommitHook? hook) {
final previous = _installedCommitHook;
if (hook == null) {
_installedCommitHook = null;
libsqlite3.sqlite3_commit_hook(db, nullPtr(), nullPtr());
} else {
final native = _installedCommitHook = hook.toNative(_functions);
libsqlite3.sqlite3_commit_hook(db, native.nativeFunction, nullPtr());
}
previous?.close();
}
@override
void sqlite3_rollback_hook(RawRollbackHook? hook) {
final previous = _installedRollbackHook;
if (hook == null) {
libsqlite3.sqlite3_rollback_hook(db, nullPtr(), nullPtr());
} else {
final native = _installedRollbackHook = hook.toNative(_functions);
libsqlite3.sqlite3_rollback_hook(db, native.nativeFunction, nullPtr());
}
previous?.close();
}
@override
int sqlite3_db_config(int op, int value) {
final result = libsqlite3.sqlite3_db_config(db, op, value, nullPtr());
return result;
}
@override
int sqlite3_get_autocommit() {
return libsqlite3.sqlite3_get_autocommit(db);
}
@override
int sqlite3_busy_handler(int Function(int)? callback) {
if (callback == null) {
return libsqlite3.sqlite3_busy_handler(db, nullPtr(), nullPtr());
} else {
final callable =
NativeCallable, Int)>.isolateLocal((
Pointer _,
int amount,
) {
return callback(amount);
}, exceptionalReturn: 0)
..keepIsolateAlive = false
..closeIn(_functions);
return libsqlite3.sqlite3_busy_handler(
db,
callable.nativeFunction,
nullPtr(),
);
}
}
@override
RawStatementCompiler newCompiler(List