├── .github └── workflows │ ├── linux.yml │ ├── macos.yml │ ├── scripts │ ├── clang_format.sh │ └── file_format.sh │ ├── static_checks.yml │ └── windows.yml ├── .gitignore ├── AUTHORS.md ├── LICENSE ├── README.md ├── SCsub ├── config.py ├── demo ├── .gitignore ├── SQLite │ ├── blob_data.gd │ ├── game_highscore.gd │ ├── item_database.gd │ ├── sql_queries.gd │ └── test_sqlite.tscn ├── default_env.tres ├── icon.png ├── icon.png.import ├── items.db └── project.godot ├── doc_classes ├── SQLite.xml └── SQLiteQuery.xml ├── register_types.cpp ├── register_types.h ├── sqlite.cpp ├── sqlite.h └── thirdparty └── sqlite ├── spmemvfs.c ├── spmemvfs.h ├── sqlite3.c ├── sqlite3.h └── sqlite3ext.h /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: 🐧 Linux Builds 2 | on: 3 | push: 4 | branches: [master, github_actions] 5 | pull_request: 6 | branches: [master] 7 | 8 | # Global Cache Settings 9 | env: 10 | GODOT_BASE_BRANCH: master 11 | SCONS_CACHE_LIMIT: 4096 12 | 13 | jobs: 14 | linux-editor: 15 | runs-on: "ubuntu-20.04" 16 | name: Editor 17 | 18 | steps: 19 | # Clone Godot 20 | - uses: actions/checkout@v2 21 | with: 22 | repository: godotengine/godot 23 | ref: master 24 | 25 | # Clone our module under the correct directory 26 | - uses: actions/checkout@v2 27 | with: 28 | path: modules/sqlite 29 | 30 | # Azure repositories are not reliable, we need to prevent azure giving us packages. 31 | - name: Make apt sources.list use the default Ubuntu repositories 32 | run: | 33 | sudo rm -f /etc/apt/sources.list.d/* 34 | sudo cp -f misc/ci/sources.list /etc/apt/sources.list 35 | sudo apt-get update 36 | 37 | # Install all packages (except scons) 38 | - name: Configure dependencies 39 | run: | 40 | sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ 41 | libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm 42 | 43 | # Upload cache on completion and check it out now 44 | - name: Load .scons_cache directory 45 | id: linux-editor-cache 46 | uses: actions/cache@v2 47 | with: 48 | path: ${{github.workspace}}/.scons_cache/ 49 | key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 50 | restore-keys: | 51 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 52 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} 53 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}} 54 | 55 | # Use python 3.x release (works cross platform; best to keep self contained in it's own step) 56 | - name: Set up Python 3.x 57 | uses: actions/setup-python@v2 58 | with: 59 | # Semantic version range syntax or exact version of a Python version 60 | python-version: "3.x" 61 | # Optional - x64 or x86 architecture, defaults to x64 62 | architecture: "x64" 63 | 64 | # Setup scons, print python version and scons version info, so if anything is broken it won't run the build. 65 | - name: Configuring Python packages 66 | run: | 67 | python -c "import sys; print(sys.version)" 68 | python -m pip install scons 69 | python --version 70 | scons --version 71 | 72 | # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags 73 | - name: Compilation 74 | env: 75 | SCONS_CACHE: ${{github.workspace}}/.scons_cache/ 76 | run: | 77 | scons -j2 verbose=yes warnings=all werror=yes platform=linuxbsd tools=yes tests=no target=release_debug production=yes 78 | 79 | # TODO Such tests are able to run from Godot 4.0 only 80 | # Execute unit tests for the editor 81 | #- name: Unit Tests 82 | # run: | 83 | # ./bin/godot.linuxbsd.opt.tools.64 --test 84 | 85 | # Make build available 86 | - uses: actions/upload-artifact@v2 87 | with: 88 | name: godot.linuxbsd.opt.tools.64 89 | path: bin/godot.linuxbsd.opt.tools.64 90 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: 🍎 Macos Builds 2 | on: 3 | push: 4 | branches: [master, github_actions] 5 | pull_request: 6 | branches: [master] 7 | 8 | # Global Cache Settings 9 | env: 10 | GODOT_BASE_BRANCH: master 11 | SCONS_CACHE_LIMIT: 4096 12 | 13 | jobs: 14 | macos-editor: 15 | runs-on: "macos-10.15" 16 | name: Editor 17 | 18 | steps: 19 | # Clone Godot 20 | - uses: actions/checkout@v2 21 | with: 22 | repository: godotengine/godot 23 | ref: master 24 | 25 | # Clone our module under the correct directory 26 | - uses: actions/checkout@v2 27 | with: 28 | path: modules/sqlite 29 | 30 | # Upload cache on completion and check it out now 31 | - name: Load .scons_cache directory 32 | id: macos-editor-cache 33 | uses: actions/cache@v2 34 | with: 35 | path: ${{github.workspace}}/.scons_cache/ 36 | key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 37 | restore-keys: | 38 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 39 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} 40 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}} 41 | 42 | # Use python 3.x release (works cross platform; best to keep self contained in it's own step) 43 | - name: Set up Python 3.x 44 | uses: actions/setup-python@v2 45 | with: 46 | # Semantic version range syntax or exact version of a Python version 47 | python-version: "3.x" 48 | # Optional - x64 or x86 architecture, defaults to x64 49 | architecture: "x64" 50 | 51 | # Setup scons, print python version and scons version info, so if anything is broken it won't run the build. 52 | - name: Configuring Python packages 53 | run: | 54 | python -c "import sys; print(sys.version)" 55 | python -m pip install scons 56 | python --version 57 | scons --version 58 | 59 | # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags 60 | - name: Compilation 61 | env: 62 | SCONS_CACHE: ${{github.workspace}}/.scons_cache/ 63 | run: | 64 | scons -j2 verbose=yes warnings=all werror=yes platform=osx tools=yes tests=no target=release_debug production=yes module_text_server_fb_enabled=yes 65 | 66 | # TODO Such tests are able to run from Godot 4.0 only 67 | # Execute unit tests for the editor 68 | #- name: Unit Tests 69 | # run: | 70 | # ./bin/godot.linuxbsd.opt.tools.64 --test 71 | 72 | # Make build available 73 | - uses: actions/upload-artifact@v2 74 | with: 75 | name: godot.osx.opt.tools.64 76 | path: bin/godot.osx.opt.tools.64 77 | -------------------------------------------------------------------------------- /.github/workflows/scripts/clang_format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script runs clang-format and fixes copyright headers on all relevant files in the repo. 4 | # This is the primary script responsible for fixing style violations. 5 | 6 | set -uo pipefail 7 | IFS=$'\n\t' 8 | 9 | CLANG_FORMAT_FILE_EXTS=(".c" ".h" ".cpp" ".hpp" ".cc" ".hh" ".cxx" ".m" ".mm" ".inc" ".java" ".glsl") 10 | 11 | # Loops through all text files tracked by Git. 12 | git grep -zIl '' | 13 | while IFS= read -rd '' f; do 14 | # Exclude 3rd party files. 15 | if [[ "$f" == "glad"* ]]; then 16 | continue 17 | elif [[ "$f" == "godot-cpp"* ]]; then 18 | continue 19 | elif [[ "$f" == "thirdparty"* ]]; then 20 | continue 21 | elif [[ "$f" == "gradle"* ]]; then 22 | continue 23 | elif [[ "$f" == "build"* ]]; then 24 | continue 25 | elif [[ "$f" == "android"* ]]; then 26 | continue 27 | elif [[ "$f" == ".github"* ]]; then 28 | continue 29 | fi 30 | for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do 31 | if [[ "$f" == *"$extension" ]]; then 32 | # Run clang-format. 33 | clang-format -i "$f" 34 | fi 35 | done 36 | done 37 | 38 | git diff > patch.patch 39 | 40 | # If no patch has been generated all is OK, clean up, and exit. 41 | if [ ! -s patch.patch ] ; then 42 | printf "Files in this commit comply with the clang-format style rules.\n" 43 | rm -f patch.patch 44 | exit 0 45 | fi 46 | 47 | # A patch has been created, notify the user, clean up, and exit. 48 | printf "\n*** The following differences were found between the code " 49 | printf "and the formatting rules:\n\n" 50 | cat patch.patch 51 | printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i '\n" 52 | rm -f patch.patch 53 | exit 1 54 | -------------------------------------------------------------------------------- /.github/workflows/scripts/file_format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script ensures proper POSIX text file formatting and a few other things. 4 | # This is supplementary to clang_format.sh, but should be run before it. 5 | 6 | # We need dos2unix and recode. 7 | if [ ! -x "$(command -v dos2unix)" -o ! -x "$(command -v recode)" ]; then 8 | printf "Install 'dos2unix' and 'recode' to use this script.\n" 9 | fi 10 | 11 | set -uo pipefail 12 | IFS=$'\n\t' 13 | 14 | # Loops through all text files tracked by Git. 15 | git grep -zIl '' | 16 | while IFS= read -rd '' f; do 17 | # Exclude 3rd party files 18 | if [[ "$f" == "glad"* ]]; then 19 | continue 20 | elif [[ "$f" == "godot-cpp"* ]]; then 21 | continue 22 | elif [[ "$f" == "thirdparty"* ]]; then 23 | continue 24 | elif [[ "$f" == "gradle"* ]]; then 25 | continue 26 | elif [[ "$f" == "build"* ]]; then 27 | continue 28 | elif [[ "$f" == "android"* ]]; then 29 | continue 30 | elif [[ "$f" == "api.json" ]]; then 31 | continue 32 | fi 33 | # Ensure that files are UTF-8 formatted. 34 | recode UTF-8 "$f" 2> /dev/null 35 | # Ensure that files have LF line endings and do not contain a BOM. 36 | dos2unix "$f" 2> /dev/null 37 | # Remove trailing space characters and ensures that files end 38 | # with newline characters. -l option handles newlines conveniently. 39 | perl -i -ple 's/\s*$//g' "$f" 40 | # Remove the character sequence "== true" if it has a leading space. 41 | perl -i -pe 's/\x20== true//g' "$f" 42 | # We don't want to change lines around braces in godot/tscn files. 43 | if [[ "$f" == *"godot" ]]; then 44 | continue 45 | elif [[ "$f" == *"tscn" ]]; then 46 | continue 47 | fi 48 | # Disallow empty lines after the opening brace. 49 | sed -z -i 's/\x7B\x0A\x0A/\x7B\x0A/g' "$f" 50 | # Disallow some empty lines before the closing brace. 51 | sed -z -i 's/\x0A\x0A\x7D/\x0A\x7D/g' "$f" 52 | done 53 | 54 | git diff > patch.patch 55 | 56 | # If no patch has been generated all is OK, clean up, and exit. 57 | if [ ! -s patch.patch ] ; then 58 | printf "Files in this commit comply with the formatting rules.\n" 59 | rm -f patch.patch 60 | exit 0 61 | fi 62 | 63 | # A patch has been created, notify the user, clean up, and exit. 64 | printf "\n*** The following differences were found between the code " 65 | printf "and the formatting rules:\n\n" 66 | cat patch.patch 67 | printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i '\n" 68 | rm -f patch.patch 69 | exit 1 70 | -------------------------------------------------------------------------------- /.github/workflows/static_checks.yml: -------------------------------------------------------------------------------- 1 | name: 📊 Static Checks 2 | on: [push, pull_request] 3 | 4 | concurrency: 5 | group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static-checks 6 | cancel-in-progress: true 7 | 8 | jobs: 9 | static-checks: 10 | name: Formatting (clang-format, file format) 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | 16 | - name: Install dependencies 17 | run: | 18 | sudo apt-get install -qq dos2unix recode clang-format 19 | 20 | - name: File formatting checks (file_format.sh) 21 | run: | 22 | bash ./.github/workflows/scripts/file_format.sh 23 | 24 | - name: Style checks via clang-format (clang_format.sh) 25 | run: | 26 | bash ./.github/workflows/scripts/clang_format.sh 27 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: 🚪 Windows Builds 2 | on: 3 | push: 4 | branches: [master, github_actions] 5 | pull_request: 6 | branches: [master] 7 | 8 | # Global Cache Settings 9 | # SCONS_CACHE for windows must be set in the build environment 10 | env: 11 | GODOT_BASE_BRANCH: master 12 | SCONS_CACHE_MSVC_CONFIG: true 13 | SCONS_CACHE_LIMIT: 4096 14 | 15 | jobs: 16 | windows-editor: 17 | # Windows 10 with latest image 18 | runs-on: "windows-latest" 19 | name: Editor 20 | 21 | steps: 22 | # Clone Godot 23 | - uses: actions/checkout@v2 24 | with: 25 | repository: v-sekai/godot 26 | ref: groups-4.x 27 | 28 | # Clone our module under the correct directory 29 | - uses: actions/checkout@v2 30 | with: 31 | path: modules/sqlite 32 | 33 | # Upload cache on completion and check it out now 34 | # Editing this is pretty dangerous for Windows since it can break and needs to be properly tested with a fresh cache. 35 | - name: Load .scons_cache directory 36 | id: windows-editor-cache 37 | uses: actions/cache@v2 38 | with: 39 | path: /.scons_cache/ 40 | key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 41 | restore-keys: | 42 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 43 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} 44 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}} 45 | 46 | # Use python 3.x release (works cross platform; best to keep self contained in it's own step) 47 | - name: Set up Python 3.x 48 | uses: actions/setup-python@v2 49 | with: 50 | # Semantic version range syntax or exact version of a Python version 51 | python-version: "3.x" 52 | # Optional - x64 or x86 architecture, defaults to x64 53 | architecture: "x64" 54 | 55 | # Setup scons, print python version and scons version info, so if anything is broken it won't run the build. 56 | - name: Configuring Python packages 57 | run: | 58 | python -c "import sys; print(sys.version)" 59 | python -m pip install scons pywin32 60 | python --version 61 | scons --version 62 | 63 | # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags 64 | - name: Compilation 65 | env: 66 | SCONS_CACHE: /.scons_cache/ 67 | run: | 68 | scons -j2 verbose=yes warnings=all werror=yes platform=windows tools=yes tests=no target=release_debug 69 | 70 | # TODO Such tests are able to run from Godot 4.0 only 71 | # Execute unit tests for the editor 72 | #- name: Unit Tests 73 | # run: | 74 | # ./bin/godot.windows.opt.tools.64.exe --test 75 | 76 | # Make build available 77 | - uses: actions/upload-artifact@v2 78 | with: 79 | name: godot.windows.opt.tools.64.exe 80 | path: bin/godot.windows.opt.tools.64.exe 81 | 82 | windows-template: 83 | # Windows 10 with latest image 84 | runs-on: "windows-latest" 85 | name: Release 86 | 87 | steps: 88 | # Clone Godot 89 | - uses: actions/checkout@v2 90 | with: 91 | repository: v-sekai/godot 92 | ref: groups-4.x 93 | 94 | # Clone our module under the correct directory 95 | - uses: actions/checkout@v2 96 | with: 97 | path: modules/sqlite 98 | 99 | # Upload cache on completion and check it out now 100 | # Editing this is pretty dangerous for Windows since it can break and needs to be properly tested with a fresh cache. 101 | - name: Load .scons_cache directory 102 | id: windows-editor-cache 103 | uses: RevoluPowered/cache@v2.1 104 | with: 105 | path: /.scons_cache/ 106 | key: ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 107 | restore-keys: | 108 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} 109 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} 110 | ${{github.job}}-${{env.GODOT_BASE_BRANCH}} 111 | 112 | # Use python 3.x release (works cross platform; best to keep self contained in it's own step) 113 | - name: Set up Python 3.x 114 | uses: actions/setup-python@v2 115 | with: 116 | # Semantic version range syntax or exact version of a Python version 117 | python-version: "3.x" 118 | # Optional - x64 or x86 architecture, defaults to x64 119 | architecture: "x64" 120 | 121 | # Setup scons, print python version and scons version info, so if anything is broken it won't run the build. 122 | - name: Configuring Python packages 123 | run: | 124 | python -c "import sys; print(sys.version)" 125 | python -m pip install scons pywin32 126 | python --version 127 | scons --version 128 | 129 | # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags 130 | - name: Compilation 131 | env: 132 | SCONS_CACHE: /.scons_cache/ 133 | run: | 134 | scons -j2 verbose=yes warnings=all werror=yes platform=windows tools=no tests=no target=release 135 | 136 | # TODO Such tests are able to run from Godot 4.0 only 137 | # Execute unit tests for the editor 138 | #- name: Unit Tests 139 | # run: | 140 | # ./bin/godot.windows.opt.tools.64.exe --test 141 | 142 | # Make build available 143 | - uses: actions/upload-artifact@v2 144 | with: 145 | name: godot.windows.opt.64.exe 146 | path: bin/godot.windows.opt.64.exe 147 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot auto generated files 2 | *.gen.* 3 | .import/ 4 | 5 | # Documentation generated by doxygen or from classes.xml 6 | doc/_build/ 7 | 8 | # Javascript specific 9 | *.bc 10 | 11 | # CLion 12 | cmake-build-debug 13 | 14 | # Android specific 15 | .gradle 16 | local.properties 17 | *.iml 18 | .idea 19 | .gradletasknamecache 20 | project.properties 21 | platform/android/java/lib/.cxx/ 22 | platform/android/java/libs/* 23 | platform/android/java/app/libs/* 24 | platform/android/java/lib/.cxx/* 25 | 26 | # General c++ generated files 27 | *.lib 28 | *.o 29 | *.ox 30 | *.a 31 | *.ax 32 | *.d 33 | *.so 34 | *.os 35 | *.Plo 36 | *.lo 37 | 38 | # Libs generated files 39 | .deps/* 40 | .dirstamp 41 | 42 | # Gprof output 43 | gmon.out 44 | 45 | # Vim temp files 46 | *.swo 47 | *.swp 48 | 49 | # Qt project files 50 | *.config 51 | *.creator 52 | *.creator.* 53 | *.files 54 | *.includes 55 | *.cflags 56 | *.cxxflags 57 | 58 | # Code::Blocks files 59 | *.cbp 60 | *.layout 61 | *.depend 62 | 63 | # Eclipse CDT files 64 | .cproject 65 | .settings/ 66 | *.pydevproject 67 | *.launch 68 | 69 | # Geany/geany-plugins files 70 | *.geany 71 | .geanyprj 72 | 73 | # Jetbrains IDEs 74 | .idea/ 75 | 76 | # Misc 77 | .DS_Store 78 | __MACOSX 79 | logs/ 80 | 81 | # for projects that use SCons for building: http://http://www.scons.org/ 82 | .sconf_temp 83 | .sconsign*.dblite 84 | *.pyc 85 | 86 | # https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 87 | ## Ignore Visual Studio temporary files, build results, and 88 | ## files generated by popular Visual Studio add-ons. 89 | 90 | # User-specific files 91 | *.suo 92 | *.user 93 | *.sln.docstates 94 | *.sln 95 | *.vcxproj* 96 | 97 | # Custom SCons configuration override 98 | /custom.py 99 | 100 | # Build results 101 | [Dd]ebug/ 102 | [Dd]ebugPublic/ 103 | [Rr]elease/ 104 | x64/ 105 | build/ 106 | bld/ 107 | [Bb]in/ 108 | [Oo]bj/ 109 | *.debug 110 | *.dSYM 111 | 112 | # Visual Studio cache/options directory 113 | .vs/ 114 | 115 | # MSTest test Results 116 | [Tt]est[Rr]esult*/ 117 | [Bb]uild[Ll]og.* 118 | 119 | # Hints for improving IntelliSense, created together with VS project 120 | cpp.hint 121 | 122 | #NUNIT 123 | *.VisualState.xml 124 | TestResult.xml 125 | 126 | *.o 127 | *.a 128 | *_i.c 129 | *_p.c 130 | *_i.h 131 | *.ilk 132 | *.meta 133 | *.obj 134 | *.pch 135 | *.pdb 136 | *.pgc 137 | *.pgd 138 | *.rsp 139 | *.sbr 140 | *.tlb 141 | *.tli 142 | *.tlh 143 | *.tmp 144 | *.tmp_proj 145 | *.bak 146 | *.log 147 | *.vspscc 148 | *.vssscc 149 | .builds 150 | *.pidb 151 | *.svclog 152 | *.scc 153 | *.nib 154 | 155 | # Chutzpah Test files 156 | _Chutzpah* 157 | 158 | # Visual C++ cache files 159 | ipch/ 160 | *.aps 161 | *.ncb 162 | *.opensdf 163 | *.sdf 164 | *.cachefile 165 | *.VC.db 166 | *.VC.opendb 167 | *.VC.VC.opendb 168 | enc_temp_folder/ 169 | 170 | # Visual Studio profiler 171 | *.psess 172 | *.vsp 173 | *.vspx 174 | 175 | # CodeLite project files 176 | *.project 177 | *.workspace 178 | .codelite/ 179 | 180 | # TFS 2012 Local Workspace 181 | $tf/ 182 | 183 | # Guidance Automation Toolkit 184 | *.gpState 185 | 186 | # ReSharper is a .NET coding add-in 187 | _ReSharper*/ 188 | *.[Rr]e[Ss]harper 189 | *.DotSettings.user 190 | 191 | # JustCode is a .NET coding addin-in 192 | .JustCode 193 | 194 | # TeamCity is a build add-in 195 | _TeamCity* 196 | 197 | # DotCover is a Code Coverage Tool 198 | *.dotCover 199 | 200 | # NCrunch 201 | *.ncrunch* 202 | _NCrunch_* 203 | .*crunch*.local.xml 204 | 205 | # MightyMoose 206 | *.mm.* 207 | AutoTest.Net/ 208 | 209 | # Web workbench (sass) 210 | .sass-cache/ 211 | 212 | # Installshield output folder 213 | [Ee]xpress/ 214 | 215 | # DocProject is a documentation generator add-in 216 | DocProject/buildhelp/ 217 | DocProject/Help/*.HxT 218 | DocProject/Help/*.HxC 219 | DocProject/Help/*.hhc 220 | DocProject/Help/*.hhk 221 | DocProject/Help/*.hhp 222 | DocProject/Help/Html2 223 | DocProject/Help/html 224 | 225 | # Click-Once directory 226 | publish/ 227 | 228 | # Publish Web Output 229 | *.[Pp]ublish.xml 230 | *.azurePubxml 231 | 232 | # NuGet Packages Directory 233 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 234 | #packages/* 235 | ## TODO: If the tool you use requires repositories.config, also uncomment the next line 236 | #!packages/repositories.config 237 | 238 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 239 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 240 | !packages/build/ 241 | 242 | # Windows Azure Build Output 243 | csx/ 244 | *.build.csdef 245 | 246 | # Windows Store app package directory 247 | AppPackages/ 248 | 249 | # Others 250 | sql/ 251 | *.Cache 252 | ClientBin/ 253 | [Ss]tyle[Cc]op.* 254 | ~$* 255 | *~ 256 | *.dbmdl 257 | *.dbproj.schemaview 258 | *.pfx 259 | *.publishsettings 260 | node_modules/ 261 | __pycache__/ 262 | 263 | # KDE 264 | .directory 265 | 266 | #Kdevelop project files 267 | *.kdev4 268 | 269 | # Xcode 270 | xcuserdata/ 271 | *.xcscmblueprint 272 | *.xccheckout 273 | *.xcodeproj/* 274 | 275 | # RIA/Silverlight projects 276 | Generated_Code/ 277 | 278 | # Backup & report files from converting an old project file to a newer 279 | # Visual Studio version. Backup files are not needed, because we have git ;-) 280 | _UpgradeReport_Files/ 281 | Backup*/ 282 | UpgradeLog*.XML 283 | UpgradeLog*.htm 284 | 285 | # SQL Server files 286 | App_Data/*.mdf 287 | App_Data/*.ldf 288 | 289 | # Business Intelligence projects 290 | *.rdl.data 291 | *.bim.layout 292 | *.bim_*.settings 293 | 294 | # Microsoft Fakes 295 | FakesAssemblies/ 296 | 297 | # ========================= 298 | # Windows detritus 299 | # ========================= 300 | 301 | # Windows image file caches 302 | [Tt]humbs.db 303 | [Tt]humbs.db:encryptable 304 | ehthumbs.db 305 | ehthumbs_vista.db 306 | 307 | # Windows stackdumps 308 | *.stackdump 309 | 310 | # Windows shortcuts 311 | *.lnk 312 | 313 | # Folder config file 314 | [Dd]esktop.ini 315 | 316 | # Recycle Bin used on file shares 317 | $RECYCLE.BIN/ 318 | logo.h 319 | *.autosave 320 | 321 | # https://github.com/github/gitignore/blob/master/Global/Tags.gitignore 322 | # Ignore tags created by etags, ctags, gtags (GNU global) and cscope 323 | TAGS 324 | !TAGS/ 325 | tags 326 | *.tags 327 | !tags/ 328 | gtags.files 329 | GTAGS 330 | GRTAGS 331 | GPATH 332 | cscope.files 333 | cscope.out 334 | cscope.in.out 335 | cscope.po.out 336 | godot.creator.* 337 | 338 | projects/ 339 | platform/windows/godot_res.res 340 | 341 | # Visual Studio 2017 and Visual Studio Code workspace folder 342 | /.vs 343 | /.vscode 344 | 345 | # Visual Studio Code workspace file 346 | *.code-workspace 347 | 348 | # Scons construction environment dump 349 | .scons_env.json 350 | 351 | # Scons progress indicator 352 | .scons_node_count 353 | 354 | # ccls cache (https://github.com/MaskRay/ccls) 355 | .ccls-cache/ 356 | 357 | # compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html) 358 | compile_commands.json 359 | 360 | # Cppcheck 361 | *.cppcheck 362 | cppcheck-cppcheck-build-dir/ 363 | 364 | # Gcov and Lcov code coverage 365 | *.gcno 366 | *.gcda 367 | *.gcov.html 368 | *.func.html 369 | *.func-sort-c.html 370 | *index-sort-f.html 371 | *index-sort-l.html 372 | *index.html 373 | MachineIndependent/ 374 | godot.info 375 | amber.png 376 | emerald.png 377 | glass.png 378 | ruby.png 379 | snow.png 380 | updown.png 381 | gcov.css 382 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Authors 2 | 3 | This file aims at listing the developers who contributed significant patches to this MIT licensed source code. 4 | 5 | ## Developers 6 | 7 | * K. S. Ernest (iFire) Lee (fire) 8 | * Tiger C. (TGRCdev) 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Khairul Hidayat 4 | Copyright (c) 2020 Godot Engine SQLite module contributors (cf. AUTHORS.md). 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # godot-sqlite 2 | 3 | [SQLite3](https://www.sqlite.org/) wrapper for Godot Engine 4 | 5 | Migrated to https://github.com/V-Sekai/godot-libsql. 6 | 7 | ## Installation 8 | 9 | Download the latest [release](https://github.com/godot-extended-libraries/godot-sqlite/releases) of this module and uncompress it to your modules directory as `sqlite`. 10 | 11 | ## Git Installation 12 | 13 | Download using git. 14 | 15 | ``` 16 | git clone https://github.com/godot-extended-libraries/godot-sqlite.git sqlite 17 | ``` 18 | 19 | Move to the modules folder inside of the Godot Engine source. 20 | 21 | ``` 22 | mv sqlite godot/modules/ 23 | ``` 24 | 25 | ## Example usage 26 | 27 | - [SQL Queries](https://github.com/godot-extended-libraries/godot-sqlite/blob/master/demo/SQLite/sql_queries.gd) 28 | - [Game Highscore](https://github.com/godot-extended-libraries/godot-sqlite/blob/master/demo/SQLite/game_highscore.gd) 29 | - [Item Libraries](https://github.com/godot-extended-libraries/godot-sqlite/blob/master/demo/SQLite/item_database.gd) 30 | 31 | ## Attribution 32 | 33 | This engine module for Godot is based on gdsqlite-native by Khairul Hidayat in 2017. 34 | 35 | -------------------------------------------------------------------------------- /SCsub: -------------------------------------------------------------------------------- 1 | Import('env') 2 | 3 | module_env = env.Clone() 4 | module_env.Append(CPPDEFINES=[('SQLITE_ENABLE_RBU', 1)]) 5 | module_env.Append(CPPDEFINES=[('SQLITE_USE_URI', 1)]) 6 | module_env.Prepend(CPPPATH=['#thirdparty/sqlite/thirdparty/sqlite']) 7 | module_env.Append(CPPDEFINES=["SQLITE_ENABLE_JSON1"]) 8 | 9 | env_thirdparty = module_env.Clone() 10 | env_thirdparty.disable_warnings() 11 | env_thirdparty.add_source_files(env.modules_sources, "thirdparty/sqlite/*.c") 12 | 13 | module_env.add_source_files(env.modules_sources, "*.cpp") 14 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # config.py 2 | 3 | def can_build(env, platform): 4 | return True 5 | 6 | def configure(env): 7 | pass 8 | 9 | def get_doc_classes(): 10 | return [ 11 | "SQLite", 12 | "SQLiteQuery", 13 | ] 14 | 15 | def get_doc_path(): 16 | return "doc_classes" 17 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Godot-specific ignores 2 | .import/ 3 | export.cfg 4 | export_presets.cfg 5 | 6 | # Imported translations (automatically generated from CSV files) 7 | *.translation 8 | 9 | # Mono-specific ignores 10 | .mono/ 11 | data_*/ 12 | -------------------------------------------------------------------------------- /demo/SQLite/blob_data.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | onready var db = SQLite.new(); 4 | 5 | var db_path = "user://bytes_db.sqlite" 6 | 7 | var create_table_query = """ 8 | CREATE TABLE IF NOT EXISTS byte_data ( 9 | id INTEGER PRIMARY KEY, 10 | dict BLOB NOT NULL 11 | ); 12 | """ 13 | 14 | var insert_data_query = """ 15 | INSERT INTO byte_data VALUES (?, ?) 16 | """ # ? are SQLite prepared statement substitutes 17 | 18 | var select_data_query = """ 19 | SELECT dict FROM byte_data WHERE id=? LIMIT 1 20 | """ 21 | 22 | func _ready(): 23 | print(OS.get_user_data_dir()); 24 | var file = File.new(); 25 | if file.file_exists(db_path): 26 | load_db(); 27 | else: 28 | create_db(); 29 | 30 | func load_db(): 31 | db.open(db_path); 32 | var result = db.fetch_assoc_with_args(select_data_query, [0]); 33 | if result: 34 | var data = bytes2var(result[0]["dict"]); 35 | print("Byte data retrieved. Time of creation: %d:%d:%d" % 36 | [data["time_created"]["hour"], 37 | data["time_created"]["minute"], 38 | data["time_created"]["second"]]); 39 | else: 40 | print("Failed to retrieve byte data"); 41 | 42 | func create_db(): 43 | db.open(db_path); 44 | var data = Dictionary(); 45 | data["time_created"] = OS.get_time(true); 46 | print("New byte data created. Current time: %d:%d:%d" % 47 | [data["time_created"]["hour"], 48 | data["time_created"]["minute"], 49 | data["time_created"]["second"]]); 50 | var bytes = var2bytes(data); 51 | print(bytes.size()); 52 | db.query(create_table_query) 53 | db.query_with_args(insert_data_query, [0, bytes]); 54 | db.close(); 55 | -------------------------------------------------------------------------------- /demo/SQLite/game_highscore.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | # Variables 4 | var db; 5 | var highscore = 0; 6 | var row_id = 0; 7 | onready var open = false; 8 | 9 | func _ready(): 10 | # Create gdsqlite instance 11 | db = SQLite.new(); 12 | 13 | # Open the database 14 | if (not db.open("user://player_stats.sqlite")): 15 | return; 16 | 17 | open = true; 18 | 19 | # Create table 20 | var query = "CREATE TABLE IF NOT EXISTS highscore (id INTEGER PRIMARY KEY, score INTEGER NOT NULL);"; 21 | if (not db.query(query)): 22 | return; 23 | 24 | # Retrieve current highscore 25 | var rows = db.fetch_array("SELECT id, score FROM highscore LIMIT 1;"); 26 | if (rows and not rows.empty()): 27 | row_id = rows[0]['id']; 28 | highscore = rows[0]['score']; 29 | 30 | # Test 31 | set_highscore(1000); 32 | set_highscore(2000); 33 | set_highscore(10000); 34 | set_highscore(50000); 35 | print("High score: ", get_highscore()); 36 | 37 | func _exit_tree(): 38 | if (db): 39 | # Close database 40 | db.close(); 41 | 42 | func set_highscore(score): 43 | if not open: 44 | return; 45 | 46 | # Update highscore 47 | highscore = score; 48 | 49 | # Execute sql syntax 50 | if (row_id > 0): 51 | db.query_with_args("UPDATE highscore SET score=? WHERE id=?;", [highscore, row_id]); 52 | else: 53 | db.query_with_args("INSERT INTO highscore (score) VALUES (?);", [row_id]); 54 | row_id = db.fetch_array_with_args("SELECT last_insert_rowid()", [])[0]['last_insert_rowid()']; 55 | 56 | func get_highscore(): 57 | if not open: 58 | return; 59 | 60 | # Retrieve highscore from database 61 | var rows = db.fetch_array_with_args("SELECT score FROM highscore WHERE id=? LIMIT 1;", [row_id]); 62 | if (rows and not rows.empty()): 63 | highscore = rows[0]['score']; 64 | 65 | # Return the highscore 66 | return highscore; 67 | -------------------------------------------------------------------------------- /demo/SQLite/item_database.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | # SQLite module 4 | # Variables 5 | var item_list = []; 6 | 7 | func _ready() -> void: 8 | # Create new gdsqlite instance 9 | var db = SQLite.new(); 10 | 11 | # Open item database 12 | if (!open_database(db, "res://items.db")): 13 | print("Failed opening database."); 14 | return; 15 | 16 | # Get item list from db 17 | var pots = db.fetch_array("SELECT * FROM potion ORDER BY id ASC"); 18 | if (not pots or pots.empty()): 19 | return; 20 | 21 | for pot in pots: 22 | # Create new item from database 23 | var item = { 24 | 'id': pot['id'], 25 | 'name': pot['name'], 26 | 'price': pot['price'], 27 | 'heals': pot['heals'] 28 | }; 29 | 30 | # Add to item list 31 | item_list.append(item); 32 | 33 | # Print all item 34 | for i in item_list: 35 | print("Item ", i.id, " (", i.name, ") $", i.price, " +", i.heals, "hp"); 36 | 37 | func open_database(db : SQLite, path : String) -> bool: 38 | if (path.begins_with("res://")): 39 | # Open packed database 40 | var file = File.new(); 41 | if (file.open(path, file.READ) != OK): 42 | return false; 43 | var size = file.get_length(); 44 | var buffers = file.get_buffer(size); 45 | return db.open_buffered(path, buffers, size); 46 | 47 | # Open database normally 48 | return db.open(path); 49 | -------------------------------------------------------------------------------- /demo/SQLite/sql_queries.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | func _ready(): 4 | # Create gdsqlite instance 5 | var db = SQLite.new(); 6 | 7 | # Open database 8 | if (!db.open("user://godot.sqlite")): 9 | return; 10 | 11 | var query = ""; 12 | var result = null; 13 | 14 | # Create table 15 | query = "CREATE TABLE IF NOT EXISTS users ("; 16 | query += "id integer PRIMARY KEY,"; 17 | query += "first_name text NOT NULL,"; 18 | query += "last_name text NOT NULL,"; 19 | query += "email text NOT NULL"; 20 | query += ");"; 21 | result = db.query(query); 22 | 23 | # Fetch rows 24 | query = "SELECT * FROM users;"; 25 | result = db.fetch_array(query); 26 | 27 | if (!result || result.size() <= 0): 28 | # Insert new row 29 | query = "INSERT INTO users (first_name, last_name, email) VALUES ('godot', 'engine', 'user@users.org');"; 30 | result = db.query(query); 31 | 32 | if (!result): 33 | print("Cannot insert data!"); 34 | else: 35 | print("Data inserted into table."); 36 | 37 | else: 38 | # Print rows 39 | for i in result: 40 | print(i); 41 | 42 | # Close database 43 | db.close(); 44 | -------------------------------------------------------------------------------- /demo/SQLite/test_sqlite.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://SQLite/item_database.gd" type="Script" id=1] 4 | [ext_resource path="res://SQLite/sql_queries.gd" type="Script" id=2] 5 | [ext_resource path="res://SQLite/game_highscore.gd" type="Script" id=3] 6 | [ext_resource path="res://SQLite/blob_data.gd" type="Script" id=4] 7 | 8 | [node name="Node" type="Node"] 9 | 10 | [node name="ItemDatabase" type="Node" parent="."] 11 | script = ExtResource( 1 ) 12 | 13 | [node name="SqlQueries" type="Node" parent="."] 14 | script = ExtResource( 2 ) 15 | 16 | [node name="GameHighScore" type="Node" parent="."] 17 | script = ExtResource( 3 ) 18 | 19 | [node name="BLOBData" type="Node" parent="."] 20 | script = ExtResource( 4 ) 21 | -------------------------------------------------------------------------------- /demo/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) 5 | sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) 6 | sky_curve = 0.25 7 | ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) 8 | ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) 9 | ground_curve = 0.01 10 | sun_energy = 16.0 11 | 12 | [resource] 13 | background_mode = 2 14 | background_sky = SubResource( 1 ) 15 | -------------------------------------------------------------------------------- /demo/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godot-extended-libraries/godot-sqlite/1962a384398d32696adb17ff0053d93d1f31bf2c/demo/icon.png -------------------------------------------------------------------------------- /demo/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /demo/items.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/godot-extended-libraries/godot-sqlite/1962a384398d32696adb17ff0053d93d1f31bf2c/demo/items.db -------------------------------------------------------------------------------- /demo/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ ] 12 | _global_script_class_icons={ 13 | 14 | } 15 | 16 | [application] 17 | 18 | config/name="SQLiteTest" 19 | run/main_scene="res://SQLite/test_sqlite.tscn" 20 | config/icon="res://icon.png" 21 | 22 | [gdnative] 23 | 24 | singletons=[ ] 25 | 26 | [rendering] 27 | 28 | environment/default_environment="res://default_env.tres" 29 | -------------------------------------------------------------------------------- /doc_classes/SQLite.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Wrapper class for SQLite databases. 5 | 6 | 7 | A wrapper class that lets you perform SQL statements on an SQLite database file. 8 | For queries that involve arbitrary user input, you should use methods that end in [code]*_with_args[/code], as these protect against SQL injection. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Closes the database handle. 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Returns the result of [code]statement[/code] as an [Array] of rows. 30 | Each row is a [Dictionary], and each column can be accessed with either its name or its column position. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Returns the result of [code]statement[/code] as an [Array] of rows, substituting each [code]?[/code] with [code]args[/code]. 39 | Each row is a [Dictionary], and each column can be accessed with either its name or its column position. 40 | 41 | 42 | 43 | 44 | 45 | 46 | Returns the result of [code]statement[/code] as an [Array] of rows. 47 | Each row is a [Dictionary], and the keys are the names of the columns. 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Returns the result of [code]statement[/code] as an [Array] of rows, substituting each [code]?[/code] with [code]args[/code]. 56 | Each row is a [Dictionary], and the keys are the names of the columns. 57 | 58 | 59 | 60 | 61 | 62 | 63 | Opens the database file at the given path. Returns [code]true[/code] if the database was successfully opened, [code]false[/code] otherwise. 64 | If the path starts with "res://", it will use [method open_buffered] implicitly. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Opens a temporary database with the data in [code]buffer[/code]. Used for opening databases stored in res:// or compressed databases. Returns [code]true[/code] if the database was opened successfully. 74 | Can be written to, but the changes are NOT saved! 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Queries the database with the given SQL statement. Returns [code]true[/code] if no errors occurred. 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Queries the database with the given SQL statement, replacing any [code]?[/code] with arguments supplied by [code]args[/code]. Returns [code]true[/code] if no errors occurred. 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /doc_classes/SQLiteQuery.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /register_types.cpp: -------------------------------------------------------------------------------- 1 | #include "register_types.h" 2 | 3 | #include "core/object/class_db.h" 4 | #include "sqlite.h" 5 | 6 | void initialize_sqlite_module(ModuleInitializationLevel p_level) { 7 | if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) { 8 | return; 9 | } 10 | ClassDB::register_class(); 11 | ClassDB::register_class(); 12 | } 13 | 14 | void uninitialize_sqlite_module(ModuleInitializationLevel p_level) { 15 | if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) { 16 | return; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /register_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "modules/register_module_types.h" 4 | 5 | void initialize_sqlite_module(ModuleInitializationLevel p_level); 6 | void uninitialize_sqlite_module(ModuleInitializationLevel p_level); 7 | -------------------------------------------------------------------------------- /sqlite.cpp: -------------------------------------------------------------------------------- 1 | #include "sqlite.h" 2 | #include "core/core_bind.h" 3 | #include "core/os/os.h" 4 | #include "editor/project_settings_editor.h" 5 | 6 | Array fast_parse_row(sqlite3_stmt *stmt) { 7 | Array result; 8 | 9 | // Get column count 10 | const int col_count = sqlite3_column_count(stmt); 11 | 12 | // Fetch all column 13 | for (int i = 0; i < col_count; i++) { 14 | // Value 15 | const int col_type = sqlite3_column_type(stmt, i); 16 | Variant value; 17 | 18 | // Get column value 19 | switch (col_type) { 20 | case SQLITE_INTEGER: 21 | value = Variant(sqlite3_column_int(stmt, i)); 22 | break; 23 | 24 | case SQLITE_FLOAT: 25 | value = Variant(sqlite3_column_double(stmt, i)); 26 | break; 27 | 28 | case SQLITE_TEXT: { 29 | int size = sqlite3_column_bytes(stmt, i); 30 | String str = 31 | String::utf8((const char *)sqlite3_column_text(stmt, i), size); 32 | value = Variant(str); 33 | break; 34 | } 35 | case SQLITE_BLOB: { 36 | PackedByteArray arr; 37 | int size = sqlite3_column_bytes(stmt, i); 38 | arr.resize(size); 39 | memcpy(arr.ptrw(), sqlite3_column_blob(stmt, i), size); 40 | value = Variant(arr); 41 | break; 42 | } 43 | case SQLITE_NULL: { 44 | // Nothing to do. 45 | } break; 46 | default: 47 | ERR_PRINT("This kind of data is not yet supported: " + itos(col_type)); 48 | break; 49 | } 50 | 51 | result.push_back(value); 52 | } 53 | 54 | return result; 55 | } 56 | 57 | SQLiteQuery::SQLiteQuery() {} 58 | 59 | SQLiteQuery::~SQLiteQuery() { finalize(); } 60 | 61 | void SQLiteQuery::init(SQLite *p_db, const String &p_query) { 62 | db = p_db; 63 | query = p_query; 64 | stmt = nullptr; 65 | } 66 | 67 | bool SQLiteQuery::is_ready() const { return stmt != nullptr; } 68 | 69 | String SQLiteQuery::get_last_error_message() const { 70 | ERR_FAIL_COND_V(db == nullptr, "Database is undefined."); 71 | return db->get_last_error_message(); 72 | } 73 | 74 | Variant SQLiteQuery::execute(const Array p_args) { 75 | if (is_ready() == false) { 76 | ERR_FAIL_COND_V(prepare() == false, Variant()); 77 | } 78 | 79 | // At this point stmt can't be null. 80 | CRASH_COND(stmt == nullptr); 81 | 82 | // Error occurred during argument binding 83 | if (!SQLite::bind_args(stmt, p_args)) { 84 | ERR_FAIL_V_MSG(Variant(), 85 | "Error during arguments set: " + get_last_error_message()); 86 | } 87 | 88 | // Execute the query. 89 | Array result; 90 | while (true) { 91 | const int res = sqlite3_step(stmt); 92 | if (res == SQLITE_ROW) { 93 | // Collect the result. 94 | result.append(fast_parse_row(stmt)); 95 | } else if (res == SQLITE_DONE) { 96 | // Nothing more to do. 97 | break; 98 | } else { 99 | // Error 100 | ERR_BREAK_MSG(true, "There was an error during an SQL execution: " + 101 | get_last_error_message()); 102 | } 103 | } 104 | 105 | if (SQLITE_OK != sqlite3_reset(stmt)) { 106 | finalize(); 107 | ERR_FAIL_V_MSG(result, "Was not possible to reset the query: " + 108 | get_last_error_message()); 109 | } 110 | 111 | return result; 112 | } 113 | 114 | Variant SQLiteQuery::batch_execute(Array p_rows) { 115 | Array res; 116 | for (int i = 0; i < p_rows.size(); i += 1) { 117 | ERR_FAIL_COND_V_MSG(p_rows[i].get_type() != Variant::ARRAY, Variant(), 118 | "An Array of Array is exepected."); 119 | Variant r = execute(p_rows[i]); 120 | if (unlikely(r.get_type() == Variant::NIL)) { 121 | // An error occurred, the error is already logged. 122 | return Variant(); 123 | } 124 | res.push_back(r); 125 | } 126 | return res; 127 | } 128 | 129 | Array SQLiteQuery::get_columns() { 130 | if (is_ready() == false) { 131 | ERR_FAIL_COND_V(prepare() == false, Array()); 132 | } 133 | 134 | // At this point stmt can't be null. 135 | CRASH_COND(stmt == nullptr); 136 | 137 | Array res; 138 | const int col_count = sqlite3_column_count(stmt); 139 | res.resize(col_count); 140 | 141 | // Fetch all column 142 | for (int i = 0; i < col_count; i++) { 143 | // Key name 144 | const char *col_name = sqlite3_column_name(stmt, i); 145 | res[i] = String(col_name); 146 | } 147 | 148 | return res; 149 | } 150 | 151 | bool SQLiteQuery::prepare() { 152 | ERR_FAIL_COND_V(stmt != nullptr, false); 153 | ERR_FAIL_COND_V(db == nullptr, false); 154 | ERR_FAIL_COND_V(query == "", false); 155 | 156 | // Prepare the statement 157 | int result = sqlite3_prepare_v2(db->get_handler(), query.utf8().ptr(), -1, 158 | &stmt, nullptr); 159 | 160 | // Cannot prepare query! 161 | ERR_FAIL_COND_V_MSG(result != SQLITE_OK, false, 162 | "SQL Error: " + db->get_last_error_message()); 163 | 164 | return true; 165 | } 166 | 167 | void SQLiteQuery::finalize() { 168 | if (stmt) { 169 | sqlite3_finalize(stmt); 170 | stmt = nullptr; 171 | } 172 | } 173 | 174 | void SQLiteQuery::_bind_methods() { 175 | ClassDB::bind_method(D_METHOD("get_last_error_message"), 176 | &SQLiteQuery::get_last_error_message); 177 | ClassDB::bind_method(D_METHOD("execute", "arguments"), &SQLiteQuery::execute, 178 | DEFVAL(Array())); 179 | ClassDB::bind_method(D_METHOD("batch_execute", "rows"), 180 | &SQLiteQuery::batch_execute); 181 | ClassDB::bind_method(D_METHOD("get_columns"), &SQLiteQuery::get_columns); 182 | } 183 | 184 | SQLite::SQLite() { 185 | db = nullptr; 186 | memory_read = false; 187 | } 188 | /* 189 | Open a database file. 190 | If this is running outside of the editor, databases under res:// are 191 | assumed to be packed. 192 | @param path The database resource path. 193 | @return status 194 | */ 195 | bool SQLite::open(String path) { 196 | if (!path.strip_edges().length()) 197 | return false; 198 | 199 | if (!Engine::get_singleton()->is_editor_hint() && 200 | path.begins_with("res://")) { 201 | Ref dbfile; 202 | dbfile.instantiate(); 203 | if (dbfile->open(path, core_bind::File::READ) != Error::OK) { 204 | print_error("Cannot open packed database!"); 205 | return false; 206 | } 207 | int64_t size = dbfile->get_length(); 208 | PackedByteArray buffer = dbfile->get_buffer(size); 209 | return open_buffered(path, buffer, size); 210 | } 211 | 212 | String real_path = 213 | ProjectSettings::get_singleton()->globalize_path(path.strip_edges()); 214 | 215 | int result = sqlite3_open(real_path.utf8().get_data(), &db); 216 | 217 | if (result != SQLITE_OK) { 218 | print_error("Cannot open database!"); 219 | return false; 220 | } 221 | 222 | return true; 223 | } 224 | 225 | bool SQLite::open_in_memory() { 226 | int result = sqlite3_open(":memory:", &db); 227 | ERR_FAIL_COND_V_MSG(result != SQLITE_OK, false, 228 | "Cannot open database in memory, error:" + itos(result)); 229 | return true; 230 | } 231 | 232 | /* 233 | Open the database and initialize memory buffer. 234 | @param name Name of the database. 235 | @param buffers The database buffer. 236 | @param size Size of the database; 237 | @return status 238 | */ 239 | bool SQLite::open_buffered(String name, PackedByteArray buffers, int64_t size) { 240 | if (!name.strip_edges().length()) { 241 | return false; 242 | } 243 | 244 | if (!buffers.size() || !size) { 245 | return false; 246 | } 247 | 248 | spmembuffer_t *p_mem = (spmembuffer_t *)calloc(1, sizeof(spmembuffer_t)); 249 | p_mem->total = p_mem->used = size; 250 | p_mem->data = (char *)malloc(size + 1); 251 | memcpy(p_mem->data, buffers.ptr(), size); 252 | p_mem->data[size] = '\0'; 253 | 254 | // 255 | spmemvfs_env_init(); 256 | int err = spmemvfs_open_db(&p_db, name.utf8().get_data(), p_mem); 257 | 258 | if (err != SQLITE_OK || p_db.mem != p_mem) { 259 | print_error("Cannot open buffered database!"); 260 | return false; 261 | } 262 | 263 | memory_read = true; 264 | return true; 265 | } 266 | 267 | void SQLite::close() { 268 | // Finalize all queries before close the DB. 269 | // Reverse order because I need to remove the not available queries. 270 | for (uint32_t i = queries.size(); i > 0; i -= 1) { 271 | SQLiteQuery *query = 272 | Object::cast_to(queries[i - 1]->get_ref()); 273 | if (query != nullptr) { 274 | query->finalize(); 275 | } else { 276 | memdelete(queries[i - 1]); 277 | queries.remove_at(i - 1); 278 | } 279 | } 280 | 281 | if (db) { 282 | // Cannot close database! 283 | if (sqlite3_close_v2(db) != SQLITE_OK) { 284 | print_error("Cannot close database: " + get_last_error_message()); 285 | } else { 286 | db = nullptr; 287 | } 288 | } 289 | 290 | if (memory_read) { 291 | // Close virtual filesystem database 292 | spmemvfs_close_db(&p_db); 293 | spmemvfs_env_fini(); 294 | memory_read = false; 295 | } 296 | } 297 | 298 | sqlite3_stmt *SQLite::prepare(const char *query) { 299 | // Get database pointer 300 | sqlite3 *dbs = get_handler(); 301 | 302 | ERR_FAIL_COND_V_MSG(dbs == nullptr, nullptr, 303 | "Cannot prepare query! Database is not opened."); 304 | 305 | // Prepare the statement 306 | sqlite3_stmt *stmt = nullptr; 307 | int result = sqlite3_prepare_v2(dbs, query, -1, &stmt, nullptr); 308 | 309 | // Cannot prepare query! 310 | ERR_FAIL_COND_V_MSG(result != SQLITE_OK, nullptr, 311 | "SQL Error: " + get_last_error_message()); 312 | return stmt; 313 | } 314 | 315 | bool SQLite::bind_args(sqlite3_stmt *stmt, Array args) { 316 | // Check parameter count 317 | int param_count = sqlite3_bind_parameter_count(stmt); 318 | if (param_count != args.size()) { 319 | print_error("SQLiteQuery failed; expected " + itos(param_count) + 320 | " arguments, got " + itos(args.size())); 321 | return false; 322 | } 323 | 324 | /** 325 | * SQLite data types: 326 | * - NULL 327 | * - INTEGER (signed, max 8 bytes) 328 | * - REAL (stored as a double-precision float) 329 | * - TEXT (stored in database encoding of UTF-8, UTF-16BE or UTF-16LE) 330 | * - BLOB (1:1 storage) 331 | */ 332 | 333 | for (int i = 0; i < param_count; i++) { 334 | int retcode; 335 | switch (args[i].get_type()) { 336 | case Variant::Type::NIL: 337 | retcode = sqlite3_bind_null(stmt, i + 1); 338 | break; 339 | case Variant::Type::BOOL: 340 | case Variant::Type::INT: 341 | retcode = sqlite3_bind_int(stmt, i + 1, (int)args[i]); 342 | break; 343 | case Variant::Type::FLOAT: 344 | retcode = sqlite3_bind_double(stmt, i + 1, (double)args[i]); 345 | break; 346 | case Variant::Type::STRING: 347 | retcode = sqlite3_bind_text( 348 | stmt, i + 1, String(args[i]).utf8().get_data(), -1, SQLITE_TRANSIENT); 349 | break; 350 | case Variant::Type::PACKED_BYTE_ARRAY: 351 | retcode = 352 | sqlite3_bind_blob(stmt, i + 1, PackedByteArray(args[i]).ptr(), 353 | PackedByteArray(args[i]).size(), SQLITE_TRANSIENT); 354 | break; 355 | default: 356 | print_error( 357 | "SQLite was passed unhandled Variant with TYPE_* enum " + 358 | itos(args[i].get_type()) + 359 | ". Please serialize your object into a String or a PoolByteArray.\n"); 360 | return false; 361 | } 362 | 363 | if (retcode != SQLITE_OK) { 364 | print_error( 365 | "SQLiteQuery failed, an error occured while binding argument" + 366 | itos(i + 1) + " of " + itos(args.size()) + " (SQLite errcode " + 367 | itos(retcode) + ")"); 368 | return false; 369 | } 370 | } 371 | 372 | return true; 373 | } 374 | 375 | bool SQLite::query_with_args(String query, Array args) { 376 | sqlite3_stmt *stmt = prepare(query.utf8().get_data()); 377 | 378 | // Failed to prepare the query 379 | ERR_FAIL_COND_V_MSG(stmt == nullptr, false, 380 | "SQLiteQuery preparation error: " + 381 | get_last_error_message()); 382 | 383 | // Error occurred during argument binding 384 | if (!bind_args(stmt, args)) { 385 | sqlite3_finalize(stmt); 386 | ERR_FAIL_V_MSG(false, 387 | "Error during arguments bind: " + get_last_error_message()); 388 | } 389 | 390 | // Evaluate the sql query 391 | sqlite3_step(stmt); 392 | sqlite3_finalize(stmt); 393 | 394 | return true; 395 | } 396 | 397 | Ref SQLite::create_query(String p_query) { 398 | Ref query; 399 | query.instantiate(); 400 | query->init(this, p_query); 401 | 402 | WeakRef *wr = memnew(WeakRef); 403 | wr->set_obj(query.ptr()); 404 | queries.push_back(wr); 405 | 406 | return query; 407 | } 408 | 409 | bool SQLite::query(String query) { 410 | return this->query_with_args(query, Array()); 411 | } 412 | 413 | Array SQLite::fetch_rows(String statement, Array args, int result_type) { 414 | Array result; 415 | 416 | // Empty statement 417 | if (!statement.strip_edges().length()) { 418 | return result; 419 | } 420 | 421 | // Cannot prepare query 422 | sqlite3_stmt *stmt = prepare(statement.strip_edges().utf8().get_data()); 423 | if (!stmt) { 424 | return result; 425 | } 426 | 427 | // Bind arguments 428 | if (!bind_args(stmt, args)) { 429 | sqlite3_finalize(stmt); 430 | return result; 431 | } 432 | 433 | // Fetch rows 434 | while (sqlite3_step(stmt) == SQLITE_ROW) { 435 | // Do a step 436 | result.append(parse_row(stmt, result_type)); 437 | } 438 | 439 | // Delete prepared statement 440 | sqlite3_finalize(stmt); 441 | 442 | // Return the result 443 | return result; 444 | } 445 | 446 | Dictionary SQLite::parse_row(sqlite3_stmt *stmt, int result_type) { 447 | Dictionary result; 448 | 449 | // Get column count 450 | int col_count = sqlite3_column_count(stmt); 451 | 452 | // Fetch all column 453 | for (int i = 0; i < col_count; i++) { 454 | // Key name 455 | const char *col_name = sqlite3_column_name(stmt, i); 456 | String key = String(col_name); 457 | 458 | // Value 459 | int col_type = sqlite3_column_type(stmt, i); 460 | Variant value; 461 | 462 | // Get column value 463 | switch (col_type) { 464 | case SQLITE_INTEGER: 465 | value = Variant(sqlite3_column_int(stmt, i)); 466 | break; 467 | 468 | case SQLITE_FLOAT: 469 | value = Variant(sqlite3_column_double(stmt, i)); 470 | break; 471 | 472 | case SQLITE_TEXT: { 473 | int size = sqlite3_column_bytes(stmt, i); 474 | String str = 475 | String::utf8((const char *)sqlite3_column_text(stmt, i), size); 476 | value = Variant(str); 477 | break; 478 | } 479 | case SQLITE_BLOB: { 480 | PackedByteArray arr; 481 | int size = sqlite3_column_bytes(stmt, i); 482 | arr.resize(size); 483 | memcpy((void *)arr.ptr(), sqlite3_column_blob(stmt, i), size); 484 | value = Variant(arr); 485 | break; 486 | } 487 | 488 | default: 489 | break; 490 | } 491 | 492 | // Set dictionary value 493 | if (result_type == RESULT_NUM) 494 | result[i] = value; 495 | else if (result_type == RESULT_ASSOC) 496 | result[key] = value; 497 | else { 498 | result[i] = value; 499 | result[key] = value; 500 | } 501 | } 502 | 503 | return result; 504 | } 505 | 506 | Array SQLite::fetch_array(String query) { 507 | return fetch_rows(query, Array(), RESULT_BOTH); 508 | } 509 | 510 | Array SQLite::fetch_array_with_args(String query, Array args) { 511 | return fetch_rows(query, args, RESULT_BOTH); 512 | } 513 | 514 | Array SQLite::fetch_assoc(String query) { 515 | return fetch_rows(query, Array(), RESULT_ASSOC); 516 | } 517 | 518 | Array SQLite::fetch_assoc_with_args(String query, Array args) { 519 | return fetch_rows(query, args, RESULT_ASSOC); 520 | } 521 | 522 | String SQLite::get_last_error_message() const { 523 | return sqlite3_errmsg(get_handler()); 524 | } 525 | 526 | SQLite::~SQLite() { 527 | // Close database 528 | close(); 529 | // Make sure to invalidate all associated queries. 530 | for (uint32_t i = 0; i < queries.size(); i += 1) { 531 | SQLiteQuery *query = Object::cast_to(queries[i]->get_ref()); 532 | if (query != nullptr) { 533 | query->init(nullptr, ""); 534 | } 535 | } 536 | } 537 | 538 | void SQLite::_bind_methods() { 539 | ClassDB::bind_method(D_METHOD("open", "path"), &SQLite::open); 540 | ClassDB::bind_method(D_METHOD("open_in_memory"), &SQLite::open_in_memory); 541 | ClassDB::bind_method(D_METHOD("open_buffered", "path", "buffers", "size"), 542 | &SQLite::open_buffered); 543 | 544 | ClassDB::bind_method(D_METHOD("close"), &SQLite::close); 545 | 546 | ClassDB::bind_method(D_METHOD("create_query", "statement"), 547 | &SQLite::create_query); 548 | 549 | ClassDB::bind_method(D_METHOD("query", "statement"), &SQLite::query); 550 | ClassDB::bind_method(D_METHOD("query_with_args", "statement", "args"), 551 | &SQLite::query_with_args); 552 | ClassDB::bind_method(D_METHOD("fetch_array", "statement"), 553 | &SQLite::fetch_array); 554 | ClassDB::bind_method(D_METHOD("fetch_array_with_args", "statement", "args"), 555 | &SQLite::fetch_array_with_args); 556 | ClassDB::bind_method(D_METHOD("fetch_assoc", "statement"), 557 | &SQLite::fetch_assoc); 558 | ClassDB::bind_method(D_METHOD("fetch_assoc_with_args", "statement", "args"), 559 | &SQLite::fetch_assoc_with_args); 560 | } 561 | -------------------------------------------------------------------------------- /sqlite.h: -------------------------------------------------------------------------------- 1 | #ifndef GDSQLITE_H 2 | #define GDSQLITE_H 3 | 4 | #include "core/config/engine.h" 5 | #include "core/object/ref_counted.h" 6 | #include "core/templates/local_vector.h" 7 | 8 | // SQLite3 9 | #include "thirdparty/sqlite/spmemvfs.h" 10 | #include "thirdparty/sqlite/sqlite3.h" 11 | 12 | class SQLite; 13 | 14 | class SQLiteQuery : public RefCounted { 15 | GDCLASS(SQLiteQuery, RefCounted); 16 | 17 | SQLite *db = nullptr; 18 | sqlite3_stmt *stmt = nullptr; 19 | String query; 20 | 21 | protected: 22 | static void _bind_methods(); 23 | 24 | public: 25 | SQLiteQuery(); 26 | ~SQLiteQuery(); 27 | 28 | void init(SQLite *p_db, const String &p_query); 29 | 30 | bool is_ready() const; 31 | 32 | /// Returns the last error message. 33 | String get_last_error_message() const; 34 | 35 | /// Executes the query. 36 | /// ``` 37 | /// var query = db.create_query("SELECT * FROM table_name;") 38 | /// print(query.execute()) 39 | /// # prints: [[0, 1], [1, 1], [2, 1]] 40 | /// ``` 41 | /// 42 | /// You can also pass some arguments: 43 | /// ``` 44 | /// var query = db.create_query("INSERT INTO table_name (column1, column2) 45 | /// VALUES (?, ?); ") print(query.execute([0,1])) # prints: [] 46 | /// ``` 47 | /// 48 | /// In case of error, a Variant() is returned and the error is logged. 49 | /// You can also use `get_last_error_message()` to retrieve the message. 50 | Variant execute(Array p_args = Array()); 51 | 52 | /// Expects an array of arguments array. 53 | /// Executes N times the query, for N array. 54 | /// ``` 55 | /// var query = db.create_query("INSERT INTO table_name (column1, column2) 56 | /// VALUES (?, ?); ") query.batch_execute([[0,1], [1,2], [2,3]]) 57 | /// ``` 58 | /// The above script insert 3 rows. 59 | /// 60 | /// Also works with a select: 61 | /// ``` 62 | /// var query = db.create_query("SELECT * FROM table_name WHERE column1 = ?;") 63 | /// query.batch_execute([[0], [1], [2]]) 64 | /// ``` 65 | /// Returns: `[[0,1], [1,2], [2,3]]` 66 | Variant batch_execute(Array p_rows); 67 | 68 | /// Return the list of columns of this query. 69 | Array get_columns(); 70 | 71 | void finalize(); 72 | 73 | private: 74 | bool prepare(); 75 | }; 76 | 77 | class SQLite : public RefCounted { 78 | GDCLASS(SQLite, RefCounted); 79 | 80 | friend class SQLiteQuery; 81 | 82 | private: 83 | // sqlite handler 84 | sqlite3 *db; 85 | 86 | // vfs 87 | spmemvfs_db_t p_db; 88 | bool memory_read; 89 | 90 | ::LocalVector queries; 91 | 92 | sqlite3_stmt *prepare(const char *statement); 93 | Array fetch_rows(String query, Array args, int result_type = RESULT_BOTH); 94 | sqlite3 *get_handler() const { return memory_read ? p_db.handle : db; } 95 | Dictionary parse_row(sqlite3_stmt *stmt, int result_type); 96 | 97 | public: 98 | static bool bind_args(sqlite3_stmt *stmt, Array args); 99 | 100 | protected: 101 | static void _bind_methods(); 102 | 103 | public: 104 | enum { RESULT_BOTH = 0, RESULT_NUM, RESULT_ASSOC }; 105 | 106 | SQLite(); 107 | ~SQLite(); 108 | 109 | // methods 110 | bool open(String path); 111 | bool open_in_memory(); 112 | bool open_buffered(String name, PackedByteArray buffers, int64_t size); 113 | void close(); 114 | 115 | /// Compiles the query into bytecode and returns an handle to it for a faster 116 | /// execution. 117 | /// Note: you can create the query at any time, but you can execute it only 118 | /// when the DB is open. 119 | Ref create_query(String p_query); 120 | 121 | bool query(String statement); 122 | bool query_with_args(String statement, Array args); 123 | Array fetch_array(String statement); 124 | Array fetch_array_with_args(String statement, Array args); 125 | Array fetch_assoc(String statement); 126 | Array fetch_assoc_with_args(String statement, Array args); 127 | 128 | String get_last_error_message() const; 129 | }; 130 | #endif 131 | -------------------------------------------------------------------------------- /thirdparty/sqlite/spmemvfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 2-Clause License 3 | * 4 | * Copyright 2009 Stephen Liu 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma warning(disable: 4996) // Fixes "unsafe" warnings for strdup and strncpy 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "spmemvfs.h" 36 | 37 | #include "sqlite3.h" 38 | 39 | /* Useful macros used in several places */ 40 | #define SPMEMVFS_MIN(x,y) ((x)<(y)?(x):(y)) 41 | #define SPMEMVFS_MAX(x,y) ((x)>(y)?(x):(y)) 42 | 43 | static void spmemvfsDebug(const char *format, ...){ 44 | 45 | #if defined(SPMEMVFS_DEBUG) 46 | 47 | char logTemp[ 1024 ] = { 0 }; 48 | 49 | va_list vaList; 50 | va_start( vaList, format ); 51 | vsnprintf( logTemp, sizeof( logTemp ), format, vaList ); 52 | va_end ( vaList ); 53 | 54 | if( strchr( logTemp, '\n' ) ) { 55 | printf( "%s", logTemp ); 56 | } else { 57 | printf( "%s\n", logTemp ); 58 | } 59 | #endif 60 | 61 | } 62 | 63 | //=========================================================================== 64 | 65 | typedef struct spmemfile_t { 66 | sqlite3_file base; 67 | char * path; 68 | int flags; 69 | spmembuffer_t * mem; 70 | } spmemfile_t; 71 | 72 | static int spmemfileClose( sqlite3_file * file ); 73 | static int spmemfileRead( sqlite3_file * file, void * buffer, int len, sqlite3_int64 offset ); 74 | static int spmemfileWrite( sqlite3_file * file, const void * buffer, int len, sqlite3_int64 offset ); 75 | static int spmemfileTruncate( sqlite3_file * file, sqlite3_int64 size ); 76 | static int spmemfileSync( sqlite3_file * file, int flags ); 77 | static int spmemfileFileSize( sqlite3_file * file, sqlite3_int64 * size ); 78 | static int spmemfileLock( sqlite3_file * file, int type ); 79 | static int spmemfileUnlock( sqlite3_file * file, int type ); 80 | static int spmemfileCheckReservedLock( sqlite3_file * file, int * result ); 81 | static int spmemfileFileControl( sqlite3_file * file, int op, void * arg ); 82 | static int spmemfileSectorSize( sqlite3_file * file ); 83 | static int spmemfileDeviceCharacteristics( sqlite3_file * file ); 84 | 85 | static sqlite3_io_methods g_spmemfile_io_memthods = { 86 | 1, /* iVersion */ 87 | spmemfileClose, /* xClose */ 88 | spmemfileRead, /* xRead */ 89 | spmemfileWrite, /* xWrite */ 90 | spmemfileTruncate, /* xTruncate */ 91 | spmemfileSync, /* xSync */ 92 | spmemfileFileSize, /* xFileSize */ 93 | spmemfileLock, /* xLock */ 94 | spmemfileUnlock, /* xUnlock */ 95 | spmemfileCheckReservedLock, /* xCheckReservedLock */ 96 | spmemfileFileControl, /* xFileControl */ 97 | spmemfileSectorSize, /* xSectorSize */ 98 | spmemfileDeviceCharacteristics /* xDeviceCharacteristics */ 99 | }; 100 | 101 | int spmemfileClose( sqlite3_file * file ) 102 | { 103 | spmemfile_t * memfile = (spmemfile_t*)file; 104 | 105 | spmemvfsDebug( "call %s( %p )", __func__, memfile ); 106 | 107 | if( SQLITE_OPEN_MAIN_DB & memfile->flags ) { 108 | // noop 109 | } else { 110 | if( NULL != memfile->mem ) { 111 | if( memfile->mem->data ) free( memfile->mem->data ); 112 | free( memfile->mem ); 113 | } 114 | } 115 | 116 | free( memfile->path ); 117 | 118 | return SQLITE_OK; 119 | } 120 | 121 | int spmemfileRead( sqlite3_file * file, void * buffer, int len, sqlite3_int64 offset ) 122 | { 123 | spmemfile_t * memfile = (spmemfile_t*)file; 124 | 125 | spmemvfsDebug( "call %s( %p, ..., %d, %lld ), len %d", 126 | __func__, memfile, len, offset, memfile->mem->used ); 127 | 128 | if( ( offset + len ) > memfile->mem->used ) { 129 | return SQLITE_IOERR_SHORT_READ; 130 | } 131 | 132 | memcpy( buffer, memfile->mem->data + offset, len ); 133 | 134 | return SQLITE_OK; 135 | } 136 | 137 | int spmemfileWrite( sqlite3_file * file, const void * buffer, int len, sqlite3_int64 offset ) 138 | { 139 | spmemfile_t * memfile = (spmemfile_t*)file; 140 | spmembuffer_t * mem = memfile->mem; 141 | 142 | spmemvfsDebug( "call %s( %p, ..., %d, %lld ), len %d", 143 | __func__, memfile, len, offset, mem->used ); 144 | 145 | if( ( offset + len ) > mem->total ) { 146 | int64_t newTotal = 2 * ( offset + len + mem->total ); 147 | char * newBuffer = (char*)realloc( mem->data, newTotal ); 148 | if( NULL == newBuffer ) { 149 | return SQLITE_NOMEM; 150 | } 151 | 152 | mem->total = newTotal; 153 | mem->data = newBuffer; 154 | } 155 | 156 | memcpy( mem->data + offset, buffer, len ); 157 | 158 | mem->used = SPMEMVFS_MAX( mem->used, offset + len ); 159 | 160 | return SQLITE_OK; 161 | } 162 | 163 | int spmemfileTruncate( sqlite3_file * file, sqlite3_int64 size ) 164 | { 165 | spmemfile_t * memfile = (spmemfile_t*)file; 166 | 167 | spmemvfsDebug( "call %s( %p )", __func__, memfile ); 168 | 169 | memfile->mem->used = SPMEMVFS_MIN( memfile->mem->used, size ); 170 | 171 | return SQLITE_OK; 172 | } 173 | 174 | int spmemfileSync( sqlite3_file * file, int flags ) 175 | { 176 | spmemvfsDebug( "call %s( %p )", __func__, file ); 177 | 178 | return SQLITE_OK; 179 | } 180 | 181 | int spmemfileFileSize( sqlite3_file * file, sqlite3_int64 * size ) 182 | { 183 | spmemfile_t * memfile = (spmemfile_t*)file; 184 | 185 | spmemvfsDebug( "call %s( %p )", __func__, memfile ); 186 | 187 | * size = memfile->mem->used; 188 | 189 | return SQLITE_OK; 190 | } 191 | 192 | int spmemfileLock( sqlite3_file * file, int type ) 193 | { 194 | spmemvfsDebug( "call %s( %p )", __func__, file ); 195 | 196 | return SQLITE_OK; 197 | } 198 | 199 | int spmemfileUnlock( sqlite3_file * file, int type ) 200 | { 201 | spmemvfsDebug( "call %s( %p )", __func__, file ); 202 | 203 | return SQLITE_OK; 204 | } 205 | 206 | int spmemfileCheckReservedLock( sqlite3_file * file, int * result ) 207 | { 208 | spmemvfsDebug( "call %s( %p )", __func__, file ); 209 | 210 | *result = 0; 211 | 212 | return SQLITE_OK; 213 | } 214 | 215 | int spmemfileFileControl( sqlite3_file * file, int op, void * arg ) 216 | { 217 | spmemvfsDebug( "call %s( %p )", __func__, file ); 218 | 219 | return SQLITE_OK; 220 | } 221 | 222 | int spmemfileSectorSize( sqlite3_file * file ) 223 | { 224 | spmemvfsDebug( "call %s( %p )", __func__, file ); 225 | 226 | return 0; 227 | } 228 | 229 | int spmemfileDeviceCharacteristics( sqlite3_file * file ) 230 | { 231 | spmemvfsDebug( "call %s( %p )", __func__, file ); 232 | 233 | return 0; 234 | } 235 | 236 | //=========================================================================== 237 | 238 | typedef struct spmemvfs_cb_t { 239 | void * arg; 240 | spmembuffer_t * ( * load ) ( void * args, const char * path ); 241 | } spmemvfs_cb_t; 242 | 243 | typedef struct spmemvfs_t { 244 | sqlite3_vfs base; 245 | spmemvfs_cb_t cb; 246 | sqlite3_vfs * parent; 247 | } spmemvfs_t; 248 | 249 | static int spmemvfsOpen( sqlite3_vfs * vfs, const char * path, sqlite3_file * file, int flags, int * outflags ); 250 | static int spmemvfsDelete( sqlite3_vfs * vfs, const char * path, int syncDir ); 251 | static int spmemvfsAccess( sqlite3_vfs * vfs, const char * path, int flags, int * result ); 252 | static int spmemvfsFullPathname( sqlite3_vfs * vfs, const char * path, int len, char * fullpath ); 253 | static void * spmemvfsDlOpen( sqlite3_vfs * vfs, const char * path ); 254 | static void spmemvfsDlError( sqlite3_vfs * vfs, int len, char * errmsg ); 255 | static void ( * spmemvfsDlSym ( sqlite3_vfs * vfs, void * handle, const char * symbol ) ) ( void ); 256 | static void spmemvfsDlClose( sqlite3_vfs * vfs, void * handle ); 257 | static int spmemvfsRandomness( sqlite3_vfs * vfs, int len, char * buffer ); 258 | static int spmemvfsSleep( sqlite3_vfs * vfs, int microseconds ); 259 | static int spmemvfsCurrentTime( sqlite3_vfs * vfs, double * result ); 260 | 261 | static spmemvfs_t g_spmemvfs = { 262 | { 263 | 1, /* iVersion */ 264 | 0, /* szOsFile */ 265 | 0, /* mxPathname */ 266 | 0, /* pNext */ 267 | SPMEMVFS_NAME, /* zName */ 268 | 0, /* pAppData */ 269 | spmemvfsOpen, /* xOpen */ 270 | spmemvfsDelete, /* xDelete */ 271 | spmemvfsAccess, /* xAccess */ 272 | spmemvfsFullPathname, /* xFullPathname */ 273 | spmemvfsDlOpen, /* xDlOpen */ 274 | spmemvfsDlError, /* xDlError */ 275 | spmemvfsDlSym, /* xDlSym */ 276 | spmemvfsDlClose, /* xDlClose */ 277 | spmemvfsRandomness, /* xRandomness */ 278 | spmemvfsSleep, /* xSleep */ 279 | spmemvfsCurrentTime /* xCurrentTime */ 280 | }, 281 | { 0 }, 282 | 0 /* pParent */ 283 | }; 284 | 285 | int spmemvfsOpen( sqlite3_vfs * vfs, const char * path, sqlite3_file * file, int flags, int * outflags ) 286 | { 287 | spmemvfs_t * memvfs = (spmemvfs_t*)vfs; 288 | spmemfile_t * memfile = (spmemfile_t*)file; 289 | 290 | spmemvfsDebug( "call %s( %p(%p), %s, %p, %x, %p )\n", 291 | __func__, vfs, &g_spmemvfs, path, file, flags, outflags ); 292 | 293 | memset( memfile, 0, sizeof( spmemfile_t ) ); 294 | memfile->base.pMethods = &g_spmemfile_io_memthods; 295 | memfile->flags = flags; 296 | 297 | memfile->path = strdup( path ); 298 | 299 | if( SQLITE_OPEN_MAIN_DB & memfile->flags ) { 300 | memfile->mem = memvfs->cb.load( memvfs->cb.arg, path ); 301 | } else { 302 | memfile->mem = (spmembuffer_t*)calloc( sizeof( spmembuffer_t ), 1 ); 303 | } 304 | 305 | return memfile->mem ? SQLITE_OK : SQLITE_ERROR; 306 | } 307 | 308 | int spmemvfsDelete( sqlite3_vfs * vfs, const char * path, int syncDir ) 309 | { 310 | spmemvfsDebug( "call %s( %p(%p), %s, %d )\n", 311 | __func__, vfs, &g_spmemvfs, path, syncDir ); 312 | 313 | return SQLITE_OK; 314 | } 315 | 316 | int spmemvfsAccess( sqlite3_vfs * vfs, const char * path, int flags, int * result ) 317 | { 318 | * result = 0; 319 | return SQLITE_OK; 320 | } 321 | 322 | int spmemvfsFullPathname( sqlite3_vfs * vfs, const char * path, int len, char * fullpath ) 323 | { 324 | strncpy( fullpath, path, len ); 325 | fullpath[ len - 1 ] = '\0'; 326 | 327 | return SQLITE_OK; 328 | } 329 | 330 | void * spmemvfsDlOpen( sqlite3_vfs * vfs, const char * path ) 331 | { 332 | return NULL; 333 | } 334 | 335 | void spmemvfsDlError( sqlite3_vfs * vfs, int len, char * errmsg ) 336 | { 337 | // noop 338 | } 339 | 340 | void ( * spmemvfsDlSym ( sqlite3_vfs * vfs, void * handle, const char * symbol ) ) ( void ) 341 | { 342 | return NULL; 343 | } 344 | 345 | void spmemvfsDlClose( sqlite3_vfs * vfs, void * handle ) 346 | { 347 | // noop 348 | } 349 | 350 | int spmemvfsRandomness( sqlite3_vfs * vfs, int len, char * buffer ) 351 | { 352 | return SQLITE_OK; 353 | } 354 | 355 | int spmemvfsSleep( sqlite3_vfs * vfs, int microseconds ) 356 | { 357 | return SQLITE_OK; 358 | } 359 | 360 | int spmemvfsCurrentTime( sqlite3_vfs * vfs, double * result ) 361 | { 362 | return SQLITE_OK; 363 | } 364 | 365 | //=========================================================================== 366 | 367 | int spmemvfs_init( spmemvfs_cb_t * cb ) 368 | { 369 | sqlite3_vfs * parent = NULL; 370 | 371 | if( g_spmemvfs.parent ) return SQLITE_OK; 372 | 373 | parent = sqlite3_vfs_find( 0 ); 374 | 375 | g_spmemvfs.parent = parent; 376 | 377 | g_spmemvfs.base.mxPathname = parent->mxPathname; 378 | g_spmemvfs.base.szOsFile = sizeof( spmemfile_t ); 379 | 380 | g_spmemvfs.cb = * cb; 381 | 382 | return sqlite3_vfs_register( (sqlite3_vfs*)&g_spmemvfs, 0 ); 383 | } 384 | 385 | //=========================================================================== 386 | 387 | typedef struct spmembuffer_link_t { 388 | char * path; 389 | spmembuffer_t * mem; 390 | struct spmembuffer_link_t * next; 391 | } spmembuffer_link_t; 392 | 393 | spmembuffer_link_t * spmembuffer_link_remove( spmembuffer_link_t ** head, const char * path ) 394 | { 395 | spmembuffer_link_t * ret = NULL; 396 | 397 | spmembuffer_link_t ** iter = head; 398 | for( ; NULL != *iter; ) { 399 | spmembuffer_link_t * curr = *iter; 400 | 401 | if( 0 == strcmp( path, curr->path ) ) { 402 | ret = curr; 403 | *iter = curr->next; 404 | break; 405 | } else { 406 | iter = &( curr->next ); 407 | } 408 | } 409 | 410 | return ret; 411 | } 412 | 413 | void spmembuffer_link_free( spmembuffer_link_t * iter ) 414 | { 415 | free( iter->path ); 416 | free( iter->mem->data ); 417 | free( iter->mem ); 418 | free( iter ); 419 | } 420 | 421 | //=========================================================================== 422 | 423 | typedef struct spmemvfs_env_t { 424 | spmembuffer_link_t * head; 425 | sqlite3_mutex * mutex; 426 | } spmemvfs_env_t; 427 | 428 | static spmemvfs_env_t * g_spmemvfs_env = NULL; 429 | 430 | static spmembuffer_t * load_cb( void * arg, const char * path ) 431 | { 432 | spmembuffer_t * ret = NULL; 433 | 434 | spmemvfs_env_t * env = (spmemvfs_env_t*)arg; 435 | 436 | sqlite3_mutex_enter( env->mutex ); 437 | { 438 | spmembuffer_link_t * toFind = spmembuffer_link_remove( &( env->head ), path ); 439 | 440 | if( NULL != toFind ) { 441 | ret = toFind->mem; 442 | free( toFind->path ); 443 | free( toFind ); 444 | } 445 | } 446 | sqlite3_mutex_leave( env->mutex ); 447 | 448 | return ret; 449 | } 450 | 451 | int spmemvfs_env_init() 452 | { 453 | int ret = 0; 454 | 455 | if( NULL == g_spmemvfs_env ) { 456 | spmemvfs_cb_t cb; 457 | 458 | g_spmemvfs_env = (spmemvfs_env_t*)calloc( sizeof( spmemvfs_env_t ), 1 ); 459 | g_spmemvfs_env->mutex = sqlite3_mutex_alloc( SQLITE_MUTEX_FAST ); 460 | 461 | cb.arg = g_spmemvfs_env; 462 | cb.load = load_cb; 463 | 464 | ret = spmemvfs_init( &cb ); 465 | } 466 | 467 | return ret; 468 | } 469 | 470 | void spmemvfs_env_fini() 471 | { 472 | if( NULL != g_spmemvfs_env ) { 473 | spmembuffer_link_t * iter = NULL; 474 | 475 | sqlite3_vfs_unregister( (sqlite3_vfs*)&g_spmemvfs ); 476 | g_spmemvfs.parent = NULL; 477 | 478 | sqlite3_mutex_free( g_spmemvfs_env->mutex ); 479 | 480 | iter = g_spmemvfs_env->head; 481 | for( ; NULL != iter; ) { 482 | spmembuffer_link_t * next = iter->next; 483 | 484 | spmembuffer_link_free( iter ); 485 | 486 | iter = next; 487 | } 488 | 489 | free( g_spmemvfs_env ); 490 | g_spmemvfs_env = NULL; 491 | } 492 | } 493 | 494 | int spmemvfs_open_db( spmemvfs_db_t * db, const char * path, spmembuffer_t * mem ) 495 | { 496 | int ret = 0; 497 | 498 | spmembuffer_link_t * iter = NULL; 499 | 500 | memset( db, 0, sizeof( spmemvfs_db_t ) ); 501 | 502 | iter = (spmembuffer_link_t*)calloc( sizeof( spmembuffer_link_t ), 1 ); 503 | iter->path = strdup( path ); 504 | iter->mem = mem; 505 | 506 | sqlite3_mutex_enter( g_spmemvfs_env->mutex ); 507 | { 508 | iter->next = g_spmemvfs_env->head; 509 | g_spmemvfs_env->head = iter; 510 | } 511 | sqlite3_mutex_leave( g_spmemvfs_env->mutex ); 512 | 513 | ret = sqlite3_open_v2( path, &(db->handle), 514 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, SPMEMVFS_NAME ); 515 | 516 | if( 0 == ret ) { 517 | db->mem = mem; 518 | } else { 519 | sqlite3_mutex_enter( g_spmemvfs_env->mutex ); 520 | { 521 | iter = spmembuffer_link_remove( &(g_spmemvfs_env->head), path ); 522 | if( NULL != iter ) spmembuffer_link_free( iter ); 523 | } 524 | sqlite3_mutex_leave( g_spmemvfs_env->mutex ); 525 | } 526 | 527 | return ret; 528 | } 529 | 530 | int spmemvfs_close_db( spmemvfs_db_t * db ) 531 | { 532 | int ret = 0; 533 | 534 | if( NULL == db ) return 0; 535 | 536 | if( NULL != db->handle ) { 537 | ret = sqlite3_close( db->handle ); 538 | db->handle = NULL; 539 | } 540 | 541 | if( NULL != db->mem ) { 542 | if( NULL != db->mem->data ) free( db->mem->data ); 543 | free( db->mem ); 544 | db->mem = NULL; 545 | } 546 | 547 | return ret; 548 | } 549 | 550 | -------------------------------------------------------------------------------- /thirdparty/sqlite/spmemvfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 2-Clause License 3 | * 4 | * Copyright 2009 Stephen Liu 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef __spmemvfs_h__ 30 | #define __spmemvfs_h__ 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #include 37 | #include "sqlite3.h" 38 | 39 | #define SPMEMVFS_NAME "spmemvfs" 40 | 41 | typedef struct spmembuffer_t { 42 | char *data; 43 | int64_t used; 44 | int64_t total; 45 | } spmembuffer_t; 46 | 47 | typedef struct spmemvfs_db_t { 48 | sqlite3 * handle; 49 | spmembuffer_t * mem; 50 | } spmemvfs_db_t; 51 | 52 | int spmemvfs_env_init(); 53 | 54 | void spmemvfs_env_fini(); 55 | 56 | int spmemvfs_open_db( spmemvfs_db_t * db, const char * path, spmembuffer_t * mem ); 57 | 58 | int spmemvfs_close_db( spmemvfs_db_t * db ); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /thirdparty/sqlite/sqlite3ext.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2006 June 7 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This header file defines the SQLite interface for use by 13 | ** shared libraries that want to be imported as extensions into 14 | ** an SQLite instance. Shared libraries that intend to be loaded 15 | ** as extensions by SQLite should #include this file instead of 16 | ** sqlite3.h. 17 | */ 18 | #ifndef SQLITE3EXT_H 19 | #define SQLITE3EXT_H 20 | #include "sqlite3.h" 21 | 22 | /* 23 | ** The following structure holds pointers to all of the SQLite API 24 | ** routines. 25 | ** 26 | ** WARNING: In order to maintain backwards compatibility, add new 27 | ** interfaces to the end of this structure only. If you insert new 28 | ** interfaces in the middle of this structure, then older different 29 | ** versions of SQLite will not be able to load each other's shared 30 | ** libraries! 31 | */ 32 | struct sqlite3_api_routines { 33 | void * (*aggregate_context)(sqlite3_context*,int nBytes); 34 | int (*aggregate_count)(sqlite3_context*); 35 | int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); 36 | int (*bind_double)(sqlite3_stmt*,int,double); 37 | int (*bind_int)(sqlite3_stmt*,int,int); 38 | int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); 39 | int (*bind_null)(sqlite3_stmt*,int); 40 | int (*bind_parameter_count)(sqlite3_stmt*); 41 | int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); 42 | const char * (*bind_parameter_name)(sqlite3_stmt*,int); 43 | int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); 44 | int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); 45 | int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); 46 | int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); 47 | int (*busy_timeout)(sqlite3*,int ms); 48 | int (*changes)(sqlite3*); 49 | int (*close)(sqlite3*); 50 | int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, 51 | int eTextRep,const char*)); 52 | int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, 53 | int eTextRep,const void*)); 54 | const void * (*column_blob)(sqlite3_stmt*,int iCol); 55 | int (*column_bytes)(sqlite3_stmt*,int iCol); 56 | int (*column_bytes16)(sqlite3_stmt*,int iCol); 57 | int (*column_count)(sqlite3_stmt*pStmt); 58 | const char * (*column_database_name)(sqlite3_stmt*,int); 59 | const void * (*column_database_name16)(sqlite3_stmt*,int); 60 | const char * (*column_decltype)(sqlite3_stmt*,int i); 61 | const void * (*column_decltype16)(sqlite3_stmt*,int); 62 | double (*column_double)(sqlite3_stmt*,int iCol); 63 | int (*column_int)(sqlite3_stmt*,int iCol); 64 | sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); 65 | const char * (*column_name)(sqlite3_stmt*,int); 66 | const void * (*column_name16)(sqlite3_stmt*,int); 67 | const char * (*column_origin_name)(sqlite3_stmt*,int); 68 | const void * (*column_origin_name16)(sqlite3_stmt*,int); 69 | const char * (*column_table_name)(sqlite3_stmt*,int); 70 | const void * (*column_table_name16)(sqlite3_stmt*,int); 71 | const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); 72 | const void * (*column_text16)(sqlite3_stmt*,int iCol); 73 | int (*column_type)(sqlite3_stmt*,int iCol); 74 | sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); 75 | void * (*commit_hook)(sqlite3*,int(*)(void*),void*); 76 | int (*complete)(const char*sql); 77 | int (*complete16)(const void*sql); 78 | int (*create_collation)(sqlite3*,const char*,int,void*, 79 | int(*)(void*,int,const void*,int,const void*)); 80 | int (*create_collation16)(sqlite3*,const void*,int,void*, 81 | int(*)(void*,int,const void*,int,const void*)); 82 | int (*create_function)(sqlite3*,const char*,int,int,void*, 83 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 84 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 85 | void (*xFinal)(sqlite3_context*)); 86 | int (*create_function16)(sqlite3*,const void*,int,int,void*, 87 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 88 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 89 | void (*xFinal)(sqlite3_context*)); 90 | int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); 91 | int (*data_count)(sqlite3_stmt*pStmt); 92 | sqlite3 * (*db_handle)(sqlite3_stmt*); 93 | int (*declare_vtab)(sqlite3*,const char*); 94 | int (*enable_shared_cache)(int); 95 | int (*errcode)(sqlite3*db); 96 | const char * (*errmsg)(sqlite3*); 97 | const void * (*errmsg16)(sqlite3*); 98 | int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); 99 | int (*expired)(sqlite3_stmt*); 100 | int (*finalize)(sqlite3_stmt*pStmt); 101 | void (*free)(void*); 102 | void (*free_table)(char**result); 103 | int (*get_autocommit)(sqlite3*); 104 | void * (*get_auxdata)(sqlite3_context*,int); 105 | int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); 106 | int (*global_recover)(void); 107 | void (*interruptx)(sqlite3*); 108 | sqlite_int64 (*last_insert_rowid)(sqlite3*); 109 | const char * (*libversion)(void); 110 | int (*libversion_number)(void); 111 | void *(*malloc)(int); 112 | char * (*mprintf)(const char*,...); 113 | int (*open)(const char*,sqlite3**); 114 | int (*open16)(const void*,sqlite3**); 115 | int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); 116 | int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); 117 | void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); 118 | void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); 119 | void *(*realloc)(void*,int); 120 | int (*reset)(sqlite3_stmt*pStmt); 121 | void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); 122 | void (*result_double)(sqlite3_context*,double); 123 | void (*result_error)(sqlite3_context*,const char*,int); 124 | void (*result_error16)(sqlite3_context*,const void*,int); 125 | void (*result_int)(sqlite3_context*,int); 126 | void (*result_int64)(sqlite3_context*,sqlite_int64); 127 | void (*result_null)(sqlite3_context*); 128 | void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); 129 | void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); 130 | void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); 131 | void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); 132 | void (*result_value)(sqlite3_context*,sqlite3_value*); 133 | void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); 134 | int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, 135 | const char*,const char*),void*); 136 | void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); 137 | char * (*xsnprintf)(int,char*,const char*,...); 138 | int (*step)(sqlite3_stmt*); 139 | int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, 140 | char const**,char const**,int*,int*,int*); 141 | void (*thread_cleanup)(void); 142 | int (*total_changes)(sqlite3*); 143 | void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); 144 | int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); 145 | void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, 146 | sqlite_int64),void*); 147 | void * (*user_data)(sqlite3_context*); 148 | const void * (*value_blob)(sqlite3_value*); 149 | int (*value_bytes)(sqlite3_value*); 150 | int (*value_bytes16)(sqlite3_value*); 151 | double (*value_double)(sqlite3_value*); 152 | int (*value_int)(sqlite3_value*); 153 | sqlite_int64 (*value_int64)(sqlite3_value*); 154 | int (*value_numeric_type)(sqlite3_value*); 155 | const unsigned char * (*value_text)(sqlite3_value*); 156 | const void * (*value_text16)(sqlite3_value*); 157 | const void * (*value_text16be)(sqlite3_value*); 158 | const void * (*value_text16le)(sqlite3_value*); 159 | int (*value_type)(sqlite3_value*); 160 | char *(*vmprintf)(const char*,va_list); 161 | /* Added ??? */ 162 | int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); 163 | /* Added by 3.3.13 */ 164 | int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); 165 | int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); 166 | int (*clear_bindings)(sqlite3_stmt*); 167 | /* Added by 3.4.1 */ 168 | int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, 169 | void (*xDestroy)(void *)); 170 | /* Added by 3.5.0 */ 171 | int (*bind_zeroblob)(sqlite3_stmt*,int,int); 172 | int (*blob_bytes)(sqlite3_blob*); 173 | int (*blob_close)(sqlite3_blob*); 174 | int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, 175 | int,sqlite3_blob**); 176 | int (*blob_read)(sqlite3_blob*,void*,int,int); 177 | int (*blob_write)(sqlite3_blob*,const void*,int,int); 178 | int (*create_collation_v2)(sqlite3*,const char*,int,void*, 179 | int(*)(void*,int,const void*,int,const void*), 180 | void(*)(void*)); 181 | int (*file_control)(sqlite3*,const char*,int,void*); 182 | sqlite3_int64 (*memory_highwater)(int); 183 | sqlite3_int64 (*memory_used)(void); 184 | sqlite3_mutex *(*mutex_alloc)(int); 185 | void (*mutex_enter)(sqlite3_mutex*); 186 | void (*mutex_free)(sqlite3_mutex*); 187 | void (*mutex_leave)(sqlite3_mutex*); 188 | int (*mutex_try)(sqlite3_mutex*); 189 | int (*open_v2)(const char*,sqlite3**,int,const char*); 190 | int (*release_memory)(int); 191 | void (*result_error_nomem)(sqlite3_context*); 192 | void (*result_error_toobig)(sqlite3_context*); 193 | int (*sleep)(int); 194 | void (*soft_heap_limit)(int); 195 | sqlite3_vfs *(*vfs_find)(const char*); 196 | int (*vfs_register)(sqlite3_vfs*,int); 197 | int (*vfs_unregister)(sqlite3_vfs*); 198 | int (*xthreadsafe)(void); 199 | void (*result_zeroblob)(sqlite3_context*,int); 200 | void (*result_error_code)(sqlite3_context*,int); 201 | int (*test_control)(int, ...); 202 | void (*randomness)(int,void*); 203 | sqlite3 *(*context_db_handle)(sqlite3_context*); 204 | int (*extended_result_codes)(sqlite3*,int); 205 | int (*limit)(sqlite3*,int,int); 206 | sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); 207 | const char *(*sql)(sqlite3_stmt*); 208 | int (*status)(int,int*,int*,int); 209 | int (*backup_finish)(sqlite3_backup*); 210 | sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); 211 | int (*backup_pagecount)(sqlite3_backup*); 212 | int (*backup_remaining)(sqlite3_backup*); 213 | int (*backup_step)(sqlite3_backup*,int); 214 | const char *(*compileoption_get)(int); 215 | int (*compileoption_used)(const char*); 216 | int (*create_function_v2)(sqlite3*,const char*,int,int,void*, 217 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 218 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 219 | void (*xFinal)(sqlite3_context*), 220 | void(*xDestroy)(void*)); 221 | int (*db_config)(sqlite3*,int,...); 222 | sqlite3_mutex *(*db_mutex)(sqlite3*); 223 | int (*db_status)(sqlite3*,int,int*,int*,int); 224 | int (*extended_errcode)(sqlite3*); 225 | void (*log)(int,const char*,...); 226 | sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); 227 | const char *(*sourceid)(void); 228 | int (*stmt_status)(sqlite3_stmt*,int,int); 229 | int (*strnicmp)(const char*,const char*,int); 230 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); 231 | int (*wal_autocheckpoint)(sqlite3*,int); 232 | int (*wal_checkpoint)(sqlite3*,const char*); 233 | void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); 234 | int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); 235 | int (*vtab_config)(sqlite3*,int op,...); 236 | int (*vtab_on_conflict)(sqlite3*); 237 | /* Version 3.7.16 and later */ 238 | int (*close_v2)(sqlite3*); 239 | const char *(*db_filename)(sqlite3*,const char*); 240 | int (*db_readonly)(sqlite3*,const char*); 241 | int (*db_release_memory)(sqlite3*); 242 | const char *(*errstr)(int); 243 | int (*stmt_busy)(sqlite3_stmt*); 244 | int (*stmt_readonly)(sqlite3_stmt*); 245 | int (*stricmp)(const char*,const char*); 246 | int (*uri_boolean)(const char*,const char*,int); 247 | sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); 248 | const char *(*uri_parameter)(const char*,const char*); 249 | char *(*xvsnprintf)(int,char*,const char*,va_list); 250 | int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); 251 | /* Version 3.8.7 and later */ 252 | int (*auto_extension)(void(*)(void)); 253 | int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, 254 | void(*)(void*)); 255 | int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, 256 | void(*)(void*),unsigned char); 257 | int (*cancel_auto_extension)(void(*)(void)); 258 | int (*load_extension)(sqlite3*,const char*,const char*,char**); 259 | void *(*malloc64)(sqlite3_uint64); 260 | sqlite3_uint64 (*msize)(void*); 261 | void *(*realloc64)(void*,sqlite3_uint64); 262 | void (*reset_auto_extension)(void); 263 | void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, 264 | void(*)(void*)); 265 | void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, 266 | void(*)(void*), unsigned char); 267 | int (*strglob)(const char*,const char*); 268 | /* Version 3.8.11 and later */ 269 | sqlite3_value *(*value_dup)(const sqlite3_value*); 270 | void (*value_free)(sqlite3_value*); 271 | int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); 272 | int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); 273 | /* Version 3.9.0 and later */ 274 | unsigned int (*value_subtype)(sqlite3_value*); 275 | void (*result_subtype)(sqlite3_context*,unsigned int); 276 | /* Version 3.10.0 and later */ 277 | int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); 278 | int (*strlike)(const char*,const char*,unsigned int); 279 | int (*db_cacheflush)(sqlite3*); 280 | /* Version 3.12.0 and later */ 281 | int (*system_errno)(sqlite3*); 282 | /* Version 3.14.0 and later */ 283 | int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); 284 | char *(*expanded_sql)(sqlite3_stmt*); 285 | /* Version 3.18.0 and later */ 286 | void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); 287 | /* Version 3.20.0 and later */ 288 | int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, 289 | sqlite3_stmt**,const char**); 290 | int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, 291 | sqlite3_stmt**,const void**); 292 | int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); 293 | void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); 294 | void *(*value_pointer)(sqlite3_value*,const char*); 295 | int (*vtab_nochange)(sqlite3_context*); 296 | int (*value_nochange)(sqlite3_value*); 297 | const char *(*vtab_collation)(sqlite3_index_info*,int); 298 | /* Version 3.24.0 and later */ 299 | int (*keyword_count)(void); 300 | int (*keyword_name)(int,const char**,int*); 301 | int (*keyword_check)(const char*,int); 302 | sqlite3_str *(*str_new)(sqlite3*); 303 | char *(*str_finish)(sqlite3_str*); 304 | void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); 305 | void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); 306 | void (*str_append)(sqlite3_str*, const char *zIn, int N); 307 | void (*str_appendall)(sqlite3_str*, const char *zIn); 308 | void (*str_appendchar)(sqlite3_str*, int N, char C); 309 | void (*str_reset)(sqlite3_str*); 310 | int (*str_errcode)(sqlite3_str*); 311 | int (*str_length)(sqlite3_str*); 312 | char *(*str_value)(sqlite3_str*); 313 | /* Version 3.25.0 and later */ 314 | int (*create_window_function)(sqlite3*,const char*,int,int,void*, 315 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 316 | void (*xFinal)(sqlite3_context*), 317 | void (*xValue)(sqlite3_context*), 318 | void (*xInv)(sqlite3_context*,int,sqlite3_value**), 319 | void(*xDestroy)(void*)); 320 | /* Version 3.26.0 and later */ 321 | const char *(*normalized_sql)(sqlite3_stmt*); 322 | /* Version 3.28.0 and later */ 323 | int (*stmt_isexplain)(sqlite3_stmt*); 324 | int (*value_frombind)(sqlite3_value*); 325 | /* Version 3.30.0 and later */ 326 | int (*drop_modules)(sqlite3*,const char**); 327 | /* Version 3.31.0 and later */ 328 | sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64); 329 | const char *(*uri_key)(const char*,int); 330 | const char *(*filename_database)(const char*); 331 | const char *(*filename_journal)(const char*); 332 | const char *(*filename_wal)(const char*); 333 | /* Version 3.32.0 and later */ 334 | char *(*create_filename)(const char*,const char*,const char*, 335 | int,const char**); 336 | void (*free_filename)(char*); 337 | sqlite3_file *(*database_file_object)(const char*); 338 | /* Version 3.34.0 and later */ 339 | int (*txn_state)(sqlite3*,const char*); 340 | /* Version 3.36.1 and later */ 341 | sqlite3_int64 (*changes64)(sqlite3*); 342 | sqlite3_int64 (*total_changes64)(sqlite3*); 343 | /* Version 3.37.0 and later */ 344 | int (*autovacuum_pages)(sqlite3*, 345 | unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), 346 | void*, void(*)(void*)); 347 | }; 348 | 349 | /* 350 | ** This is the function signature used for all extension entry points. It 351 | ** is also defined in the file "loadext.c". 352 | */ 353 | typedef int (*sqlite3_loadext_entry)( 354 | sqlite3 *db, /* Handle to the database. */ 355 | char **pzErrMsg, /* Used to set error string on failure. */ 356 | const sqlite3_api_routines *pThunk /* Extension API function pointers. */ 357 | ); 358 | 359 | /* 360 | ** The following macros redefine the API routines so that they are 361 | ** redirected through the global sqlite3_api structure. 362 | ** 363 | ** This header file is also used by the loadext.c source file 364 | ** (part of the main SQLite library - not an extension) so that 365 | ** it can get access to the sqlite3_api_routines structure 366 | ** definition. But the main library does not want to redefine 367 | ** the API. So the redefinition macros are only valid if the 368 | ** SQLITE_CORE macros is undefined. 369 | */ 370 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) 371 | #define sqlite3_aggregate_context sqlite3_api->aggregate_context 372 | #ifndef SQLITE_OMIT_DEPRECATED 373 | #define sqlite3_aggregate_count sqlite3_api->aggregate_count 374 | #endif 375 | #define sqlite3_bind_blob sqlite3_api->bind_blob 376 | #define sqlite3_bind_double sqlite3_api->bind_double 377 | #define sqlite3_bind_int sqlite3_api->bind_int 378 | #define sqlite3_bind_int64 sqlite3_api->bind_int64 379 | #define sqlite3_bind_null sqlite3_api->bind_null 380 | #define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count 381 | #define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index 382 | #define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name 383 | #define sqlite3_bind_text sqlite3_api->bind_text 384 | #define sqlite3_bind_text16 sqlite3_api->bind_text16 385 | #define sqlite3_bind_value sqlite3_api->bind_value 386 | #define sqlite3_busy_handler sqlite3_api->busy_handler 387 | #define sqlite3_busy_timeout sqlite3_api->busy_timeout 388 | #define sqlite3_changes sqlite3_api->changes 389 | #define sqlite3_close sqlite3_api->close 390 | #define sqlite3_collation_needed sqlite3_api->collation_needed 391 | #define sqlite3_collation_needed16 sqlite3_api->collation_needed16 392 | #define sqlite3_column_blob sqlite3_api->column_blob 393 | #define sqlite3_column_bytes sqlite3_api->column_bytes 394 | #define sqlite3_column_bytes16 sqlite3_api->column_bytes16 395 | #define sqlite3_column_count sqlite3_api->column_count 396 | #define sqlite3_column_database_name sqlite3_api->column_database_name 397 | #define sqlite3_column_database_name16 sqlite3_api->column_database_name16 398 | #define sqlite3_column_decltype sqlite3_api->column_decltype 399 | #define sqlite3_column_decltype16 sqlite3_api->column_decltype16 400 | #define sqlite3_column_double sqlite3_api->column_double 401 | #define sqlite3_column_int sqlite3_api->column_int 402 | #define sqlite3_column_int64 sqlite3_api->column_int64 403 | #define sqlite3_column_name sqlite3_api->column_name 404 | #define sqlite3_column_name16 sqlite3_api->column_name16 405 | #define sqlite3_column_origin_name sqlite3_api->column_origin_name 406 | #define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 407 | #define sqlite3_column_table_name sqlite3_api->column_table_name 408 | #define sqlite3_column_table_name16 sqlite3_api->column_table_name16 409 | #define sqlite3_column_text sqlite3_api->column_text 410 | #define sqlite3_column_text16 sqlite3_api->column_text16 411 | #define sqlite3_column_type sqlite3_api->column_type 412 | #define sqlite3_column_value sqlite3_api->column_value 413 | #define sqlite3_commit_hook sqlite3_api->commit_hook 414 | #define sqlite3_complete sqlite3_api->complete 415 | #define sqlite3_complete16 sqlite3_api->complete16 416 | #define sqlite3_create_collation sqlite3_api->create_collation 417 | #define sqlite3_create_collation16 sqlite3_api->create_collation16 418 | #define sqlite3_create_function sqlite3_api->create_function 419 | #define sqlite3_create_function16 sqlite3_api->create_function16 420 | #define sqlite3_create_module sqlite3_api->create_module 421 | #define sqlite3_create_module_v2 sqlite3_api->create_module_v2 422 | #define sqlite3_data_count sqlite3_api->data_count 423 | #define sqlite3_db_handle sqlite3_api->db_handle 424 | #define sqlite3_declare_vtab sqlite3_api->declare_vtab 425 | #define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache 426 | #define sqlite3_errcode sqlite3_api->errcode 427 | #define sqlite3_errmsg sqlite3_api->errmsg 428 | #define sqlite3_errmsg16 sqlite3_api->errmsg16 429 | #define sqlite3_exec sqlite3_api->exec 430 | #ifndef SQLITE_OMIT_DEPRECATED 431 | #define sqlite3_expired sqlite3_api->expired 432 | #endif 433 | #define sqlite3_finalize sqlite3_api->finalize 434 | #define sqlite3_free sqlite3_api->free 435 | #define sqlite3_free_table sqlite3_api->free_table 436 | #define sqlite3_get_autocommit sqlite3_api->get_autocommit 437 | #define sqlite3_get_auxdata sqlite3_api->get_auxdata 438 | #define sqlite3_get_table sqlite3_api->get_table 439 | #ifndef SQLITE_OMIT_DEPRECATED 440 | #define sqlite3_global_recover sqlite3_api->global_recover 441 | #endif 442 | #define sqlite3_interrupt sqlite3_api->interruptx 443 | #define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid 444 | #define sqlite3_libversion sqlite3_api->libversion 445 | #define sqlite3_libversion_number sqlite3_api->libversion_number 446 | #define sqlite3_malloc sqlite3_api->malloc 447 | #define sqlite3_mprintf sqlite3_api->mprintf 448 | #define sqlite3_open sqlite3_api->open 449 | #define sqlite3_open16 sqlite3_api->open16 450 | #define sqlite3_prepare sqlite3_api->prepare 451 | #define sqlite3_prepare16 sqlite3_api->prepare16 452 | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 453 | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 454 | #define sqlite3_profile sqlite3_api->profile 455 | #define sqlite3_progress_handler sqlite3_api->progress_handler 456 | #define sqlite3_realloc sqlite3_api->realloc 457 | #define sqlite3_reset sqlite3_api->reset 458 | #define sqlite3_result_blob sqlite3_api->result_blob 459 | #define sqlite3_result_double sqlite3_api->result_double 460 | #define sqlite3_result_error sqlite3_api->result_error 461 | #define sqlite3_result_error16 sqlite3_api->result_error16 462 | #define sqlite3_result_int sqlite3_api->result_int 463 | #define sqlite3_result_int64 sqlite3_api->result_int64 464 | #define sqlite3_result_null sqlite3_api->result_null 465 | #define sqlite3_result_text sqlite3_api->result_text 466 | #define sqlite3_result_text16 sqlite3_api->result_text16 467 | #define sqlite3_result_text16be sqlite3_api->result_text16be 468 | #define sqlite3_result_text16le sqlite3_api->result_text16le 469 | #define sqlite3_result_value sqlite3_api->result_value 470 | #define sqlite3_rollback_hook sqlite3_api->rollback_hook 471 | #define sqlite3_set_authorizer sqlite3_api->set_authorizer 472 | #define sqlite3_set_auxdata sqlite3_api->set_auxdata 473 | #define sqlite3_snprintf sqlite3_api->xsnprintf 474 | #define sqlite3_step sqlite3_api->step 475 | #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata 476 | #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup 477 | #define sqlite3_total_changes sqlite3_api->total_changes 478 | #define sqlite3_trace sqlite3_api->trace 479 | #ifndef SQLITE_OMIT_DEPRECATED 480 | #define sqlite3_transfer_bindings sqlite3_api->transfer_bindings 481 | #endif 482 | #define sqlite3_update_hook sqlite3_api->update_hook 483 | #define sqlite3_user_data sqlite3_api->user_data 484 | #define sqlite3_value_blob sqlite3_api->value_blob 485 | #define sqlite3_value_bytes sqlite3_api->value_bytes 486 | #define sqlite3_value_bytes16 sqlite3_api->value_bytes16 487 | #define sqlite3_value_double sqlite3_api->value_double 488 | #define sqlite3_value_int sqlite3_api->value_int 489 | #define sqlite3_value_int64 sqlite3_api->value_int64 490 | #define sqlite3_value_numeric_type sqlite3_api->value_numeric_type 491 | #define sqlite3_value_text sqlite3_api->value_text 492 | #define sqlite3_value_text16 sqlite3_api->value_text16 493 | #define sqlite3_value_text16be sqlite3_api->value_text16be 494 | #define sqlite3_value_text16le sqlite3_api->value_text16le 495 | #define sqlite3_value_type sqlite3_api->value_type 496 | #define sqlite3_vmprintf sqlite3_api->vmprintf 497 | #define sqlite3_vsnprintf sqlite3_api->xvsnprintf 498 | #define sqlite3_overload_function sqlite3_api->overload_function 499 | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 500 | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 501 | #define sqlite3_clear_bindings sqlite3_api->clear_bindings 502 | #define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob 503 | #define sqlite3_blob_bytes sqlite3_api->blob_bytes 504 | #define sqlite3_blob_close sqlite3_api->blob_close 505 | #define sqlite3_blob_open sqlite3_api->blob_open 506 | #define sqlite3_blob_read sqlite3_api->blob_read 507 | #define sqlite3_blob_write sqlite3_api->blob_write 508 | #define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 509 | #define sqlite3_file_control sqlite3_api->file_control 510 | #define sqlite3_memory_highwater sqlite3_api->memory_highwater 511 | #define sqlite3_memory_used sqlite3_api->memory_used 512 | #define sqlite3_mutex_alloc sqlite3_api->mutex_alloc 513 | #define sqlite3_mutex_enter sqlite3_api->mutex_enter 514 | #define sqlite3_mutex_free sqlite3_api->mutex_free 515 | #define sqlite3_mutex_leave sqlite3_api->mutex_leave 516 | #define sqlite3_mutex_try sqlite3_api->mutex_try 517 | #define sqlite3_open_v2 sqlite3_api->open_v2 518 | #define sqlite3_release_memory sqlite3_api->release_memory 519 | #define sqlite3_result_error_nomem sqlite3_api->result_error_nomem 520 | #define sqlite3_result_error_toobig sqlite3_api->result_error_toobig 521 | #define sqlite3_sleep sqlite3_api->sleep 522 | #define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit 523 | #define sqlite3_vfs_find sqlite3_api->vfs_find 524 | #define sqlite3_vfs_register sqlite3_api->vfs_register 525 | #define sqlite3_vfs_unregister sqlite3_api->vfs_unregister 526 | #define sqlite3_threadsafe sqlite3_api->xthreadsafe 527 | #define sqlite3_result_zeroblob sqlite3_api->result_zeroblob 528 | #define sqlite3_result_error_code sqlite3_api->result_error_code 529 | #define sqlite3_test_control sqlite3_api->test_control 530 | #define sqlite3_randomness sqlite3_api->randomness 531 | #define sqlite3_context_db_handle sqlite3_api->context_db_handle 532 | #define sqlite3_extended_result_codes sqlite3_api->extended_result_codes 533 | #define sqlite3_limit sqlite3_api->limit 534 | #define sqlite3_next_stmt sqlite3_api->next_stmt 535 | #define sqlite3_sql sqlite3_api->sql 536 | #define sqlite3_status sqlite3_api->status 537 | #define sqlite3_backup_finish sqlite3_api->backup_finish 538 | #define sqlite3_backup_init sqlite3_api->backup_init 539 | #define sqlite3_backup_pagecount sqlite3_api->backup_pagecount 540 | #define sqlite3_backup_remaining sqlite3_api->backup_remaining 541 | #define sqlite3_backup_step sqlite3_api->backup_step 542 | #define sqlite3_compileoption_get sqlite3_api->compileoption_get 543 | #define sqlite3_compileoption_used sqlite3_api->compileoption_used 544 | #define sqlite3_create_function_v2 sqlite3_api->create_function_v2 545 | #define sqlite3_db_config sqlite3_api->db_config 546 | #define sqlite3_db_mutex sqlite3_api->db_mutex 547 | #define sqlite3_db_status sqlite3_api->db_status 548 | #define sqlite3_extended_errcode sqlite3_api->extended_errcode 549 | #define sqlite3_log sqlite3_api->log 550 | #define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 551 | #define sqlite3_sourceid sqlite3_api->sourceid 552 | #define sqlite3_stmt_status sqlite3_api->stmt_status 553 | #define sqlite3_strnicmp sqlite3_api->strnicmp 554 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify 555 | #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint 556 | #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint 557 | #define sqlite3_wal_hook sqlite3_api->wal_hook 558 | #define sqlite3_blob_reopen sqlite3_api->blob_reopen 559 | #define sqlite3_vtab_config sqlite3_api->vtab_config 560 | #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict 561 | /* Version 3.7.16 and later */ 562 | #define sqlite3_close_v2 sqlite3_api->close_v2 563 | #define sqlite3_db_filename sqlite3_api->db_filename 564 | #define sqlite3_db_readonly sqlite3_api->db_readonly 565 | #define sqlite3_db_release_memory sqlite3_api->db_release_memory 566 | #define sqlite3_errstr sqlite3_api->errstr 567 | #define sqlite3_stmt_busy sqlite3_api->stmt_busy 568 | #define sqlite3_stmt_readonly sqlite3_api->stmt_readonly 569 | #define sqlite3_stricmp sqlite3_api->stricmp 570 | #define sqlite3_uri_boolean sqlite3_api->uri_boolean 571 | #define sqlite3_uri_int64 sqlite3_api->uri_int64 572 | #define sqlite3_uri_parameter sqlite3_api->uri_parameter 573 | #define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf 574 | #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 575 | /* Version 3.8.7 and later */ 576 | #define sqlite3_auto_extension sqlite3_api->auto_extension 577 | #define sqlite3_bind_blob64 sqlite3_api->bind_blob64 578 | #define sqlite3_bind_text64 sqlite3_api->bind_text64 579 | #define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension 580 | #define sqlite3_load_extension sqlite3_api->load_extension 581 | #define sqlite3_malloc64 sqlite3_api->malloc64 582 | #define sqlite3_msize sqlite3_api->msize 583 | #define sqlite3_realloc64 sqlite3_api->realloc64 584 | #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension 585 | #define sqlite3_result_blob64 sqlite3_api->result_blob64 586 | #define sqlite3_result_text64 sqlite3_api->result_text64 587 | #define sqlite3_strglob sqlite3_api->strglob 588 | /* Version 3.8.11 and later */ 589 | #define sqlite3_value_dup sqlite3_api->value_dup 590 | #define sqlite3_value_free sqlite3_api->value_free 591 | #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 592 | #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 593 | /* Version 3.9.0 and later */ 594 | #define sqlite3_value_subtype sqlite3_api->value_subtype 595 | #define sqlite3_result_subtype sqlite3_api->result_subtype 596 | /* Version 3.10.0 and later */ 597 | #define sqlite3_status64 sqlite3_api->status64 598 | #define sqlite3_strlike sqlite3_api->strlike 599 | #define sqlite3_db_cacheflush sqlite3_api->db_cacheflush 600 | /* Version 3.12.0 and later */ 601 | #define sqlite3_system_errno sqlite3_api->system_errno 602 | /* Version 3.14.0 and later */ 603 | #define sqlite3_trace_v2 sqlite3_api->trace_v2 604 | #define sqlite3_expanded_sql sqlite3_api->expanded_sql 605 | /* Version 3.18.0 and later */ 606 | #define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid 607 | /* Version 3.20.0 and later */ 608 | #define sqlite3_prepare_v3 sqlite3_api->prepare_v3 609 | #define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3 610 | #define sqlite3_bind_pointer sqlite3_api->bind_pointer 611 | #define sqlite3_result_pointer sqlite3_api->result_pointer 612 | #define sqlite3_value_pointer sqlite3_api->value_pointer 613 | /* Version 3.22.0 and later */ 614 | #define sqlite3_vtab_nochange sqlite3_api->vtab_nochange 615 | #define sqlite3_value_nochange sqlite3_api->value_nochange 616 | #define sqlite3_vtab_collation sqlite3_api->vtab_collation 617 | /* Version 3.24.0 and later */ 618 | #define sqlite3_keyword_count sqlite3_api->keyword_count 619 | #define sqlite3_keyword_name sqlite3_api->keyword_name 620 | #define sqlite3_keyword_check sqlite3_api->keyword_check 621 | #define sqlite3_str_new sqlite3_api->str_new 622 | #define sqlite3_str_finish sqlite3_api->str_finish 623 | #define sqlite3_str_appendf sqlite3_api->str_appendf 624 | #define sqlite3_str_vappendf sqlite3_api->str_vappendf 625 | #define sqlite3_str_append sqlite3_api->str_append 626 | #define sqlite3_str_appendall sqlite3_api->str_appendall 627 | #define sqlite3_str_appendchar sqlite3_api->str_appendchar 628 | #define sqlite3_str_reset sqlite3_api->str_reset 629 | #define sqlite3_str_errcode sqlite3_api->str_errcode 630 | #define sqlite3_str_length sqlite3_api->str_length 631 | #define sqlite3_str_value sqlite3_api->str_value 632 | /* Version 3.25.0 and later */ 633 | #define sqlite3_create_window_function sqlite3_api->create_window_function 634 | /* Version 3.26.0 and later */ 635 | #define sqlite3_normalized_sql sqlite3_api->normalized_sql 636 | /* Version 3.28.0 and later */ 637 | #define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain 638 | #define sqlite3_value_frombind sqlite3_api->value_frombind 639 | /* Version 3.30.0 and later */ 640 | #define sqlite3_drop_modules sqlite3_api->drop_modules 641 | /* Version 3.31.0 and later */ 642 | #define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64 643 | #define sqlite3_uri_key sqlite3_api->uri_key 644 | #define sqlite3_filename_database sqlite3_api->filename_database 645 | #define sqlite3_filename_journal sqlite3_api->filename_journal 646 | #define sqlite3_filename_wal sqlite3_api->filename_wal 647 | /* Version 3.32.0 and later */ 648 | #define sqlite3_create_filename sqlite3_api->create_filename 649 | #define sqlite3_free_filename sqlite3_api->free_filename 650 | #define sqlite3_database_file_object sqlite3_api->database_file_object 651 | /* Version 3.34.0 and later */ 652 | #define sqlite3_txn_state sqlite3_api->txn_state 653 | /* Version 3.36.1 and later */ 654 | #define sqlite3_changes64 sqlite3_api->changes64 655 | #define sqlite3_total_changes64 sqlite3_api->total_changes64 656 | /* Version 3.37.0 and later */ 657 | #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages 658 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ 659 | 660 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) 661 | /* This case when the file really is being compiled as a loadable 662 | ** extension */ 663 | # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; 664 | # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; 665 | # define SQLITE_EXTENSION_INIT3 \ 666 | extern const sqlite3_api_routines *sqlite3_api; 667 | #else 668 | /* This case when the file is being statically linked into the 669 | ** application */ 670 | # define SQLITE_EXTENSION_INIT1 /*no-op*/ 671 | # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ 672 | # define SQLITE_EXTENSION_INIT3 /*no-op*/ 673 | #endif 674 | 675 | #endif /* SQLITE3EXT_H */ 676 | --------------------------------------------------------------------------------