├── .github
├── release.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.LGPL
├── Package.swift
├── README.md
├── Sources
├── SQLExt
│ ├── CMakeLists.txt
│ ├── Skip
│ │ └── skip.yml
│ └── sqlite
│ │ ├── sqlite3.c
│ │ ├── sqlite3.h
│ │ ├── tomcrypt.h
│ │ ├── tomcrypt_argchk.h
│ │ ├── tomcrypt_cfg.h
│ │ ├── tomcrypt_cipher.h
│ │ ├── tomcrypt_custom.h
│ │ ├── tomcrypt_hash.h
│ │ ├── tomcrypt_mac.h
│ │ ├── tomcrypt_macros.h
│ │ ├── tomcrypt_math.h
│ │ ├── tomcrypt_misc.h
│ │ ├── tomcrypt_pk.h
│ │ ├── tomcrypt_pkcs.h
│ │ ├── tomcrypt_private.h
│ │ └── tomcrypt_prng.h
├── SkipSQL
│ ├── SQLContext.swift
│ ├── SQLStatement.swift
│ ├── SQLite.swift
│ ├── SQLiteCLibrary.swift
│ ├── SQLiteJLibrary.swift
│ ├── SQLiteLibrary.swift
│ └── Skip
│ │ └── skip.yml
└── SkipSQLPlus
│ ├── SQLPlus.swift
│ ├── SQLPlusCLibrary.swift
│ ├── SQLPlusJLibrary.swift
│ └── Skip
│ └── skip.yml
└── Tests
├── SkipSQLPlusTests
├── SQLContextTestConfiguration.swift
├── SQLContextTests.swift
├── SQLPlusTests.swift
├── Skip
│ └── skip.yml
└── XCSkipTests.swift
└── SkipSQLTests
├── SQLContextTestConfiguration.swift
├── SQLContextTests.swift
├── Skip
└── skip.yml
└── XCSkipTests.swift
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - ignore-for-release
5 | authors:
6 | - skipbuilder
7 | categories:
8 | - title: Breaking Change
9 | labels:
10 | - Semver-Major
11 | - breaking-change
12 | - title: Enhancement
13 | labels:
14 | - Semver-Minor
15 | - enhancement
16 | - title: Other Changes
17 | labels:
18 | - "*"
19 |
20 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: skip-sql
2 | on:
3 | push:
4 | branches: '*'
5 | tags: "[0-9]+.[0-9]+.[0-9]+"
6 | schedule:
7 | - cron: '0 7,17 * * *'
8 | workflow_dispatch:
9 | pull_request:
10 |
11 | permissions:
12 | contents: write
13 |
14 | jobs:
15 | call-workflow:
16 | uses: skiptools/actions/.github/workflows/skip-framework.yml@v1
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | xcodebuild*.log
9 |
10 | java_pid*.hprof
11 |
12 | .*.swp
13 | .DS_Store
14 |
15 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
16 | *.xcscmblueprint
17 | *.xccheckout
18 |
19 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
20 | build/
21 | DerivedData/
22 | .android/
23 | .kotlin/
24 | *.moved-aside
25 | *.pbxuser
26 | !default.pbxuser
27 | *.mode1v3
28 | !default.mode1v3
29 | *.mode2v3
30 | !default.mode2v3
31 | *.perspectivev3
32 | !default.perspectivev3
33 |
34 | ## Obj-C/Swift specific
35 | *.hmap
36 |
37 | ## App packaging
38 | *.ipa
39 | *.dSYM.zip
40 | *.dSYM
41 |
42 | ## Playgrounds
43 | timeline.xctimeline
44 | playground.xcworkspace
45 |
46 | # Swift Package Manager
47 | #
48 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
49 | Packages/
50 | Package.pins
51 | Package.resolved
52 | *.xcodeproj
53 |
54 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
55 | # hence it is not needed unless you have added a package configuration file to your project
56 | .swiftpm
57 |
58 | .build/
59 |
60 | # CocoaPods
61 | #
62 | # We recommend against adding the Pods directory to your .gitignore. However
63 | # you should judge for yourself, the pros and cons are mentioned at:
64 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
65 | #
66 | # Pods/
67 | #
68 | # Add this line if you want to avoid checking in source code from the Xcode workspace
69 | # *.xcworkspace
70 |
71 | # Carthage
72 | #
73 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
74 | # Carthage/Checkouts
75 |
76 | Carthage/Build/
77 |
78 | # Accio dependency management
79 | Dependencies/
80 | .accio/
81 |
82 | # fastlane
83 | #
84 | # It is recommended to not store the screenshots in the git repo.
85 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
86 | # For more information about the recommended setup visit:
87 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
88 |
89 | fastlane/report.xml
90 | fastlane/Preview.html
91 | fastlane/screenshots/**/*.png
92 | fastlane/test_output
93 |
94 | # Code Injection
95 | #
96 | # After new code Injection tools there's a generated folder /iOSInjectionProject
97 | # https://github.com/johnno1962/injectionforxcode
98 |
99 | iOSInjectionProject/
100 |
101 |
102 |
103 | # Ignore Gradle project-specific cache directory
104 | .gradle
105 |
106 | # Ignore Gradle build output directory
107 | build
108 |
109 | # gradle properties
110 | local.properties
111 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.7.2
2 |
3 | Released 2024-10-16
4 |
5 | - Bump cmake_minimum_required to 3.3 to fix skip export error
6 | - Eliminate redundant import of AndroidJUnit4 test runner
7 | - Fix reference to URL.documentsDirectory in README
8 |
9 | ## 0.7.1
10 |
11 | Released 2024-08-15
12 |
13 |
14 | ## 0.7.0
15 |
16 | Released 2024-08-15
17 |
18 |
19 | ## 0.6.3
20 |
21 | Released 2024-07-08
22 |
23 | - Update search paths for tomcrypt to point to intermediates/merged_native_libs/debug/mergeDebugNativeLibs/out/lib to accommodate change in android gradle plugin 8.5.0
24 | - Update README
25 | - ci: update workflow actions location
26 |
27 | ## 0.6.2
28 |
29 | Released 2024-03-05
30 |
31 | - Link to external skip-ltc module for SQLExt
32 | - Add algorithm tests
33 | - Disable HAVE_GETHOSTUUID since it is disallowed on iOS
34 | - Ignore -Wconversion to reduce warnings
35 |
36 | ## 0.6.1
37 |
38 | Released 2024-03-02
39 |
40 | - Harmonize build options between Android and Darwin
41 | - Add JSON tests
42 | - Add test cases
43 |
44 | ## 0.6.0
45 |
46 | Released 2024-02-28
47 |
48 | - Update error messages and add JSON tests
49 | - Add SQLite JSON test
50 | - Add SQLPlus tests
51 | - Add SQLPlus tests
52 | - Add SQLPlus module that includes custom build of sqlite 3.44.2 with extensions
53 |
54 | ## 0.5.1
55 |
56 | Released 2024-02-20
57 |
58 | - Blob statement parameter binding handling
59 | - Make UpdateHook class final
60 |
61 | ## 0.5.0
62 |
63 | Released 2024-02-05
64 |
65 |
66 | ## 0.4.3
67 |
68 | Released 2023-12-22
69 |
70 |
71 | ## 0.4.2
72 |
73 | Released 2023-12-11
74 |
75 | - Minor comment updates
76 | - Update README.md
77 |
78 | ## 0.4.1
79 |
80 | Released 2023-11-27
81 |
82 | - Dependency bump
83 |
84 | ## 0.4.0
85 |
86 | Released 2023-11-25
87 |
88 | - Use direct mappings to optimize JNA access to C sqlite API
89 | - Refactor into separate implementation files
90 |
91 | ## 0.3.12
92 |
93 | Released 2023-11-25
94 |
95 | - Require statements and connections to be closed
96 |
97 | ## 0.3.11
98 |
99 | Released 2023-11-25
100 |
101 | - Add SQLContext.interrupt()
102 |
103 | ## 0.3.10
104 |
105 | Released 2023-11-25
106 |
107 | - Fix in-memory database creation string
108 |
109 | ## 0.3.9
110 |
111 | Released 2023-11-25
112 |
113 | - Add parameter inspection functions
114 |
115 | ## 0.3.8
116 |
117 | Released 2023-11-24
118 |
119 | - Use SQLITE_TRANSIENT for bound strings and blobs
120 |
121 | ## 0.3.7
122 |
123 | Released 2023-11-21
124 |
125 | - Doc updates
126 | - Docs
127 |
128 | ## 0.3.6
129 |
130 | Released 2023-11-20
131 |
132 |
133 | ## 0.3.5
134 |
135 | Released 2023-11-19
136 |
137 | - Add onUpdate hook and improve API
138 | - Add updateHook
139 |
140 | ## 0.3.4
141 |
142 | Released 2023-11-16
143 |
144 | - Update API
145 |
146 | ## 0.3.3
147 |
148 | Released 2023-11-14
149 |
150 |
151 | ## 0.3.2
152 |
153 | Released 2023-11-14
154 |
155 |
156 | ## 0.3.1
157 |
158 | Released 2023-11-02
159 |
160 | - More API and tests
161 | - Add blob accessor and transaction handling; test cases
162 | - Add SQLType and SQLValue and test cases
163 | - Add row accessor and test case
164 | - SQLStatement.next; SQLConnection.close
165 |
166 | ## 0.3.0
167 |
168 | Released 2023-10-31
169 |
170 | - Import SQLite3 through SkipFFI
171 |
172 | ## 0.2.0
173 |
174 | Released 2023-10-23
175 |
176 |
177 | ## 0.1.8
178 |
179 | Released 2023-09-24
180 |
181 |
182 | ## 0.1.7
183 |
184 | Released 2023-09-11
185 |
186 | - Elide SQLite version check since different emulators have different versions installed
187 |
188 | ## 0.1.6
189 |
190 | Released 2023-09-09
191 |
192 | - Have tests use NSTemporaryDirectory() rather than /tmp/ (which doesn't exist on the Android emulator)
193 |
194 | ## 0.1.5
195 |
196 | Released 2023-09-07
197 |
198 |
199 | ## 0.1.4
200 |
201 | Released 2023-09-07
202 |
203 |
204 | ## 0.1.3
205 |
206 | Released 2023-09-06
207 |
208 | - Modernize package
209 |
210 | ## 0.1.2
211 |
212 | Released 2023-09-04
213 |
214 |
215 | ## 0.1.1
216 |
217 | Released 2023-09-03
218 |
219 |
220 | ## 0.1.0
221 |
222 | Released 2023-09-02
223 |
224 |
225 | ## 0.0.11
226 |
227 | Released 2023-09-01
228 |
229 |
230 | ## 0.0.10
231 |
232 | Released 2023-08-31
233 |
234 |
235 | ## 0.0.9
236 |
237 | Released 2023-08-31
238 |
239 |
240 | ## 0.0.8
241 |
242 | Released 2023-08-25
243 |
244 |
245 | ## 0.0.7
246 |
247 | Released 2023-08-21
248 |
249 | - Update dependencies
250 |
251 | ## 0.0.6
252 |
253 | Released 2023-08-21
254 |
255 |
256 | ## 0.0.5
257 |
258 | Released 2023-08-20
259 |
260 |
261 | ## 0.0.4
262 |
263 | Released 2023-08-20
264 |
265 |
266 | ## 0.0.3
267 |
268 | Released 2023-08-20
269 |
270 |
271 | ## 0.0.2
272 |
273 | Released 2023-08-20
274 |
275 |
276 |
--------------------------------------------------------------------------------
/LICENSE.LGPL:
--------------------------------------------------------------------------------
1 | This software is licensed under the LGPL3, included below.
2 |
3 | As a special exception to the GNU Lesser General Public License version 3
4 | ("LGPL3"), the copyright holders of this Library give you permission to
5 | convey to a third party a Combined Work that links statically or dynamically
6 | to this Library without providing any Minimal Corresponding Source or
7 | Minimal Application Code as set out in 4d or providing the installation
8 | information set out in section 4e, provided that you comply with the other
9 | provisions of LGPL3 and provided that you meet, for the Application the
10 | terms and conditions of the license(s) which apply to the Application.
11 |
12 | Except as stated in this special exception, the provisions of LGPL3 will
13 | continue to comply in full to this Library. If you modify this Library, you
14 | may apply this exception to your version of this Library, but you are not
15 | obliged to do so. If you do not wish to do so, delete this exception
16 | statement from your version. This exception does not (and cannot) modify any
17 | license terms which apply to the Application, with which you must still
18 | comply.
19 |
20 |
21 | GNU LESSER GENERAL PUBLIC LICENSE
22 | Version 3, 29 June 2007
23 |
24 | Copyright (C) 2007 Free Software Foundation, Inc.
25 | Everyone is permitted to copy and distribute verbatim copies
26 | of this license document, but changing it is not allowed.
27 |
28 |
29 | This version of the GNU Lesser General Public License incorporates
30 | the terms and conditions of version 3 of the GNU General Public
31 | License, supplemented by the additional permissions listed below.
32 |
33 | 0. Additional Definitions.
34 |
35 | As used herein, "this License" refers to version 3 of the GNU Lesser
36 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
37 | General Public License.
38 |
39 | "The Library" refers to a covered work governed by this License,
40 | other than an Application or a Combined Work as defined below.
41 |
42 | An "Application" is any work that makes use of an interface provided
43 | by the Library, but which is not otherwise based on the Library.
44 | Defining a subclass of a class defined by the Library is deemed a mode
45 | of using an interface provided by the Library.
46 |
47 | A "Combined Work" is a work produced by combining or linking an
48 | Application with the Library. The particular version of the Library
49 | with which the Combined Work was made is also called the "Linked
50 | Version".
51 |
52 | The "Minimal Corresponding Source" for a Combined Work means the
53 | Corresponding Source for the Combined Work, excluding any source code
54 | for portions of the Combined Work that, considered in isolation, are
55 | based on the Application, and not on the Linked Version.
56 |
57 | The "Corresponding Application Code" for a Combined Work means the
58 | object code and/or source code for the Application, including any data
59 | and utility programs needed for reproducing the Combined Work from the
60 | Application, but excluding the System Libraries of the Combined Work.
61 |
62 | 1. Exception to Section 3 of the GNU GPL.
63 |
64 | You may convey a covered work under sections 3 and 4 of this License
65 | without being bound by section 3 of the GNU GPL.
66 |
67 | 2. Conveying Modified Versions.
68 |
69 | If you modify a copy of the Library, and, in your modifications, a
70 | facility refers to a function or data to be supplied by an Application
71 | that uses the facility (other than as an argument passed when the
72 | facility is invoked), then you may convey a copy of the modified
73 | version:
74 |
75 | a) under this License, provided that you make a good faith effort to
76 | ensure that, in the event an Application does not supply the
77 | function or data, the facility still operates, and performs
78 | whatever part of its purpose remains meaningful, or
79 |
80 | b) under the GNU GPL, with none of the additional permissions of
81 | this License applicable to that copy.
82 |
83 | 3. Object Code Incorporating Material from Library Header Files.
84 |
85 | The object code form of an Application may incorporate material from
86 | a header file that is part of the Library. You may convey such object
87 | code under terms of your choice, provided that, if the incorporated
88 | material is not limited to numerical parameters, data structure
89 | layouts and accessors, or small macros, inline functions and templates
90 | (ten or fewer lines in length), you do both of the following:
91 |
92 | a) Give prominent notice with each copy of the object code that the
93 | Library is used in it and that the Library and its use are
94 | covered by this License.
95 |
96 | b) Accompany the object code with a copy of the GNU GPL and this license
97 | document.
98 |
99 | 4. Combined Works.
100 |
101 | You may convey a Combined Work under terms of your choice that,
102 | taken together, effectively do not restrict modification of the
103 | portions of the Library contained in the Combined Work and reverse
104 | engineering for debugging such modifications, if you also do each of
105 | the following:
106 |
107 | a) Give prominent notice with each copy of the Combined Work that
108 | the Library is used in it and that the Library and its use are
109 | covered by this License.
110 |
111 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
112 | document.
113 |
114 | c) For a Combined Work that displays copyright notices during
115 | execution, include the copyright notice for the Library among
116 | these notices, as well as a reference directing the user to the
117 | copies of the GNU GPL and this license document.
118 |
119 | d) Do one of the following:
120 |
121 | 0) Convey the Minimal Corresponding Source under the terms of this
122 | License, and the Corresponding Application Code in a form
123 | suitable for, and under terms that permit, the user to
124 | recombine or relink the Application with a modified version of
125 | the Linked Version to produce a modified Combined Work, in the
126 | manner specified by section 6 of the GNU GPL for conveying
127 | Corresponding Source.
128 |
129 | 1) Use a suitable shared library mechanism for linking with the
130 | Library. A suitable mechanism is one that (a) uses at run time
131 | a copy of the Library already present on the user's computer
132 | system, and (b) will operate properly with a modified version
133 | of the Library that is interface-compatible with the Linked
134 | Version.
135 |
136 | e) Provide Installation Information, but only if you would otherwise
137 | be required to provide such information under section 6 of the
138 | GNU GPL, and only to the extent that such information is
139 | necessary to install and execute a modified version of the
140 | Combined Work produced by recombining or relinking the
141 | Application with a modified version of the Linked Version. (If
142 | you use option 4d0, the Installation Information must accompany
143 | the Minimal Corresponding Source and Corresponding Application
144 | Code. If you use option 4d1, you must provide the Installation
145 | Information in the manner specified by section 6 of the GNU GPL
146 | for conveying Corresponding Source.)
147 |
148 | 5. Combined Libraries.
149 |
150 | You may place library facilities that are a work based on the
151 | Library side by side in a single library together with other library
152 | facilities that are not Applications and are not covered by this
153 | License, and convey such a combined library under terms of your
154 | choice, if you do both of the following:
155 |
156 | a) Accompany the combined library with a copy of the same work based
157 | on the Library, uncombined with any other library facilities,
158 | conveyed under the terms of this License.
159 |
160 | b) Give prominent notice with the combined library that part of it
161 | is a work based on the Library, and explaining where to find the
162 | accompanying uncombined form of the same work.
163 |
164 | 6. Revised Versions of the GNU Lesser General Public License.
165 |
166 | The Free Software Foundation may publish revised and/or new versions
167 | of the GNU Lesser General Public License from time to time. Such new
168 | versions will be similar in spirit to the present version, but may
169 | differ in detail to address new problems or concerns.
170 |
171 | Each version is given a distinguishing version number. If the
172 | Library as you received it specifies that a certain numbered version
173 | of the GNU Lesser General Public License "or any later version"
174 | applies to it, you have the option of following the terms and
175 | conditions either of that published version or of any later version
176 | published by the Free Software Foundation. If the Library as you
177 | received it does not specify a version number of the GNU Lesser
178 | General Public License, you may choose any version of the GNU Lesser
179 | General Public License ever published by the Free Software Foundation.
180 |
181 | If the Library as you received it specifies that a proxy can decide
182 | whether future versions of the GNU Lesser General Public License shall
183 | apply, that proxy's public statement of acceptance of any version is
184 | permanent authorization for you to choose that version for the
185 | Library.
186 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.9
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "skip-sql",
6 | defaultLocalization: "en",
7 | platforms: [.iOS(.v16), .macOS(.v13), .tvOS(.v16), .watchOS(.v9), .macCatalyst(.v16)],
8 | products: [
9 | .library(name: "SkipSQL", targets: ["SkipSQL"]),
10 | .library(name: "SkipSQLPlus", type: .dynamic, targets: ["SkipSQLPlus"]),
11 | ],
12 | dependencies: [
13 | .package(url: "https://source.skip.tools/skip.git", from: "1.1.11"),
14 | .package(url: "https://source.skip.tools/skip-foundation.git", from: "1.1.11"),
15 | .package(url: "https://source.skip.tools/skip-unit.git", from: "1.0.1"),
16 | .package(url: "https://source.skip.tools/skip-ffi.git", from: "1.0.0"),
17 | .package(url: "https://source.skip.tools/skip-ltc.git", "0.0.0"..<"2.0.0"),
18 | ],
19 | targets: [
20 | .target(name: "SkipSQL", dependencies: [
21 | .product(name: "SkipFoundation", package: "skip-foundation"),
22 | .product(name: "SkipFFI", package: "skip-ffi")
23 | ], plugins: [.plugin(name: "skipstone", package: "skip")]),
24 | .testTarget(name: "SkipSQLTests", dependencies: [
25 | "SkipSQL",
26 | .product(name: "SkipTest", package: "skip")
27 | ], plugins: [.plugin(name: "skipstone", package: "skip")]),
28 | .target(name: "SkipSQLPlus", dependencies: [
29 | "SkipSQL",
30 | "SQLExt",
31 | ], plugins: [.plugin(name: "skipstone", package: "skip")]),
32 | .testTarget(name: "SkipSQLPlusTests", dependencies: [
33 | "SkipSQLPlus",
34 | .product(name: "SkipTest", package: "skip")
35 | ], plugins: [.plugin(name: "skipstone", package: "skip")]),
36 | .target(name: "SQLExt", dependencies: [
37 | .product(name: "SkipLTC", package: "skip-ltc"),
38 | .product(name: "SkipUnit", package: "skip-unit")
39 | ], sources: ["sqlite"],
40 | publicHeadersPath: "sqlite",
41 | cSettings: [
42 | .headerSearchPath("sqlite"),
43 | .define("SQLITE_DQS", to: "0"),
44 | .define("SQLITE_ENABLE_API_ARMOR"),
45 | .define("SQLITE_ENABLE_COLUMN_METADATA"),
46 | .define("SQLITE_ENABLE_DBSTAT_VTAB"),
47 | .define("SQLITE_ENABLE_FTS3"),
48 | .define("SQLITE_ENABLE_FTS3_PARENTHESIS"),
49 | .define("SQLITE_ENABLE_FTS3_TOKENIZER"),
50 | .define("SQLITE_ENABLE_FTS4"),
51 | .define("SQLITE_ENABLE_FTS5"),
52 | .define("SQLITE_ENABLE_MEMORY_MANAGEMENT"),
53 | .define("SQLITE_ENABLE_PREUPDATE_HOOK"),
54 | .define("SQLITE_ENABLE_RTREE"),
55 | .define("SQLITE_ENABLE_SESSION"),
56 | .define("SQLITE_ENABLE_STMTVTAB"),
57 | .define("SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION"),
58 | .define("SQLITE_ENABLE_UNLOCK_NOTIFY"),
59 | .define("SQLITE_MAX_VARIABLE_NUMBER", to: "250000"),
60 | .define("SQLITE_LIKE_DOESNT_MATCH_BLOBS"),
61 | .define("SQLITE_OMIT_DEPRECATED"),
62 | .define("SQLITE_OMIT_SHARED_CACHE"),
63 | .define("SQLITE_SECURE_DELETE"),
64 | .define("SQLITE_THREADSAFE", to: "2"),
65 | .define("SQLITE_USE_URI"),
66 | .define("SQLITE_ENABLE_SNAPSHOT"),
67 | .define("SQLITE_HAS_CODEC"),
68 | .define("SQLITE_TEMP_STORE", to: "2"),
69 | .define("HAVE_GETHOSTUUID", to: "0"),
70 | .define("SQLCIPHER_CRYPTO_LIBTOMCRYPT"),
71 | //.unsafeFlags(["-Wno-shorten-64-to-32", "-Wno-ambiguous-macro"]), // enabled manually in libs
72 | ],
73 | plugins: [.plugin(name: "skipstone", package: "skip")]),
74 |
75 | ]
76 | )
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SkipSQL
2 |
3 | The SkipSQL module is a dual-platform [Skip Lite](https://skip.tools) framework that provides access to sqlite database in Darwin and Android systems.
4 |
5 | ## Usage
6 |
7 | ### Connection example
8 |
9 | To connect
10 | ```swift
11 | let dbpath = URL.documentsDirectory.appendingPathComponent("db.sqlite")
12 |
13 | let ctx = try SQLContext(path: dbpath, flags: [.create, .readWrite])
14 | defer { ctx.close() }
15 |
16 | try sqlite.exec(sql: "CREATE TABLE IF NOT EXISTS SOME_TABLE (STRING TEXT)")
17 |
18 | try sqlite.exec(sql: "INSERT INTO SOME_TABLE (STRING) VALUES ('ABC')")
19 |
20 | let rows: [[SQLValue]] = ctx.query(sql: "SELECT STRING FROM SOME_TABLE")
21 | assert(rows[0][0] == SQLValue.string("ABC"))
22 |
23 | ```
24 |
25 | ### In-memory databases
26 |
27 | When passing `nil` as the path, the `SQLContext` will reside entirely in memory, and will not persist once the context is closed. This can be useful for unit testing and performing in-memory calculations, or as a temporary engine for calculations and sorting.
28 |
29 | ```swift
30 | let ctx = try SQLContext(path: nil)
31 | defer { ctx.close() }
32 |
33 | let rows: [[SQLValue]] = ctx.query(sql: "SELECT 1, 1.1+2.2, 'AB'||'C'")
34 |
35 | assert(rows[0][0] == SQLValue.integer(1))
36 | assert(rows[0][1] == SQLValue.float(3.3))
37 | assert(rows[0][2] == SQLValue.text("ABC"))
38 |
39 | ```
40 |
41 | ### Transactions
42 |
43 | Performing multiple operations in the context of a transaction will ensure that either all the operations succeed (`COMMIT`) or fail (`ROLLBACK`) together.
44 |
45 | ```swift
46 | try ctx.transaction {
47 | try ctx.exec(sql: "INSERT INTO TABLE_NAME VALUES(1)")
48 | try ctx.exec(sql: "INSERT INTO TABLE_NAME VALUES(2)")
49 | }
50 | ```
51 |
52 | The default transaction type is `.deferred`, but it can be specified as a parameter to `transaction` to override the default, or `nil` to perform the operation without a transaction.
53 |
54 | ### Bound parameters
55 |
56 | Retaining a prepared `SQLStatement` will mean that the SQL doesn't need to be re-parsed each time a query or insert/update statement is performed.
57 |
58 | SQL statements with a `?` symbol will expect those parameters to be applied with the `bind` function before the statement is executed.
59 |
60 | ```swift
61 |
62 | let insert = try sqlite.prepare(sql: "INSERT INTO TABLE_NAME (NUM, STR) VALUES (?, ?)")
63 | defer { insert.close() }
64 |
65 | // insert 1,000 rows in a single transaction, re-using the insert statement
66 | try sqlite.transaction {
67 | for i in 1...1_000 {
68 | let params: [SQLValue] = [
69 | SQLValue.integer(Int64(i)),
70 | SQLValue.text("Row #\(i)")
71 | ]
72 | try insert.update(parameters: params)
73 | }
74 | }
75 |
76 | ```
77 |
78 |
79 | ### Schema Migration
80 |
81 | There is no built-in support for schema migrations. Following is a part of a sample of how you might perform migrations in your own app.
82 |
83 |
84 | ```swift
85 | // track the version of the schema in the database, which can be used for schema migration
86 | try ctx.exec(sql: "CREATE TABLE IF NOT EXISTS DB_SCHEMA_VERSION (id INTEGER PRIMARY KEY, version INTEGER)")
87 | try ctx.exec(sql: "INSERT OR IGNORE INTO DB_SCHEMA_VERSION (id, version) VALUES (0, 0)")
88 | var currentVersion = try ctx.query(sql: "SELECT version FROM DB_SCHEMA_VERSION").first?.first?.integerValue ?? 0
89 |
90 | func migrateSchema(v version: Int64, ddl: String) throws {
91 | if currentVersion < version {
92 | let startTime = Date.now
93 | try ctx.transaction {
94 | try ctx.exec(sql: ddl) // perform the DDL operation
95 | // then update the schema version
96 | try ctx.exec(sql: "UPDATE DB_SCHEMA_VERSION SET version = ?", parameters: [SQLValue.integer(version)])
97 | }
98 | currentVersion = version
99 | logger.log("updated database schema to \(version) in \(startTime.durationToNow)")
100 | }
101 | }
102 |
103 | // the initial creation script for a new database
104 | try migrateSchema(v: 1, ddl: """
105 | CREATE TABLE DATA_ITEM (ID INTEGER PRIMARY KEY AUTOINCREMENT)
106 | """)
107 | // migrate records to have new description column
108 | try migrateSchema(v: 2, ddl: """
109 | ALTER TABLE DATA_ITEM ADD COLUMN DESCRIPTION TEXT
110 | """)
111 | ```
112 |
113 | ### Concurrency
114 |
115 | As a thin layer over a SQLite connection, SkipSQL itself performs no locking or manages threads in any way. It is up to the application layer to set up reader/writer locks, or else just perform all the operations in an isolated context (e.g., using an actor).
116 |
117 | The SQLite guide on [Locking And Concurrency](https://www.sqlite.org/lockingv3.html) can provide additional guidance.
118 |
119 |
120 | ## Implementation
121 |
122 | SkipSQL speaks directly to the low-level SQLite3 C library that is included with all Darwin/iOS/Android operating systems.
123 | On Darwin/iOS, it communicates directly through Swift's C bridging support.
124 | On Android, it uses the [SkipFFI](https://source.skip.tools/skip-ffi) module to interact directly with the underlying sqlite installation on Android.
125 | (For performance and a consistent API, SkipSQL eschews Android's `android.database.sqlite` Java wrapper, and uses JNA to directly access the SQLite C API.)
126 |
127 | ## SQLite Versions
128 |
129 | ### Vendored SQLite Versions
130 |
131 | Because SkipSQL uses the version of SQLite that is shipped with the platform, care should be taken when using recent SQLite features, such as the [`json`](https://sqlite.org/json1.html) function, which is new in SQLite 3.38. This would raise an error on Android versions below 14.0 (API 34) and iOS versions below 16.0.
132 |
133 | Be aware that some very useful SQL features may only have been added to more recent versions of SQLite, such as strict tables (added in 3.37). This may impact the Android API version you can deploy back to, so be sure to test your code on the oldest available Android emulator and iOS simulator for your project.
134 |
135 | Also be aware that the availability of some SQL features are contingent on the compile flags used to build the vendored sqlite implementation provided as part of the OS, such as `SQLITE_ENABLE_JSON1` enabling the various [`json_`](https://www.sqlite.org/json1.html) operations. In the case of Android, be aware that local Robolectric testing will be insufficient to identify any limitations resulting from sqlite compile flags, since local testing will use the local (i.e., macOS-vendored) version of SQLite. Testing against an Android emulator (or device) should be performed when developing new SQL operations.
136 |
137 |
138 | | OS Version | SQLite Version |
139 | |------------------------|----------------|
140 | | Android 9 (API 28) | 3.22 |
141 | | iOS 13 | 3.28 |
142 | | Android 10 (API 30) | 3.28 |
143 | | iOS 14 | 3.32 |
144 | | Android 11 (API 31) | 3.32 |
145 | | Android 12 (API 32) | 3.32 |
146 | | Android 13 (API 33) | 3.32 |
147 | | iOS 15 | 3.36 |
148 | | iOS 16 | 3.39 |
149 | | Android 14 (API 34) | 3.39 |
150 | | Android 15 (API 35) | 3.42 |
151 | | SQLPlus | 3.44 |
152 |
153 |
154 | ---
155 |
156 | ### SQLPlus
157 |
158 | The `skip-sql` framework includes an additional `SQLPlus` module,
159 | which creates a local build with the following extensions enabled:
160 |
161 | - Full Text Search (FTS)
162 | - Encryption (sqlcipher)
163 |
164 | The `SQLPlus` module uses sqlite version 3.44.2, which means
165 | that it will be safe to use newer sqlite features like
166 | the [`json`](https://sqlite.org/json1.html) function,
167 | regardless of the Android API and iOS versions of the
168 | deployment platform.
169 |
170 | This comes at the cost of additional build time for the native libraries,
171 | as well as a larger artifact size (around 1MB on iOS and 4MB on Android).
172 |
173 | #### Using SQLPlus
174 |
175 | The SQLPlus extensions can be used by importing the `SkipSQLPlus` module
176 | and passing `configuration: .plus` to the `SQLContext` constructor, like so:
177 |
178 | ```swift
179 | import SkipSQL
180 | import SkipSQLPlus
181 |
182 | let dbpath = URL.documentsDirectory.appendingPathComponent("db.sqlite")
183 | let db = try SQLContext(path: dbpath.path, flags: [.create, .readWrite], configuration: .plus)
184 | // do something with the database
185 | db.close()
186 | ```
187 |
188 | #### JSON
189 |
190 | SQLPlus enables the [`json`](https://sqlite.org/json1.html) extensions:
191 |
192 |
193 | ```swift
194 | let sqlplus = SQLContext(configuration: .plus)
195 | try sqlplus.exec(sql: #"CREATE TABLE users (id INTEGER PRIMARY KEY, profile JSON)"#)
196 |
197 | try sqlplus.exec(sql: #"INSERT INTO users (id, profile) VALUES (1, '{"name": "Alice", "age": 30}')"#)
198 | try sqlplus.exec(sql: #"INSERT INTO users (id, profile) VALUES (2, '{"name": "Bob", "age": 25}')"#)
199 |
200 | let j1 = try sqlplus.query(sql: #"SELECT json_extract(profile, '$.name') as name FROM users WHERE id = ?"#, parameters: [.integer(1)]).first
201 | assert j1 == [.text("Alice")]
202 |
203 | let j2 = try sqlplus.query(sql: #"SELECT json_extract(profile, '$.name') as name, json_extract(profile, '$.age') as age FROM users WHERE id = ?"#, parameters: [.integer(2)]).first
204 | assert j2 == [.text("Bob"), .integer(25)]
205 | ```
206 |
207 |
208 | #### Encryption
209 |
210 | SQLPlus contains the SQLCipher extension, which adds 256 bit AES encryption of database files and other security features like:
211 |
212 | - On-the-fly encryption
213 | - Tamper detection
214 | - Memory sanitization
215 | - Strong key derivation
216 |
217 | SQLCipher is based on SQLite and stable upstream release features are periodically integrated. The extension is documented at the official [SQLCipher site](https://www.zetetic.net/sqlcipher/). It is used by many mobile applications like the [Signal](https://github.com/signalapp/sqlcipher) iOS and Android app to
218 | secure local database files. Cryptographic algorithms are provided by the [LibTomCrypt](https://github.com/libtom/libtomcrypt) C library, which is included alongside the sqlcipher sources.
219 |
220 | An example of creating an encryped database:
221 |
222 | ```swift
223 | import SkipSQL
224 | import SkipSQLPlus
225 |
226 | let dbpath = URL.documentsDirectory.appendingPathComponent("encrypted.sqlite")
227 | let db = try SQLContext(path: dbpath.path, flags: [.create, .readWrite], configuration: .plus)
228 | _ = try db.query(sql: "PRAGMA key = 'password'")
229 | try db.exec(sql: #"CREATE TABLE SOME_TABLE(col)"#)
230 | try db.exec(sql: #"INSERT INTO SOME_TABLE(col) VALUES(?)"#, parameters: [.text("SOME SECRET STRING")])
231 | try db.close()
232 | ```
233 |
234 |
235 | ## Building
236 |
237 | This project is a Swift Package Manager module that uses the
238 | [Skip](https://skip.tools) plugin to transpile Swift into Kotlin.
239 |
240 | Building the module requires that Skip be installed using
241 | [Homebrew](https://brew.sh) with `brew install skiptools/skip/skip`.
242 | This will also install the necessary build prerequisites:
243 | Kotlin, Gradle, and the Android build tools.
244 |
245 | ## Testing
246 |
247 | The module can be tested using the standard `swift test` command
248 | or by running the test target for the macOS destination in Xcode,
249 | which will run the Swift tests as well as the transpiled
250 | Kotlin JUnit tests in the Robolectric Android simulation environment.
251 |
252 | Parity testing can be performed with `skip test`,
253 | which will output a table of the test results for both platforms.
254 |
255 | ## Contributing
256 |
257 | We welcome contributions to this package in the form of enhancements and bug fixes.
258 |
259 | The general flow for contributing to this and any other Skip package is:
260 |
261 | 1. Fork this repository and enable actions from the "Actions" tab
262 | 2. Check out your fork locally
263 | 3. When developing alongside a Skip app, add the package to a [shared workspace](https://skip.tools/docs/contributing) to see your changes incorporated in the app
264 | 4. Push your changes to your fork and ensure the CI checks all pass in the Actions tab
265 | 5. Add your name to the Skip [Contributor Agreement](https://github.com/skiptools/clabot-config)
266 | 6. Open a Pull Request from your fork with a description of your changes
267 |
268 | ## License
269 |
270 | This software is licensed under the
271 | [GNU Lesser General Public License v3.0](https://spdx.org/licenses/LGPL-3.0-only.html),
272 | with the following
273 | [linking exception](https://spdx.org/licenses/LGPL-3.0-linking-exception.html)
274 | to clarify that distribution to restricted environments (e.g., app stores)
275 | is permitted:
276 |
277 | > This software is licensed under the LGPL3, included below.
278 | > As a special exception to the GNU Lesser General Public License version 3
279 | > ("LGPL3"), the copyright holders of this Library give you permission to
280 | > convey to a third party a Combined Work that links statically or dynamically
281 | > to this Library without providing any Minimal Corresponding Source or
282 | > Minimal Application Code as set out in 4d or providing the installation
283 | > information set out in section 4e, provided that you comply with the other
284 | > provisions of LGPL3 and provided that you meet, for the Application the
285 | > terms and conditions of the license(s) which apply to the Application.
286 | > Except as stated in this special exception, the provisions of LGPL3 will
287 | > continue to comply in full to this Library. If you modify this Library, you
288 | > may apply this exception to your version of this Library, but you are not
289 | > obliged to do so. If you do not wish to do so, delete this exception
290 | > statement from your version. This exception does not (and cannot) modify any
291 | > license terms which apply to the Application, with which you must still
292 | > comply.
293 |
294 |
--------------------------------------------------------------------------------
/Sources/SQLExt/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.3)
2 |
3 | project(sqlext LANGUAGES C)
4 |
5 | file(GLOB_RECURSE SOURCES sqlite/*.c)
6 | add_library(sqlext SHARED ${SOURCES})
7 | include_directories(sqlext PUBLIC sqlite/)
8 |
9 | # these should match the definitions in the Package.swift
10 | # so the Android build and the Swift build options match
11 | add_compile_definitions(SQLITE_DQS=0)
12 | add_compile_definitions(SQLITE_ENABLE_API_ARMOR)
13 | add_compile_definitions(SQLITE_ENABLE_COLUMN_METADATA)
14 | add_compile_definitions(SQLITE_ENABLE_DBSTAT_VTAB)
15 | add_compile_definitions(SQLITE_ENABLE_FTS3)
16 | add_compile_definitions(SQLITE_ENABLE_FTS3_PARENTHESIS)
17 | add_compile_definitions(SQLITE_ENABLE_FTS3_TOKENIZER)
18 | add_compile_definitions(SQLITE_ENABLE_FTS4)
19 | add_compile_definitions(SQLITE_ENABLE_FTS5)
20 | add_compile_definitions(SQLITE_ENABLE_MEMORY_MANAGEMENT)
21 | add_compile_definitions(SQLITE_ENABLE_PREUPDATE_HOOK)
22 | add_compile_definitions(SQLITE_ENABLE_RTREE)
23 | add_compile_definitions(SQLITE_ENABLE_SESSION)
24 | add_compile_definitions(SQLITE_ENABLE_STMTVTAB)
25 | add_compile_definitions(SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION)
26 | add_compile_definitions(SQLITE_ENABLE_UNLOCK_NOTIFY)
27 | add_compile_definitions(SQLITE_MAX_VARIABLE_NUMBER=250000)
28 | add_compile_definitions(SQLITE_LIKE_DOESNT_MATCH_BLOBS)
29 | add_compile_definitions(SQLITE_OMIT_DEPRECATED)
30 | add_compile_definitions(SQLITE_OMIT_SHARED_CACHE)
31 | add_compile_definitions(SQLITE_SECURE_DELETE)
32 | add_compile_definitions(SQLITE_THREADSAFE=2)
33 | add_compile_definitions(SQLITE_USE_URI)
34 | add_compile_definitions(SQLITE_ENABLE_SNAPSHOT)
35 | add_compile_definitions(SQLITE_HAS_CODEC)
36 | add_compile_definitions(SQLITE_TEMP_STORE=2)
37 | add_compile_definitions(HAVE_GETHOSTUUID=0)
38 | add_compile_definitions(SQLCIPHER_CRYPTO_LIBTOMCRYPT)
39 |
40 |
41 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -frtti -fexceptions")
42 |
43 | #set(CMAKE_FIND_LIBRARY_PREFIXES "lib")
44 | #set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
45 |
46 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
47 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
48 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
49 |
50 | set(CMAKE_FIND_DEBUG_MODE ON)
51 |
52 | get_filename_component(CMAKE_PARENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
53 | #message("CMAKE FINDING LIBRARY FOR ABI: ${ANDROID_ABI} in: ${CMAKE_PARENT_SOURCE_DIR} for build type: ${CMAKE_BUILD_TYPE}")
54 |
55 | if(CMAKE_BUILD_TYPE STREQUAL "Release")
56 | set(BUILD_MODE "Release")
57 | elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
58 | set(BUILD_MODE "Release")
59 | elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
60 | set(BUILD_MODE "Release")
61 | elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
62 | set(BUILD_MODE "Debug")
63 | else()
64 | message(WARNING "CMAKE_BUILD_TYPE is set to an unsupported value: ${CMAKE_BUILD_TYPE}. Defaulting to Debug.")
65 | set(BUILD_MODE "Debug")
66 | endif()
67 |
68 | string(TOLOWER "${BUILD_MODE}" BUILD_MODE_LOWER)
69 |
70 | #message("CHECKING CMAKE LIBRARY: ${CMAKE_PARENT_SOURCE_DIR}/../LibTomCrypt/")
71 |
72 | find_library(TOMCRYPT
73 | NAMES tomcrypt
74 | REQUIRED
75 | PATHS
76 |
77 | # the output paths for the LibTomCrypt project
78 | # it would be nice if we could discover this automatically based on the gradle dependency
79 | # after updating to the android-gradle-plugin 8.5.0, the output has moved to mergeDebugNativeLibs/mergeReleaseNativeLibs
80 | #${CMAKE_PARENT_SOURCE_DIR}/../LibTomCrypt/build/intermediates/merged_native_libs/${BUILD_MODE_LOWER}/out/lib/${ANDROID_ABI}/
81 | ${CMAKE_PARENT_SOURCE_DIR}/../LibTomCrypt/build/intermediates/merged_native_libs/${BUILD_MODE_LOWER}/merge${BUILD_MODE}NativeLibs/out/lib/${ANDROID_ABI}/
82 | ${CMAKE_PARENT_SOURCE_DIR}/../LibTomCrypt/.build/*/intermediates/merged_native_libs/${BUILD_MODE_LOWER}/merge${BUILD_MODE}NativeLibs/out/lib/${ANDROID_ABI}/
83 |
84 | NO_DEFAULT_PATH
85 | NO_CMAKE_FIND_ROOT_PATH
86 | )
87 |
88 |
89 | #message("CMAKE FIND LIBRARY FOR: ${ANDROID_ABI}: ${TOMCRYPT}")
90 |
91 | target_link_libraries(sqlext ${TOMCRYPT})
92 |
93 | # sqlite has calls to __android_log_print
94 | target_link_libraries(sqlext log)
95 |
96 | # support 16 KB page sizes: https://developer.android.com/guide/practices/page-sizes
97 | target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
98 |
--------------------------------------------------------------------------------
/Sources/SQLExt/Skip/skip.yml:
--------------------------------------------------------------------------------
1 | # This skip.yml file will generate a build.gradle.kts that uses the CMakeLists.txt for a native build.
2 | #
3 | # android {
4 | # namespace = group as String
5 | # compileSdk = libs.versions.android.sdk.compile.get().toInt()
6 | # defaultConfig {
7 | # minSdk = libs.versions.android.sdk.min.get().toInt()
8 | # }
9 | # externalNativeBuild {
10 | # cmake {
11 | # path = file("ext/CMakeLists.txt")
12 | # }
13 | # }
14 | # }
15 |
16 | # the blocks to add to the build.gradle.kts
17 | build:
18 | contents:
19 | - block: 'android'
20 | export: false
21 | contents:
22 | - block: 'externalNativeBuild'
23 | contents:
24 | - block: 'cmake'
25 | contents:
26 | - 'path = file("ext/CMakeLists.txt")'
27 | - block: 'defaultConfig'
28 | contents:
29 | - block: 'externalNativeBuild'
30 | contents:
31 | - block: 'cmake'
32 | contents:
33 | # activating trace helps diagnose issues with not finding build dependencies
34 | #- 'arguments += listOf("--trace")'
35 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | #ifndef TOMCRYPT_H_
5 | #define TOMCRYPT_H_
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | /* use configuration data */
16 | #include "tomcrypt_custom.h"
17 |
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | /* version */
23 | #define CRYPT 0x0118
24 | #define SCRYPT "1.18.2-develop"
25 |
26 | /* max size of either a cipher/hash block or symmetric key [largest of the two] */
27 | #define MAXBLOCKSIZE 144
28 |
29 | #ifndef TAB_SIZE
30 | /* descriptor table size */
31 | #define TAB_SIZE 34
32 | #endif
33 |
34 | /* error codes [will be expanded in future releases] */
35 | enum {
36 | CRYPT_OK=0, /* Result OK */
37 | CRYPT_ERROR, /* Generic Error */
38 | CRYPT_NOP, /* Not a failure but no operation was performed */
39 |
40 | CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
41 | CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
42 | CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
43 |
44 | CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
45 | CRYPT_INVALID_PACKET, /* Invalid input packet given */
46 |
47 | CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
48 | CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
49 |
50 | CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
51 | CRYPT_INVALID_HASH, /* Invalid hash specified */
52 | CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
53 |
54 | CRYPT_MEM, /* Out of memory */
55 |
56 | CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
57 | CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
58 |
59 | CRYPT_INVALID_ARG, /* Generic invalid argument */
60 | CRYPT_FILE_NOTFOUND, /* File Not Found */
61 |
62 | CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
63 |
64 | CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
65 |
66 | CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */
67 |
68 | CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */
69 |
70 | CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
71 |
72 | CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
73 | CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */
74 |
75 | CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */
76 | };
77 |
78 | #include "tomcrypt_cfg.h"
79 | #include "tomcrypt_macros.h"
80 | #include "tomcrypt_cipher.h"
81 | #include "tomcrypt_hash.h"
82 | #include "tomcrypt_mac.h"
83 | #include "tomcrypt_prng.h"
84 | #include "tomcrypt_pk.h"
85 | #include "tomcrypt_math.h"
86 | #include "tomcrypt_misc.h"
87 | #include "tomcrypt_argchk.h"
88 | #include "tomcrypt_pkcs.h"
89 |
90 | #ifdef __cplusplus
91 | }
92 | #endif
93 |
94 | #endif /* TOMCRYPT_H_ */
95 |
96 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_argchk.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* Defines the LTC_ARGCHK macro used within the library */
5 | /* ARGTYPE is defined in tomcrypt_cfg.h */
6 |
7 | /* ARGTYPE is per default defined to 0 */
8 | #if ARGTYPE == 0
9 |
10 | #include
11 |
12 | LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d);
13 | #define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
14 | #define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0)
15 |
16 | #elif ARGTYPE == 1
17 |
18 | /* fatal type of error */
19 | #define LTC_ARGCHK(x) assert((x))
20 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
21 |
22 | #elif ARGTYPE == 2
23 |
24 | #define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
25 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
26 |
27 | #elif ARGTYPE == 3
28 |
29 | #define LTC_ARGCHK(x) LTC_UNUSED_PARAM(x)
30 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
31 |
32 | #elif ARGTYPE == 4
33 |
34 | #define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
35 | #define LTC_ARGCHKVD(x) if (!(x)) return;
36 |
37 | #endif
38 |
39 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_cfg.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* This is the build config file.
5 | *
6 | * With this you can setup what to include/exclude automatically during any build. Just comment
7 | * out the line that #define's the word for the thing you want to remove. phew!
8 | */
9 |
10 | #ifndef TOMCRYPT_CFG_H
11 | #define TOMCRYPT_CFG_H
12 |
13 | #if defined(_WIN32) || defined(_MSC_VER)
14 | #define LTC_CALL __cdecl
15 | #elif !defined(LTC_CALL)
16 | #define LTC_CALL
17 | #endif
18 |
19 | #ifndef LTC_EXPORT
20 | #define LTC_EXPORT
21 | #endif
22 |
23 | /* certain platforms use macros for these, making the prototypes broken */
24 | #ifndef LTC_NO_PROTOTYPES
25 |
26 | /* you can change how memory allocation works ... */
27 | LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
28 | LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
29 | LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
30 | LTC_EXPORT void LTC_CALL XFREE(void *p);
31 |
32 | LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
33 |
34 |
35 | /* change the clock function too */
36 | LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
37 |
38 | /* various other functions */
39 | LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
40 | LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
41 | LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
42 |
43 | LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
44 |
45 | #endif
46 |
47 | /* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */
48 | #if defined(__GNUC__) || defined(__xlc__)
49 | #define LTC_INLINE __inline__
50 | #elif defined(_MSC_VER) || defined(__HP_cc)
51 | #define LTC_INLINE __inline
52 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
53 | #define LTC_INLINE inline
54 | #else
55 | #define LTC_INLINE
56 | #endif
57 |
58 | #if defined(__clang__) || defined(__GNUC_MINOR__)
59 | #define LTC_NORETURN __attribute__ ((noreturn))
60 | #elif defined(_MSC_VER)
61 | #define LTC_NORETURN __declspec(noreturn)
62 | #else
63 | #define LTC_NORETURN
64 | #endif
65 |
66 | /* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
67 | #ifndef ARGTYPE
68 | #define ARGTYPE 0
69 | #endif
70 |
71 | #undef LTC_ENCRYPT
72 | #define LTC_ENCRYPT 0
73 | #undef LTC_DECRYPT
74 | #define LTC_DECRYPT 1
75 |
76 | /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
77 | *
78 | * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
79 | * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
80 | * use the portable [slower] macros.
81 | */
82 | /* detect x86/i386/ARM 32bit */
83 | #if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_ARM)
84 | #define ENDIAN_LITTLE
85 | #define ENDIAN_32BITWORD
86 | #define LTC_FAST
87 | #endif
88 |
89 | /* detect amd64/x64/arm64 */
90 | #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64)
91 | #define ENDIAN_LITTLE
92 | #define ENDIAN_64BITWORD
93 | #define LTC_FAST
94 | #if defined(__SSE4_1__)
95 | #if __SSE4_1__ == 1
96 | #define LTC_AMD64_SSE4_1
97 | #endif
98 | #endif
99 | #endif
100 |
101 | /* detect PPC32 */
102 | #if defined(LTC_PPC32)
103 | #define ENDIAN_BIG
104 | #define ENDIAN_32BITWORD
105 | #define LTC_FAST
106 | #endif
107 |
108 | /* detects MIPS R5900 processors (PS2) */
109 | #if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
110 | #define ENDIAN_64BITWORD
111 | #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
112 | #define ENDIAN_BIG
113 | #else
114 | #define ENDIAN_LITTLE
115 | #endif
116 | #endif
117 |
118 | /* detect AIX */
119 | #if defined(_AIX) && defined(_BIG_ENDIAN)
120 | #define ENDIAN_BIG
121 | #if defined(__LP64__) || defined(_ARCH_PPC64)
122 | #define ENDIAN_64BITWORD
123 | #else
124 | #define ENDIAN_32BITWORD
125 | #endif
126 | #endif
127 |
128 | /* detect HP-UX */
129 | #if defined(__hpux) || defined(__hpux__)
130 | #define ENDIAN_BIG
131 | #if defined(__ia64) || defined(__ia64__) || defined(__LP64__)
132 | #define ENDIAN_64BITWORD
133 | #else
134 | #define ENDIAN_32BITWORD
135 | #endif
136 | #endif
137 |
138 | /* detect Apple OS X */
139 | #if defined(__APPLE__) && defined(__MACH__)
140 | #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__)
141 | #define ENDIAN_LITTLE
142 | #else
143 | #define ENDIAN_BIG
144 | #endif
145 | #if defined(__LP64__) || defined(__x86_64__)
146 | #define ENDIAN_64BITWORD
147 | #else
148 | #define ENDIAN_32BITWORD
149 | #endif
150 | #endif
151 |
152 | /* detect SPARC and SPARC64 */
153 | #if defined(__sparc__) || defined(__sparc)
154 | #define ENDIAN_BIG
155 | #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)
156 | #define ENDIAN_64BITWORD
157 | #else
158 | #define ENDIAN_32BITWORD
159 | #endif
160 | #endif
161 |
162 | /* detect IBM S390(x) */
163 | #if defined(__s390x__) || defined(__s390__)
164 | #define ENDIAN_BIG
165 | #if defined(__s390x__)
166 | #define ENDIAN_64BITWORD
167 | #else
168 | #define ENDIAN_32BITWORD
169 | #endif
170 | #endif
171 |
172 | /* detect PPC64 */
173 | #if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
174 | #define ENDIAN_64BITWORD
175 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
176 | #define ENDIAN_BIG
177 | #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
178 | #define ENDIAN_LITTLE
179 | #endif
180 | #define LTC_FAST
181 | #endif
182 |
183 | /* endianness fallback */
184 | #if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE)
185 | #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \
186 | defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
187 | defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
188 | defined(__BIG_ENDIAN__) || \
189 | defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
190 | defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \
191 | defined(__m68k__)
192 | #define ENDIAN_BIG
193 | #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \
194 | defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
195 | defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
196 | defined(__LITTLE_ENDIAN__) || \
197 | defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
198 | defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
199 | defined(_M_ARM) || defined(_M_ARM64)
200 | #define ENDIAN_LITTLE
201 | #else
202 | #error Cannot detect endianness
203 | #endif
204 | #endif
205 |
206 | /* ulong64: 64-bit data type */
207 | #ifdef _MSC_VER
208 | #define CONST64(n) n ## ui64
209 | typedef unsigned __int64 ulong64;
210 | typedef __int64 long64;
211 | #else
212 | #define CONST64(n) n ## uLL
213 | typedef unsigned long long ulong64;
214 | typedef long long long64;
215 | #endif
216 |
217 | /* ulong32: "32-bit at least" data type */
218 | #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \
219 | defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
220 | defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
221 | defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
222 | defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
223 | defined(__LP64__) || defined(_LP64) || defined(__64BIT__) || defined(_M_ARM64)
224 | typedef unsigned ulong32;
225 | #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
226 | #define ENDIAN_64BITWORD
227 | #endif
228 | #else
229 | typedef unsigned long ulong32;
230 | #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
231 | #define ENDIAN_32BITWORD
232 | #endif
233 | #endif
234 |
235 | #if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER)
236 | typedef unsigned long long ltc_mp_digit;
237 | #else
238 | typedef unsigned long ltc_mp_digit;
239 | #endif
240 |
241 | /* No asm is a quick way to disable anything "not portable" */
242 | #ifdef LTC_NO_ASM
243 | #define ENDIAN_NEUTRAL
244 | #undef ENDIAN_32BITWORD
245 | #undef ENDIAN_64BITWORD
246 | #undef LTC_FAST
247 | #define LTC_NO_BSWAP
248 | #define LTC_NO_ROLC
249 | #define LTC_NO_ROTATE
250 | #endif
251 |
252 | /* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */
253 | #if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__)
254 | #undef LTC_FAST
255 | #endif
256 |
257 | #ifdef LTC_FAST
258 | #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x))
259 | #ifdef ENDIAN_64BITWORD
260 | typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE;
261 | #else
262 | typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE;
263 | #endif
264 | #endif
265 |
266 | #if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
267 | #error You must specify a word size as well as endianess in tomcrypt_cfg.h
268 | #endif
269 |
270 | #if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
271 | #define ENDIAN_NEUTRAL
272 | #endif
273 |
274 | #if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD))
275 | #error Cannot be 32 and 64 bit words...
276 | #endif
277 |
278 | /* gcc 4.3 and up has a bswap builtin; detect it by gcc version.
279 | * clang also supports the bswap builtin, and although clang pretends
280 | * to be gcc (macro-wise, anyway), clang pretends to be a version
281 | * prior to gcc 4.3, so we can't detect bswap that way. Instead,
282 | * clang has a __has_builtin mechanism that can be used to check
283 | * for builtins:
284 | * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */
285 | #ifndef __has_builtin
286 | #define __has_builtin(x) 0
287 | #endif
288 | #if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \
289 | ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \
290 | (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)))
291 | #define LTC_HAVE_BSWAP_BUILTIN
292 | #endif
293 |
294 | #if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32))
295 | #define LTC_HAVE_ROTATE_BUILTIN
296 | #endif
297 |
298 | #if defined(__GNUC__)
299 | #define LTC_ALIGN(n) __attribute__((aligned(n)))
300 | #else
301 | #define LTC_ALIGN(n)
302 | #endif
303 |
304 | /* Choose Windows Vista as minimum Version if we're compiling with at least VS2019
305 | * This is done in order to test the bcrypt RNG and can still be overridden by the user. */
306 | #if defined(_MSC_VER) && _MSC_VER >= 1920
307 | # ifndef _WIN32_WINNT
308 | # define _WIN32_WINNT 0x0600
309 | # endif
310 | # ifndef WINVER
311 | # define WINVER 0x0600
312 | # endif
313 | #endif
314 |
315 | #if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && !defined(LTC_WIN32_BCRYPT)
316 | # define LTC_WIN32_BCRYPT
317 | #endif
318 |
319 | /* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code
320 | * before including `tomcrypt.h` to disable this functionality.
321 | */
322 | #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK)
323 | # define LTC_NULL_TERMINATED __attribute__((sentinel))
324 | #else
325 | # define LTC_NULL_TERMINATED
326 | #endif
327 |
328 | #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
329 | # define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s)))
330 | # define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s)
331 | # define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s)
332 | #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301)
333 | # define LTC_DEPRECATED(s) __attribute__((deprecated))
334 | # define LTC_DEPRECATED_PRAGMA(s)
335 | #elif defined(_MSC_VER) && _MSC_VER >= 1500
336 | /* supported since Visual Studio 2008 */
337 | # define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s))
338 | # define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s))
339 | #else
340 | # define LTC_DEPRECATED(s)
341 | # define LTC_DEPRECATED_PRAGMA(s)
342 | #endif
343 |
344 | #endif /* TOMCRYPT_CFG_H */
345 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_hash.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* ---- HASH FUNCTIONS ---- */
5 | #if defined(LTC_SHA3) || defined(LTC_KECCAK)
6 | struct sha3_state {
7 | ulong64 saved; /* the portion of the input message that we didn't consume yet */
8 | ulong64 s[25];
9 | unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */
10 | unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */
11 | unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */
12 | unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */
13 | unsigned short xof_flag;
14 | };
15 | #endif
16 |
17 | #ifdef LTC_SHA512
18 | struct sha512_state {
19 | ulong64 length, state[8];
20 | unsigned long curlen;
21 | unsigned char buf[128];
22 | };
23 | #endif
24 |
25 | #ifdef LTC_SHA256
26 | struct sha256_state {
27 | ulong64 length;
28 | ulong32 state[8], curlen;
29 | unsigned char buf[64];
30 | };
31 | #endif
32 |
33 | #ifdef LTC_SHA1
34 | struct sha1_state {
35 | ulong64 length;
36 | ulong32 state[5], curlen;
37 | unsigned char buf[64];
38 | };
39 | #endif
40 |
41 | #ifdef LTC_MD5
42 | struct md5_state {
43 | ulong64 length;
44 | ulong32 state[4], curlen;
45 | unsigned char buf[64];
46 | };
47 | #endif
48 |
49 | #ifdef LTC_MD4
50 | struct md4_state {
51 | ulong64 length;
52 | ulong32 state[4], curlen;
53 | unsigned char buf[64];
54 | };
55 | #endif
56 |
57 | #ifdef LTC_TIGER
58 | struct tiger_state {
59 | ulong64 state[3], length;
60 | unsigned long curlen;
61 | unsigned char buf[64];
62 | };
63 | #endif
64 |
65 | #ifdef LTC_MD2
66 | struct md2_state {
67 | unsigned char chksum[16], X[48], buf[16];
68 | unsigned long curlen;
69 | };
70 | #endif
71 |
72 | #ifdef LTC_RIPEMD128
73 | struct rmd128_state {
74 | ulong64 length;
75 | unsigned char buf[64];
76 | ulong32 curlen, state[4];
77 | };
78 | #endif
79 |
80 | #ifdef LTC_RIPEMD160
81 | struct rmd160_state {
82 | ulong64 length;
83 | unsigned char buf[64];
84 | ulong32 curlen, state[5];
85 | };
86 | #endif
87 |
88 | #ifdef LTC_RIPEMD256
89 | struct rmd256_state {
90 | ulong64 length;
91 | unsigned char buf[64];
92 | ulong32 curlen, state[8];
93 | };
94 | #endif
95 |
96 | #ifdef LTC_RIPEMD320
97 | struct rmd320_state {
98 | ulong64 length;
99 | unsigned char buf[64];
100 | ulong32 curlen, state[10];
101 | };
102 | #endif
103 |
104 | #ifdef LTC_WHIRLPOOL
105 | struct whirlpool_state {
106 | ulong64 length, state[8];
107 | unsigned char buf[64];
108 | ulong32 curlen;
109 | };
110 | #endif
111 |
112 | #ifdef LTC_CHC_HASH
113 | struct chc_state {
114 | ulong64 length;
115 | unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
116 | ulong32 curlen;
117 | };
118 | #endif
119 |
120 | #ifdef LTC_BLAKE2S
121 | struct blake2s_state {
122 | ulong32 h[8];
123 | ulong32 t[2];
124 | ulong32 f[2];
125 | unsigned char buf[64];
126 | unsigned long curlen;
127 | unsigned long outlen;
128 | unsigned char last_node;
129 | };
130 | #endif
131 |
132 | #ifdef LTC_BLAKE2B
133 | struct blake2b_state {
134 | ulong64 h[8];
135 | ulong64 t[2];
136 | ulong64 f[2];
137 | unsigned char buf[128];
138 | unsigned long curlen;
139 | unsigned long outlen;
140 | unsigned char last_node;
141 | };
142 | #endif
143 |
144 | typedef union Hash_state {
145 | char dummy[1];
146 | #ifdef LTC_CHC_HASH
147 | struct chc_state chc;
148 | #endif
149 | #ifdef LTC_WHIRLPOOL
150 | struct whirlpool_state whirlpool;
151 | #endif
152 | #if defined(LTC_SHA3) || defined(LTC_KECCAK)
153 | struct sha3_state sha3;
154 | #endif
155 | #ifdef LTC_SHA512
156 | struct sha512_state sha512;
157 | #endif
158 | #ifdef LTC_SHA256
159 | struct sha256_state sha256;
160 | #endif
161 | #ifdef LTC_SHA1
162 | struct sha1_state sha1;
163 | #endif
164 | #ifdef LTC_MD5
165 | struct md5_state md5;
166 | #endif
167 | #ifdef LTC_MD4
168 | struct md4_state md4;
169 | #endif
170 | #ifdef LTC_MD2
171 | struct md2_state md2;
172 | #endif
173 | #ifdef LTC_TIGER
174 | struct tiger_state tiger;
175 | #endif
176 | #ifdef LTC_RIPEMD128
177 | struct rmd128_state rmd128;
178 | #endif
179 | #ifdef LTC_RIPEMD160
180 | struct rmd160_state rmd160;
181 | #endif
182 | #ifdef LTC_RIPEMD256
183 | struct rmd256_state rmd256;
184 | #endif
185 | #ifdef LTC_RIPEMD320
186 | struct rmd320_state rmd320;
187 | #endif
188 | #ifdef LTC_BLAKE2S
189 | struct blake2s_state blake2s;
190 | #endif
191 | #ifdef LTC_BLAKE2B
192 | struct blake2b_state blake2b;
193 | #endif
194 |
195 | void *data;
196 | } hash_state;
197 |
198 | /** hash descriptor */
199 | extern struct ltc_hash_descriptor {
200 | /** name of hash */
201 | const char *name;
202 | /** internal ID */
203 | unsigned char ID;
204 | /** Size of digest in octets */
205 | unsigned long hashsize;
206 | /** Input block size in octets */
207 | unsigned long blocksize;
208 | /** ASN.1 OID */
209 | unsigned long OID[16];
210 | /** Length of DER encoding */
211 | unsigned long OIDlen;
212 |
213 | /** Init a hash state
214 | @param hash The hash to initialize
215 | @return CRYPT_OK if successful
216 | */
217 | int (*init)(hash_state *hash);
218 | /** Process a block of data
219 | @param hash The hash state
220 | @param in The data to hash
221 | @param inlen The length of the data (octets)
222 | @return CRYPT_OK if successful
223 | */
224 | int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
225 | /** Produce the digest and store it
226 | @param hash The hash state
227 | @param out [out] The destination of the digest
228 | @return CRYPT_OK if successful
229 | */
230 | int (*done)(hash_state *hash, unsigned char *out);
231 | /** Self-test
232 | @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
233 | */
234 | int (*test)(void);
235 |
236 | /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
237 | int (*hmac_block)(const unsigned char *key, unsigned long keylen,
238 | const unsigned char *in, unsigned long inlen,
239 | unsigned char *out, unsigned long *outlen);
240 |
241 | } hash_descriptor[];
242 |
243 | #ifdef LTC_CHC_HASH
244 | int chc_register(int cipher);
245 | int chc_init(hash_state * md);
246 | int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
247 | int chc_done(hash_state * md, unsigned char *out);
248 | int chc_test(void);
249 | extern const struct ltc_hash_descriptor chc_desc;
250 | #endif
251 |
252 | #ifdef LTC_WHIRLPOOL
253 | int whirlpool_init(hash_state * md);
254 | int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
255 | int whirlpool_done(hash_state * md, unsigned char *out);
256 | int whirlpool_test(void);
257 | extern const struct ltc_hash_descriptor whirlpool_desc;
258 | #endif
259 |
260 | #if defined(LTC_SHA3) || defined(LTC_KECCAK)
261 | /* sha3_NNN_init are shared by SHA3 and KECCAK */
262 | int sha3_512_init(hash_state * md);
263 | int sha3_384_init(hash_state * md);
264 | int sha3_256_init(hash_state * md);
265 | int sha3_224_init(hash_state * md);
266 | /* sha3_process is the same for all variants of SHA3 + KECCAK */
267 | int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
268 | #endif
269 |
270 | #ifdef LTC_SHA3
271 | int sha3_512_test(void);
272 | extern const struct ltc_hash_descriptor sha3_512_desc;
273 | int sha3_384_test(void);
274 | extern const struct ltc_hash_descriptor sha3_384_desc;
275 | int sha3_256_test(void);
276 | extern const struct ltc_hash_descriptor sha3_256_desc;
277 | int sha3_224_test(void);
278 | extern const struct ltc_hash_descriptor sha3_224_desc;
279 | int sha3_done(hash_state *md, unsigned char *out);
280 | /* SHAKE128 + SHAKE256 */
281 | int sha3_shake_init(hash_state *md, int num);
282 | #define sha3_shake_process(a,b,c) sha3_process(a,b,c)
283 | int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen);
284 | int sha3_shake_test(void);
285 | int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen);
286 | #endif
287 |
288 | #ifdef LTC_KECCAK
289 | #define keccak_512_init(a) sha3_512_init(a)
290 | #define keccak_384_init(a) sha3_384_init(a)
291 | #define keccak_256_init(a) sha3_256_init(a)
292 | #define keccak_224_init(a) sha3_224_init(a)
293 | #define keccak_process(a,b,c) sha3_process(a,b,c)
294 | extern const struct ltc_hash_descriptor keccak_512_desc;
295 | int keccak_512_test(void);
296 | extern const struct ltc_hash_descriptor keccak_384_desc;
297 | int keccak_384_test(void);
298 | extern const struct ltc_hash_descriptor keccak_256_desc;
299 | int keccak_256_test(void);
300 | extern const struct ltc_hash_descriptor keccak_224_desc;
301 | int keccak_224_test(void);
302 | int keccak_done(hash_state *md, unsigned char *out);
303 | #endif
304 |
305 | #ifdef LTC_SHA512
306 | int sha512_init(hash_state * md);
307 | int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
308 | int sha512_done(hash_state * md, unsigned char *out);
309 | int sha512_test(void);
310 | extern const struct ltc_hash_descriptor sha512_desc;
311 | #endif
312 |
313 | #ifdef LTC_SHA384
314 | #ifndef LTC_SHA512
315 | #error LTC_SHA512 is required for LTC_SHA384
316 | #endif
317 | int sha384_init(hash_state * md);
318 | #define sha384_process sha512_process
319 | int sha384_done(hash_state * md, unsigned char *out);
320 | int sha384_test(void);
321 | extern const struct ltc_hash_descriptor sha384_desc;
322 | #endif
323 |
324 | #ifdef LTC_SHA512_256
325 | #ifndef LTC_SHA512
326 | #error LTC_SHA512 is required for LTC_SHA512_256
327 | #endif
328 | int sha512_256_init(hash_state * md);
329 | #define sha512_256_process sha512_process
330 | int sha512_256_done(hash_state * md, unsigned char *out);
331 | int sha512_256_test(void);
332 | extern const struct ltc_hash_descriptor sha512_256_desc;
333 | #endif
334 |
335 | #ifdef LTC_SHA512_224
336 | #ifndef LTC_SHA512
337 | #error LTC_SHA512 is required for LTC_SHA512_224
338 | #endif
339 | int sha512_224_init(hash_state * md);
340 | #define sha512_224_process sha512_process
341 | int sha512_224_done(hash_state * md, unsigned char *out);
342 | int sha512_224_test(void);
343 | extern const struct ltc_hash_descriptor sha512_224_desc;
344 | #endif
345 |
346 | #ifdef LTC_SHA256
347 | int sha256_init(hash_state * md);
348 | int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
349 | int sha256_done(hash_state * md, unsigned char *out);
350 | int sha256_test(void);
351 | extern const struct ltc_hash_descriptor sha256_desc;
352 |
353 | #ifdef LTC_SHA224
354 | #ifndef LTC_SHA256
355 | #error LTC_SHA256 is required for LTC_SHA224
356 | #endif
357 | int sha224_init(hash_state * md);
358 | #define sha224_process sha256_process
359 | int sha224_done(hash_state * md, unsigned char *out);
360 | int sha224_test(void);
361 | extern const struct ltc_hash_descriptor sha224_desc;
362 | #endif
363 | #endif
364 |
365 | #ifdef LTC_SHA1
366 | int sha1_init(hash_state * md);
367 | int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
368 | int sha1_done(hash_state * md, unsigned char *out);
369 | int sha1_test(void);
370 | extern const struct ltc_hash_descriptor sha1_desc;
371 | #endif
372 |
373 | #ifdef LTC_BLAKE2S
374 | extern const struct ltc_hash_descriptor blake2s_256_desc;
375 | int blake2s_256_init(hash_state * md);
376 | int blake2s_256_test(void);
377 |
378 | extern const struct ltc_hash_descriptor blake2s_224_desc;
379 | int blake2s_224_init(hash_state * md);
380 | int blake2s_224_test(void);
381 |
382 | extern const struct ltc_hash_descriptor blake2s_160_desc;
383 | int blake2s_160_init(hash_state * md);
384 | int blake2s_160_test(void);
385 |
386 | extern const struct ltc_hash_descriptor blake2s_128_desc;
387 | int blake2s_128_init(hash_state * md);
388 | int blake2s_128_test(void);
389 |
390 | int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
391 | int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen);
392 | int blake2s_done(hash_state * md, unsigned char *out);
393 | #endif
394 |
395 | #ifdef LTC_BLAKE2B
396 | extern const struct ltc_hash_descriptor blake2b_512_desc;
397 | int blake2b_512_init(hash_state * md);
398 | int blake2b_512_test(void);
399 |
400 | extern const struct ltc_hash_descriptor blake2b_384_desc;
401 | int blake2b_384_init(hash_state * md);
402 | int blake2b_384_test(void);
403 |
404 | extern const struct ltc_hash_descriptor blake2b_256_desc;
405 | int blake2b_256_init(hash_state * md);
406 | int blake2b_256_test(void);
407 |
408 | extern const struct ltc_hash_descriptor blake2b_160_desc;
409 | int blake2b_160_init(hash_state * md);
410 | int blake2b_160_test(void);
411 |
412 | int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen);
413 | int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen);
414 | int blake2b_done(hash_state * md, unsigned char *out);
415 | #endif
416 |
417 | #ifdef LTC_MD5
418 | int md5_init(hash_state * md);
419 | int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
420 | int md5_done(hash_state * md, unsigned char *out);
421 | int md5_test(void);
422 | extern const struct ltc_hash_descriptor md5_desc;
423 | #endif
424 |
425 | #ifdef LTC_MD4
426 | int md4_init(hash_state * md);
427 | int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
428 | int md4_done(hash_state * md, unsigned char *out);
429 | int md4_test(void);
430 | extern const struct ltc_hash_descriptor md4_desc;
431 | #endif
432 |
433 | #ifdef LTC_MD2
434 | int md2_init(hash_state * md);
435 | int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
436 | int md2_done(hash_state * md, unsigned char *out);
437 | int md2_test(void);
438 | extern const struct ltc_hash_descriptor md2_desc;
439 | #endif
440 |
441 | #ifdef LTC_TIGER
442 | int tiger_init(hash_state * md);
443 | int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
444 | int tiger_done(hash_state * md, unsigned char *out);
445 | int tiger_test(void);
446 | extern const struct ltc_hash_descriptor tiger_desc;
447 | #endif
448 |
449 | #ifdef LTC_RIPEMD128
450 | int rmd128_init(hash_state * md);
451 | int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
452 | int rmd128_done(hash_state * md, unsigned char *out);
453 | int rmd128_test(void);
454 | extern const struct ltc_hash_descriptor rmd128_desc;
455 | #endif
456 |
457 | #ifdef LTC_RIPEMD160
458 | int rmd160_init(hash_state * md);
459 | int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
460 | int rmd160_done(hash_state * md, unsigned char *out);
461 | int rmd160_test(void);
462 | extern const struct ltc_hash_descriptor rmd160_desc;
463 | #endif
464 |
465 | #ifdef LTC_RIPEMD256
466 | int rmd256_init(hash_state * md);
467 | int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
468 | int rmd256_done(hash_state * md, unsigned char *out);
469 | int rmd256_test(void);
470 | extern const struct ltc_hash_descriptor rmd256_desc;
471 | #endif
472 |
473 | #ifdef LTC_RIPEMD320
474 | int rmd320_init(hash_state * md);
475 | int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
476 | int rmd320_done(hash_state * md, unsigned char *out);
477 | int rmd320_test(void);
478 | extern const struct ltc_hash_descriptor rmd320_desc;
479 | #endif
480 |
481 |
482 | int find_hash(const char *name);
483 | int find_hash_id(unsigned char ID);
484 | int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
485 | int find_hash_any(const char *name, int digestlen);
486 | int register_hash(const struct ltc_hash_descriptor *hash);
487 | int unregister_hash(const struct ltc_hash_descriptor *hash);
488 | int register_all_hashes(void);
489 | int hash_is_valid(int idx);
490 |
491 | LTC_MUTEX_PROTO(ltc_hash_mutex)
492 |
493 | int hash_memory(int hash,
494 | const unsigned char *in, unsigned long inlen,
495 | unsigned char *out, unsigned long *outlen);
496 | int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
497 | const unsigned char *in, unsigned long inlen, ...)
498 | LTC_NULL_TERMINATED;
499 |
500 | #ifndef LTC_NO_FILE
501 | int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
502 | int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
503 | #endif
504 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_macros.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 |
5 | #define LTC_TMPVAR__(n, l) n ## l
6 | #define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l)
7 | #define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__)
8 |
9 | /* ---- HELPER MACROS ---- */
10 | #ifdef ENDIAN_NEUTRAL
11 |
12 | #define STORE32L(x, y) \
13 | do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
14 | (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
15 |
16 | #define LOAD32L(x, y) \
17 | do { x = ((ulong32)((y)[3] & 255)<<24) | \
18 | ((ulong32)((y)[2] & 255)<<16) | \
19 | ((ulong32)((y)[1] & 255)<<8) | \
20 | ((ulong32)((y)[0] & 255)); } while(0)
21 |
22 | #define STORE64L(x, y) \
23 | do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
24 | (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
25 | (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
26 | (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
27 |
28 | #define LOAD64L(x, y) \
29 | do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
30 | (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
31 | (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
32 | (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
33 |
34 | #define STORE32H(x, y) \
35 | do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
36 | (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
37 |
38 | #define LOAD32H(x, y) \
39 | do { x = ((ulong32)((y)[0] & 255)<<24) | \
40 | ((ulong32)((y)[1] & 255)<<16) | \
41 | ((ulong32)((y)[2] & 255)<<8) | \
42 | ((ulong32)((y)[3] & 255)); } while(0)
43 |
44 | #define STORE64H(x, y) \
45 | do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
46 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
47 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
48 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
49 |
50 | #define LOAD64H(x, y) \
51 | do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
52 | (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
53 | (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
54 | (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
55 |
56 |
57 | #elif defined(ENDIAN_LITTLE)
58 |
59 | #ifdef LTC_HAVE_BSWAP_BUILTIN
60 |
61 | #define STORE32H(x, y) \
62 | do { ulong32 ttt = __builtin_bswap32 ((x)); \
63 | XMEMCPY ((y), &ttt, 4); } while(0)
64 |
65 | #define LOAD32H(x, y) \
66 | do { XMEMCPY (&(x), (y), 4); \
67 | (x) = __builtin_bswap32 ((x)); } while(0)
68 |
69 | #elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
70 |
71 | #define STORE32H(x, y) \
72 | asm __volatile__ ( \
73 | "bswapl %0 \n\t" \
74 | "movl %0,(%1)\n\t" \
75 | "bswapl %0 \n\t" \
76 | ::"r"(x), "r"(y): "memory");
77 |
78 | #define LOAD32H(x, y) \
79 | asm __volatile__ ( \
80 | "movl (%1),%0\n\t" \
81 | "bswapl %0\n\t" \
82 | :"=r"(x): "r"(y): "memory");
83 |
84 | #else
85 |
86 | #define STORE32H(x, y) \
87 | do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
88 | (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
89 |
90 | #define LOAD32H(x, y) \
91 | do { x = ((ulong32)((y)[0] & 255)<<24) | \
92 | ((ulong32)((y)[1] & 255)<<16) | \
93 | ((ulong32)((y)[2] & 255)<<8) | \
94 | ((ulong32)((y)[3] & 255)); } while(0)
95 |
96 | #endif
97 |
98 | #ifdef LTC_HAVE_BSWAP_BUILTIN
99 |
100 | #define STORE64H(x, y) \
101 | do { ulong64 ttt = __builtin_bswap64 ((x)); \
102 | XMEMCPY ((y), &ttt, 8); } while(0)
103 |
104 | #define LOAD64H(x, y) \
105 | do { XMEMCPY (&(x), (y), 8); \
106 | (x) = __builtin_bswap64 ((x)); } while(0)
107 |
108 | /* x86_64 processor */
109 | #elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
110 |
111 | #define STORE64H(x, y) \
112 | asm __volatile__ ( \
113 | "bswapq %0 \n\t" \
114 | "movq %0,(%1)\n\t" \
115 | "bswapq %0 \n\t" \
116 | ::"r"(x), "r"(y): "memory");
117 |
118 | #define LOAD64H(x, y) \
119 | asm __volatile__ ( \
120 | "movq (%1),%0\n\t" \
121 | "bswapq %0\n\t" \
122 | :"=r"(x): "r"(y): "memory");
123 |
124 | #else
125 |
126 | #define STORE64H(x, y) \
127 | do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
128 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
129 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
130 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
131 |
132 | #define LOAD64H(x, y) \
133 | do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
134 | (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
135 | (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
136 | (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0)
137 |
138 | #endif
139 |
140 | #ifdef ENDIAN_32BITWORD
141 |
142 | #define STORE32L(x, y) \
143 | do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
144 |
145 | #define LOAD32L(x, y) \
146 | do { XMEMCPY(&(x), y, 4); } while(0)
147 |
148 | #define STORE64L(x, y) \
149 | do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
150 | (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
151 | (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
152 | (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
153 |
154 | #define LOAD64L(x, y) \
155 | do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
156 | (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
157 | (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
158 | (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
159 |
160 | #else /* 64-bit words then */
161 |
162 | #define STORE32L(x, y) \
163 | do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
164 |
165 | #define LOAD32L(x, y) \
166 | do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
167 |
168 | #define STORE64L(x, y) \
169 | do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0)
170 |
171 | #define LOAD64L(x, y) \
172 | do { XMEMCPY(&(x), y, 8); } while(0)
173 |
174 | #endif /* ENDIAN_64BITWORD */
175 |
176 | #elif defined(ENDIAN_BIG)
177 |
178 | #define STORE32L(x, y) \
179 | do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
180 | (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
181 |
182 | #define LOAD32L(x, y) \
183 | do { x = ((ulong32)((y)[3] & 255)<<24) | \
184 | ((ulong32)((y)[2] & 255)<<16) | \
185 | ((ulong32)((y)[1] & 255)<<8) | \
186 | ((ulong32)((y)[0] & 255)); } while(0)
187 |
188 | #define STORE64L(x, y) \
189 | do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
190 | (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
191 | (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
192 | (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
193 |
194 | #define LOAD64L(x, y) \
195 | do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
196 | (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
197 | (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
198 | (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0)
199 |
200 | #ifdef ENDIAN_32BITWORD
201 |
202 | #define STORE32H(x, y) \
203 | do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
204 |
205 | #define LOAD32H(x, y) \
206 | do { XMEMCPY(&(x), y, 4); } while(0)
207 |
208 | #define STORE64H(x, y) \
209 | do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
210 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
211 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
212 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
213 |
214 | #define LOAD64H(x, y) \
215 | do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
216 | (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
217 | (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
218 | (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0)
219 |
220 | #else /* 64-bit words then */
221 |
222 | #define STORE32H(x, y) \
223 | do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0)
224 |
225 | #define LOAD32H(x, y) \
226 | do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0)
227 |
228 | #define STORE64H(x, y) \
229 | do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0)
230 |
231 | #define LOAD64H(x, y) \
232 | do { XMEMCPY(&(x), y, 8); } while(0)
233 |
234 | #endif /* ENDIAN_64BITWORD */
235 | #endif /* ENDIAN_BIG */
236 |
237 | #define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
238 | ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
239 |
240 |
241 | /* 32-bit Rotates */
242 | #if defined(_MSC_VER)
243 | #define LTC_ROx_BUILTIN
244 |
245 | /* instrinsic rotate */
246 | #include
247 | #pragma intrinsic(_rotr,_rotl)
248 | #define ROR(x,n) _rotr(x,n)
249 | #define ROL(x,n) _rotl(x,n)
250 | #define RORc(x,n) ROR(x,n)
251 | #define ROLc(x,n) ROL(x,n)
252 |
253 | #elif defined(LTC_HAVE_ROTATE_BUILTIN)
254 | #define LTC_ROx_BUILTIN
255 |
256 | #define ROR(x,n) __builtin_rotateright32(x,n)
257 | #define ROL(x,n) __builtin_rotateleft32(x,n)
258 | #define ROLc(x,n) ROL(x,n)
259 | #define RORc(x,n) ROR(x,n)
260 |
261 | #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
262 | #define LTC_ROx_ASM
263 |
264 | static inline ulong32 ROL(ulong32 word, int i)
265 | {
266 | asm ("roll %%cl,%0"
267 | :"=r" (word)
268 | :"0" (word),"c" (i));
269 | return word;
270 | }
271 |
272 | static inline ulong32 ROR(ulong32 word, int i)
273 | {
274 | asm ("rorl %%cl,%0"
275 | :"=r" (word)
276 | :"0" (word),"c" (i));
277 | return word;
278 | }
279 |
280 | #ifndef LTC_NO_ROLC
281 |
282 | #define ROLc(word,i) ({ \
283 | ulong32 LTC_TMPVAR(ROLc) = (word); \
284 | __asm__ ("roll %2, %0" : \
285 | "=r" (LTC_TMPVAR(ROLc)) : \
286 | "0" (LTC_TMPVAR(ROLc)), \
287 | "I" (i)); \
288 | LTC_TMPVAR(ROLc); \
289 | })
290 | #define RORc(word,i) ({ \
291 | ulong32 LTC_TMPVAR(RORc) = (word); \
292 | __asm__ ("rorl %2, %0" : \
293 | "=r" (LTC_TMPVAR(RORc)) : \
294 | "0" (LTC_TMPVAR(RORc)), \
295 | "I" (i)); \
296 | LTC_TMPVAR(RORc); \
297 | })
298 |
299 | #else
300 |
301 | #define ROLc ROL
302 | #define RORc ROR
303 |
304 | #endif
305 |
306 | #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
307 | #define LTC_ROx_ASM
308 |
309 | static inline ulong32 ROL(ulong32 word, int i)
310 | {
311 | asm ("rotlw %0,%0,%2"
312 | :"=r" (word)
313 | :"0" (word),"r" (i));
314 | return word;
315 | }
316 |
317 | static inline ulong32 ROR(ulong32 word, int i)
318 | {
319 | asm ("rotlw %0,%0,%2"
320 | :"=r" (word)
321 | :"0" (word),"r" (32-i));
322 | return word;
323 | }
324 |
325 | #ifndef LTC_NO_ROLC
326 |
327 | static inline ulong32 ROLc(ulong32 word, const int i)
328 | {
329 | asm ("rotlwi %0,%0,%2"
330 | :"=r" (word)
331 | :"0" (word),"I" (i));
332 | return word;
333 | }
334 |
335 | static inline ulong32 RORc(ulong32 word, const int i)
336 | {
337 | asm ("rotrwi %0,%0,%2"
338 | :"=r" (word)
339 | :"0" (word),"I" (i));
340 | return word;
341 | }
342 |
343 | #else
344 |
345 | #define ROLc ROL
346 | #define RORc ROR
347 |
348 | #endif
349 |
350 |
351 | #else
352 |
353 | /* rotates the hard way */
354 | #define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
355 | #define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
356 | #define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
357 | #define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL)
358 |
359 | #endif
360 |
361 |
362 | /* 64-bit Rotates */
363 | #if defined(_MSC_VER)
364 |
365 | /* instrinsic rotate */
366 | #include
367 | #pragma intrinsic(_rotr64,_rotr64)
368 | #define ROR64(x,n) _rotr64(x,n)
369 | #define ROL64(x,n) _rotl64(x,n)
370 | #define ROR64c(x,n) ROR64(x,n)
371 | #define ROL64c(x,n) ROL64(x,n)
372 |
373 | #elif defined(LTC_HAVE_ROTATE_BUILTIN)
374 |
375 | #define ROR64(x,n) __builtin_rotateright64(x,n)
376 | #define ROL64(x,n) __builtin_rotateleft64(x,n)
377 | #define ROR64c(x,n) ROR64(x,n)
378 | #define ROL64c(x,n) ROL64(x,n)
379 |
380 | #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
381 |
382 | static inline ulong64 ROL64(ulong64 word, int i)
383 | {
384 | asm("rolq %%cl,%0"
385 | :"=r" (word)
386 | :"0" (word),"c" (i));
387 | return word;
388 | }
389 |
390 | static inline ulong64 ROR64(ulong64 word, int i)
391 | {
392 | asm("rorq %%cl,%0"
393 | :"=r" (word)
394 | :"0" (word),"c" (i));
395 | return word;
396 | }
397 |
398 | #ifndef LTC_NO_ROLC
399 |
400 | #define ROL64c(word,i) ({ \
401 | ulong64 LTC_TMPVAR(ROL64c) = word; \
402 | __asm__ ("rolq %2, %0" : \
403 | "=r" (LTC_TMPVAR(ROL64c)) : \
404 | "0" (LTC_TMPVAR(ROL64c)), \
405 | "J" (i)); \
406 | LTC_TMPVAR(ROL64c); \
407 | })
408 | #define ROR64c(word,i) ({ \
409 | ulong64 LTC_TMPVAR(ROR64c) = word; \
410 | __asm__ ("rorq %2, %0" : \
411 | "=r" (LTC_TMPVAR(ROR64c)) : \
412 | "0" (LTC_TMPVAR(ROR64c)), \
413 | "J" (i)); \
414 | LTC_TMPVAR(ROR64c); \
415 | })
416 |
417 | #else /* LTC_NO_ROLC */
418 |
419 | #define ROL64c ROL64
420 | #define ROR64c ROR64
421 |
422 | #endif
423 |
424 | #else /* Not x86_64 */
425 |
426 | #define ROL64(x, y) \
427 | ( (((x)<<((ulong64)(y)&63)) | \
428 | (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
429 |
430 | #define ROR64(x, y) \
431 | ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
432 | ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
433 |
434 | #define ROL64c(x, y) \
435 | ( (((x)<<((ulong64)(y)&63)) | \
436 | (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
437 |
438 | #define ROR64c(x, y) \
439 | ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
440 | ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF))
441 |
442 | #endif
443 |
444 | #ifndef MAX
445 | #define MAX(x, y) ( ((x)>(y))?(x):(y) )
446 | #endif
447 |
448 | #ifndef MIN
449 | #define MIN(x, y) ( ((x)<(y))?(x):(y) )
450 | #endif
451 |
452 | #ifndef LTC_UNUSED_PARAM
453 | #define LTC_UNUSED_PARAM(x) (void)(x)
454 | #endif
455 |
456 | /* there is no snprintf before Visual C++ 2015 */
457 | #if defined(_MSC_VER) && _MSC_VER < 1900
458 | #define snprintf _snprintf
459 | #endif
460 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_misc.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* ---- LTC_BASE64 Routines ---- */
5 | #ifdef LTC_BASE64
6 | int base64_encode(const unsigned char *in, unsigned long inlen,
7 | char *out, unsigned long *outlen);
8 |
9 | int base64_decode(const char *in, unsigned long inlen,
10 | unsigned char *out, unsigned long *outlen);
11 | int base64_strict_decode(const char *in, unsigned long inlen,
12 | unsigned char *out, unsigned long *outlen);
13 | int base64_sane_decode(const char *in, unsigned long inlen,
14 | unsigned char *out, unsigned long *outlen);
15 | #endif
16 |
17 | #ifdef LTC_BASE64_URL
18 | int base64url_encode(const unsigned char *in, unsigned long inlen,
19 | char *out, unsigned long *outlen);
20 | int base64url_strict_encode(const unsigned char *in, unsigned long inlen,
21 | char *out, unsigned long *outlen);
22 |
23 | int base64url_decode(const char *in, unsigned long inlen,
24 | unsigned char *out, unsigned long *outlen);
25 | int base64url_strict_decode(const char *in, unsigned long inlen,
26 | unsigned char *out, unsigned long *outlen);
27 | int base64url_sane_decode(const char *in, unsigned long inlen,
28 | unsigned char *out, unsigned long *outlen);
29 | #endif
30 |
31 | /* ---- BASE32 Routines ---- */
32 | #ifdef LTC_BASE32
33 | typedef enum {
34 | BASE32_RFC4648 = 0,
35 | BASE32_BASE32HEX = 1,
36 | BASE32_ZBASE32 = 2,
37 | BASE32_CROCKFORD = 3
38 | } base32_alphabet;
39 | int base32_encode(const unsigned char *in, unsigned long inlen,
40 | char *out, unsigned long *outlen,
41 | base32_alphabet id);
42 | int base32_decode(const char *in, unsigned long inlen,
43 | unsigned char *out, unsigned long *outlen,
44 | base32_alphabet id);
45 | #endif
46 |
47 | /* ---- BASE16 Routines ---- */
48 | #ifdef LTC_BASE16
49 | int base16_encode(const unsigned char *in, unsigned long inlen,
50 | char *out, unsigned long *outlen,
51 | unsigned int options);
52 | int base16_decode(const char *in, unsigned long inlen,
53 | unsigned char *out, unsigned long *outlen);
54 | #endif
55 |
56 | #ifdef LTC_BCRYPT
57 | int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
58 | const unsigned char *salt, unsigned long salt_len,
59 | unsigned int rounds, int hash_idx,
60 | unsigned char *out, unsigned long *outlen);
61 | #endif
62 |
63 | /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */
64 | #ifdef LTC_HKDF
65 |
66 | int hkdf_test(void);
67 |
68 | int hkdf_extract(int hash_idx,
69 | const unsigned char *salt, unsigned long saltlen,
70 | const unsigned char *in, unsigned long inlen,
71 | unsigned char *out, unsigned long *outlen);
72 |
73 | int hkdf_expand(int hash_idx,
74 | const unsigned char *info, unsigned long infolen,
75 | const unsigned char *in, unsigned long inlen,
76 | unsigned char *out, unsigned long outlen);
77 |
78 | int hkdf(int hash_idx,
79 | const unsigned char *salt, unsigned long saltlen,
80 | const unsigned char *info, unsigned long infolen,
81 | const unsigned char *in, unsigned long inlen,
82 | unsigned char *out, unsigned long outlen);
83 |
84 | #endif /* LTC_HKDF */
85 |
86 | /* ---- MEM routines ---- */
87 | int mem_neq(const void *a, const void *b, size_t len);
88 | void zeromem(volatile void *out, size_t outlen);
89 | void burn_stack(unsigned long len);
90 |
91 | const char *error_to_string(int err);
92 |
93 | extern const char *crypt_build_settings;
94 |
95 | /* ---- HMM ---- */
96 | int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED;
97 |
98 | /* ---- Dynamic language support ---- */
99 | int crypt_get_constant(const char* namein, int *valueout);
100 | int crypt_list_all_constants(char *names_list, unsigned int *names_list_size);
101 |
102 | int crypt_get_size(const char* namein, unsigned int *sizeout);
103 | int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size);
104 |
105 | #ifdef LTM_DESC
106 | LTC_DEPRECATED(crypt_mp_init) void init_LTM(void);
107 | #endif
108 | #ifdef TFM_DESC
109 | LTC_DEPRECATED(crypt_mp_init) void init_TFM(void);
110 | #endif
111 | #ifdef GMP_DESC
112 | LTC_DEPRECATED(crypt_mp_init) void init_GMP(void);
113 | #endif
114 | int crypt_mp_init(const char* mpi);
115 |
116 | #ifdef LTC_ADLER32
117 | typedef struct adler32_state_s
118 | {
119 | unsigned short s[2];
120 | } adler32_state;
121 |
122 | void adler32_init(adler32_state *ctx);
123 | void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length);
124 | void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size);
125 | int adler32_test(void);
126 | #endif
127 |
128 | #ifdef LTC_CRC32
129 | typedef struct crc32_state_s
130 | {
131 | ulong32 crc;
132 | } crc32_state;
133 |
134 | void crc32_init(crc32_state *ctx);
135 | void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length);
136 | void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size);
137 | int crc32_test(void);
138 | #endif
139 |
140 |
141 | #ifdef LTC_PADDING
142 |
143 | enum padding_type {
144 | LTC_PAD_PKCS7 = 0x0000U,
145 | #ifdef LTC_RNG_GET_BYTES
146 | LTC_PAD_ISO_10126 = 0x1000U,
147 | #endif
148 | LTC_PAD_ANSI_X923 = 0x2000U,
149 | LTC_PAD_SSH = 0x3000U,
150 | /* The following padding modes don't contain the padding
151 | * length as last byte of the padding.
152 | */
153 | LTC_PAD_ONE_AND_ZERO = 0x8000U,
154 | LTC_PAD_ZERO = 0x9000U,
155 | LTC_PAD_ZERO_ALWAYS = 0xA000U,
156 | };
157 |
158 | int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode);
159 | int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode);
160 | #endif /* LTC_PADDING */
161 |
162 | #ifdef LTC_SSH
163 | typedef enum ssh_data_type_ {
164 | LTC_SSHDATA_EOL,
165 | LTC_SSHDATA_BYTE,
166 | LTC_SSHDATA_BOOLEAN,
167 | LTC_SSHDATA_UINT32,
168 | LTC_SSHDATA_UINT64,
169 | LTC_SSHDATA_STRING,
170 | LTC_SSHDATA_MPINT,
171 | LTC_SSHDATA_NAMELIST,
172 | } ssh_data_type;
173 |
174 | /* VA list handy helpers with tuples of */
175 | int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED;
176 | int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED;
177 | #endif /* LTC_SSH */
178 |
179 | int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which);
180 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_pkcs.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* PKCS Header Info */
5 |
6 | /* ===> PKCS #1 -- RSA Cryptography <=== */
7 | #ifdef LTC_PKCS_1
8 |
9 | enum ltc_pkcs_1_v1_5_blocks
10 | {
11 | LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */
12 | LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */
13 | };
14 |
15 | enum ltc_pkcs_1_paddings
16 | {
17 | LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
18 | LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */
19 | LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */
20 | LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */
21 | };
22 |
23 | int pkcs_1_mgf1( int hash_idx,
24 | const unsigned char *seed, unsigned long seedlen,
25 | unsigned char *mask, unsigned long masklen);
26 |
27 | int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
28 | int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
29 |
30 | /* *** v1.5 padding */
31 | int pkcs_1_v1_5_encode(const unsigned char *msg,
32 | unsigned long msglen,
33 | int block_type,
34 | unsigned long modulus_bitlen,
35 | prng_state *prng,
36 | int prng_idx,
37 | unsigned char *out,
38 | unsigned long *outlen);
39 |
40 | int pkcs_1_v1_5_decode(const unsigned char *msg,
41 | unsigned long msglen,
42 | int block_type,
43 | unsigned long modulus_bitlen,
44 | unsigned char *out,
45 | unsigned long *outlen,
46 | int *is_valid);
47 |
48 | /* *** v2.1 padding */
49 | int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
50 | const unsigned char *lparam, unsigned long lparamlen,
51 | unsigned long modulus_bitlen, prng_state *prng,
52 | int prng_idx,
53 | int mgf_hash, int lparam_hash,
54 | unsigned char *out, unsigned long *outlen);
55 |
56 | int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
57 | const unsigned char *lparam, unsigned long lparamlen,
58 | unsigned long modulus_bitlen,
59 | int mgf_hash, int lparam_hash,
60 | unsigned char *out, unsigned long *outlen,
61 | int *res);
62 |
63 | int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
64 | unsigned long saltlen, prng_state *prng,
65 | int prng_idx, int hash_idx,
66 | unsigned long modulus_bitlen,
67 | unsigned char *out, unsigned long *outlen);
68 |
69 | int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
70 | const unsigned char *sig, unsigned long siglen,
71 | unsigned long saltlen, int hash_idx,
72 | unsigned long modulus_bitlen, int *res);
73 |
74 | #endif /* LTC_PKCS_1 */
75 |
76 | /* ===> PKCS #5 -- Password Based Cryptography <=== */
77 | #ifdef LTC_PKCS_5
78 |
79 | /* Algorithm #1 (PBKDF1) */
80 | int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
81 | const unsigned char *salt,
82 | int iteration_count, int hash_idx,
83 | unsigned char *out, unsigned long *outlen);
84 |
85 | /* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys.
86 | Compatible with EVP_BytesToKey() */
87 | int pkcs_5_alg1_openssl(const unsigned char *password,
88 | unsigned long password_len,
89 | const unsigned char *salt,
90 | int iteration_count, int hash_idx,
91 | unsigned char *out, unsigned long *outlen);
92 |
93 | /* Algorithm #2 (PBKDF2) */
94 | int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
95 | const unsigned char *salt, unsigned long salt_len,
96 | int iteration_count, int hash_idx,
97 | unsigned char *out, unsigned long *outlen);
98 |
99 | int pkcs_5_test (void);
100 | #endif /* LTC_PKCS_5 */
101 |
102 |
--------------------------------------------------------------------------------
/Sources/SQLExt/sqlite/tomcrypt_prng.h:
--------------------------------------------------------------------------------
1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 | /* SPDX-License-Identifier: Unlicense */
3 |
4 | /* ---- PRNG Stuff ---- */
5 | #ifdef LTC_YARROW
6 | struct yarrow_prng {
7 | int cipher, hash;
8 | unsigned char pool[MAXBLOCKSIZE];
9 | symmetric_CTR ctr;
10 | };
11 | #endif
12 |
13 | #ifdef LTC_RC4
14 | struct rc4_prng {
15 | rc4_state s;
16 | };
17 | #endif
18 |
19 | #ifdef LTC_CHACHA20_PRNG
20 | struct chacha20_prng {
21 | chacha_state s; /* chacha state */
22 | unsigned char ent[40]; /* entropy buffer */
23 | unsigned long idx; /* entropy counter */
24 | };
25 | #endif
26 |
27 | #ifdef LTC_FORTUNA
28 | struct fortuna_prng {
29 | hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */
30 |
31 | symmetric_key skey;
32 |
33 | unsigned char K[32], /* the current key */
34 | IV[16]; /* IV for CTR mode */
35 |
36 | unsigned long pool_idx, /* current pool we will add to */
37 | pool0_len; /* length of 0'th pool */
38 | ulong64 wd;
39 | ulong64 reset_cnt; /* number of times we have reseeded */
40 | };
41 | #endif
42 |
43 | #ifdef LTC_SOBER128
44 | struct sober128_prng {
45 | sober128_state s; /* sober128 state */
46 | unsigned char ent[40]; /* entropy buffer */
47 | unsigned long idx; /* entropy counter */
48 | };
49 | #endif
50 |
51 | typedef struct {
52 | union {
53 | char dummy[1];
54 | #ifdef LTC_YARROW
55 | struct yarrow_prng yarrow;
56 | #endif
57 | #ifdef LTC_RC4
58 | struct rc4_prng rc4;
59 | #endif
60 | #ifdef LTC_CHACHA20_PRNG
61 | struct chacha20_prng chacha;
62 | #endif
63 | #ifdef LTC_FORTUNA
64 | struct fortuna_prng fortuna;
65 | #endif
66 | #ifdef LTC_SOBER128
67 | struct sober128_prng sober128;
68 | #endif
69 | } u;
70 | short ready; /* ready flag 0-1 */
71 | LTC_MUTEX_TYPE(lock) /* lock */
72 | } prng_state;
73 |
74 | /** PRNG descriptor */
75 | extern struct ltc_prng_descriptor {
76 | /** Name of the PRNG */
77 | const char *name;
78 | /** size in bytes of exported state */
79 | int export_size;
80 | /** Start a PRNG state
81 | @param prng [out] The state to initialize
82 | @return CRYPT_OK if successful
83 | */
84 | int (*start)(prng_state *prng);
85 | /** Add entropy to the PRNG
86 | @param in The entropy
87 | @param inlen Length of the entropy (octets)\
88 | @param prng The PRNG state
89 | @return CRYPT_OK if successful
90 | */
91 | int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
92 | /** Ready a PRNG state to read from
93 | @param prng The PRNG state to ready
94 | @return CRYPT_OK if successful
95 | */
96 | int (*ready)(prng_state *prng);
97 | /** Read from the PRNG
98 | @param out [out] Where to store the data
99 | @param outlen Length of data desired (octets)
100 | @param prng The PRNG state to read from
101 | @return Number of octets read
102 | */
103 | unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
104 | /** Terminate a PRNG state
105 | @param prng The PRNG state to terminate
106 | @return CRYPT_OK if successful
107 | */
108 | int (*done)(prng_state *prng);
109 | /** Export a PRNG state
110 | @param out [out] The destination for the state
111 | @param outlen [in/out] The max size and resulting size of the PRNG state
112 | @param prng The PRNG to export
113 | @return CRYPT_OK if successful
114 | */
115 | int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
116 | /** Import a PRNG state
117 | @param in The data to import
118 | @param inlen The length of the data to import (octets)
119 | @param prng The PRNG to initialize/import
120 | @return CRYPT_OK if successful
121 | */
122 | int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
123 | /** Self-test the PRNG
124 | @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
125 | */
126 | int (*test)(void);
127 | } prng_descriptor[];
128 |
129 | #ifdef LTC_YARROW
130 | int yarrow_start(prng_state *prng);
131 | int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
132 | int yarrow_ready(prng_state *prng);
133 | unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);
134 | int yarrow_done(prng_state *prng);
135 | int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
136 | int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
137 | int yarrow_test(void);
138 | extern const struct ltc_prng_descriptor yarrow_desc;
139 | #endif
140 |
141 | #ifdef LTC_FORTUNA
142 | int fortuna_start(prng_state *prng);
143 | int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
144 | int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng);
145 | int fortuna_ready(prng_state *prng);
146 | unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
147 | int fortuna_done(prng_state *prng);
148 | int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
149 | int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
150 | int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng);
151 | int fortuna_test(void);
152 | extern const struct ltc_prng_descriptor fortuna_desc;
153 | #endif
154 |
155 | #ifdef LTC_RC4
156 | int rc4_start(prng_state *prng);
157 | int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
158 | int rc4_ready(prng_state *prng);
159 | unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);
160 | int rc4_done(prng_state *prng);
161 | int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
162 | int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
163 | int rc4_test(void);
164 | extern const struct ltc_prng_descriptor rc4_desc;
165 | #endif
166 |
167 | #ifdef LTC_CHACHA20_PRNG
168 | int chacha20_prng_start(prng_state *prng);
169 | int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
170 | int chacha20_prng_ready(prng_state *prng);
171 | unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
172 | int chacha20_prng_done(prng_state *prng);
173 | int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
174 | int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
175 | int chacha20_prng_test(void);
176 | extern const struct ltc_prng_descriptor chacha20_prng_desc;
177 | #endif
178 |
179 | #ifdef LTC_SPRNG
180 | int sprng_start(prng_state *prng);
181 | int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
182 | int sprng_ready(prng_state *prng);
183 | unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
184 | int sprng_done(prng_state *prng);
185 | int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
186 | int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
187 | int sprng_test(void);
188 | extern const struct ltc_prng_descriptor sprng_desc;
189 | #endif
190 |
191 | #ifdef LTC_SOBER128
192 | int sober128_start(prng_state *prng);
193 | int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
194 | int sober128_ready(prng_state *prng);
195 | unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);
196 | int sober128_done(prng_state *prng);
197 | int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
198 | int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
199 | int sober128_test(void);
200 | extern const struct ltc_prng_descriptor sober128_desc;
201 | #endif
202 |
203 | int find_prng(const char *name);
204 | int register_prng(const struct ltc_prng_descriptor *prng);
205 | int unregister_prng(const struct ltc_prng_descriptor *prng);
206 | int register_all_prngs(void);
207 | int prng_is_valid(int idx);
208 | LTC_MUTEX_PROTO(ltc_prng_mutex)
209 |
210 | /* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
211 | * might not work on all platforms as planned
212 | */
213 | unsigned long rng_get_bytes(unsigned char *out,
214 | unsigned long outlen,
215 | void (*callback)(void));
216 |
217 | int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
218 |
219 | #ifdef LTC_PRNG_ENABLE_LTC_RNG
220 | extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen,
221 | void (*callback)(void));
222 | #endif
223 |
224 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/SQLContext.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | import Foundation
4 | import OSLog
5 | #if SKIP
6 | import SkipFFI
7 | #endif
8 |
9 | let logger: Logger = Logger(subsystem: "skip.sql", category: "SQL")
10 |
11 | /// A context for performing operations on a SQLite database.
12 | public final class SQLContext {
13 | /// The SQLite3 library to use.
14 | fileprivate let SQLite3: SQLiteLibrary
15 |
16 | /// The logging level for this context; SQL statements and warnings will be sent to this log.
17 | public var logLevel: OSLogType? = nil
18 |
19 | /// The pointer to the SQLite database.
20 | private let db: OpaquePointer
21 | private var closed = false
22 |
23 | /// The rowid of the most recent successful `INSERT` into a rowid table.
24 | public var lastInsertRowID: Int64 {
25 | SQLite3.sqlite3_last_insert_rowid(db)
26 | }
27 |
28 | /// The number of rows modified, inserted or deleted by the most recently completed INSERT, UPDATE or DELETE statement.
29 | public var changes: Int32 {
30 | SQLite3.sqlite3_changes(db)
31 | }
32 |
33 | /// The total number of rows inserted, modified or deleted by all [INSERT], [UPDATE] or [DELETE] statements completed since the database connection was opened, including those executed as part of triggers.
34 | public var totalChanges: Int32 {
35 | SQLite3.sqlite3_total_changes(db)
36 | }
37 |
38 | deinit {
39 | #if !SKIP
40 | #if DEBUG
41 | //assert(isClosed, "SQLContext must be closed before deinit")
42 | #endif
43 | #endif
44 | }
45 |
46 | /// Create an in-memory `SQLContext`.
47 | public init(configuration: SQLiteConfiguration = .platform) {
48 | // try! because creating an in-memory context should never fail
49 | self.SQLite3 = configuration.library
50 | self.db = try! Self.connect(path: ":memory:", configuration: configuration)!
51 | }
52 |
53 | /// Create a new `SQLContext` with the given options, either in-memory (the default), or on a file path.
54 | /// - Parameters:
55 | /// - path: The path to the local file, or ":memory:" for an in-memory database.
56 | /// - flags: The flags to use to open the database.
57 | public init(path: String, flags: OpenFlags? = nil, logLevel: OSLogType? = nil, configuration: SQLiteConfiguration = .platform) throws {
58 | self.logLevel = logLevel
59 | self.SQLite3 = configuration.library
60 | self.db = try Self.connect(path: path, flags: flags, configuration: configuration)!
61 |
62 | if let logLevel = logLevel {
63 | logger.log(level: logLevel, "opened database: \(path)")
64 | }
65 | }
66 |
67 | private static func connect(path: String, flags: OpenFlags? = nil, configuration: SQLiteConfiguration = .platform) throws -> OpaquePointer? {
68 | var db: OpaquePointer? = nil
69 | let library = configuration.library
70 | try check(library, db: db, code: withUnsafeMutablePointer(to: &db) { ptr in
71 | if let flags = flags {
72 | return library.sqlite3_open_v2(path, ptr, flags.rawValue, nil)
73 | } else {
74 | return library.sqlite3_open(path, ptr)
75 | }
76 | })
77 |
78 | return db
79 | }
80 |
81 | public struct OpenFlags: OptionSet {
82 | public let rawValue: Int32
83 |
84 | public init(rawValue: Int32) {
85 | self.rawValue = rawValue
86 | }
87 |
88 | public static let readOnly = OpenFlags(rawValue: 0x00000001)
89 | public static let readWrite = OpenFlags(rawValue: 0x00000002)
90 | public static let create = OpenFlags(rawValue: 0x00000004)
91 | public static let uri = OpenFlags(rawValue: 0x00000040)
92 | public static let memory = OpenFlags(rawValue: 0x00000080)
93 | public static let nomutex = OpenFlags(rawValue: 0x00008000)
94 | public static let fullMutex = OpenFlags(rawValue: 0x00010000)
95 | public static let sharedCache = OpenFlags(rawValue: 0x00020000)
96 | public static let privateCache = OpenFlags(rawValue: 0x00040000)
97 | }
98 |
99 | public func exec(_ expr: SQLExpression) throws {
100 | try checkClosed()
101 | let stmnt = try prepare(sql: expr.template)
102 | var err: Error? = nil
103 | do {
104 | try stmnt.update(parameters: expr.bindings)
105 | } catch let e {
106 | err = e
107 | }
108 | // always close the statements; we don't use a `defer` block because they can't throw
109 | try stmnt.close()
110 | if let err = err {
111 | throw err
112 | }
113 | }
114 |
115 | /// Execute the given SQL statement.
116 | public func exec(sql: String, parameters: [SQLValue] = []) throws {
117 | try exec(SQLExpression(sql, parameters))
118 | }
119 |
120 | /// See
121 | public func interrupt() {
122 | SQLite3.sqlite3_interrupt(db)
123 | }
124 |
125 | /// True if the context has been closed.
126 | public var isClosed: Bool {
127 | closed
128 | }
129 |
130 | /// Close the connection.
131 | public func close() throws {
132 | if !closed {
133 | try check(SQLite3, db: db, code: SQLite3.sqlite3_close(db))
134 | closed = true
135 | }
136 | }
137 |
138 | /// Prepares the given SQL as a statement, which can be executed with parameter bindings.
139 | public func prepare(sql: String) throws -> SQLStatement {
140 | try checkClosed()
141 | if let logLevel = self.logLevel {
142 | logger.log(level: logLevel, "prepare: \(sql)")
143 | }
144 | var stmntPtr: OpaquePointer? = nil
145 |
146 | try check(SQLite3, db: db, code: withUnsafeMutablePointer(to: &stmntPtr) { ptr in
147 | SQLite3.sqlite3_prepare_v2(db, sql, Int32(-1), ptr, nil)
148 | })
149 |
150 | if stmntPtr == nil {
151 | throw SQLStatementCreationError()
152 | }
153 |
154 | return SQLStatement(stmnt: stmntPtr!, SQLite3: self.SQLite3)
155 | }
156 |
157 | /// How a transaction is being performed.
158 | public enum TransactionMode: String {
159 | case deferred = "DEFERRED"
160 | case immediate = "IMMEDIATE"
161 | case exclusive = "EXCLUSIVE"
162 | }
163 |
164 | /// Performs the given operation in the context of a transaction.
165 | ///
166 | /// Specifying `.none` as the transaction mode will execute the command without a transaction.
167 | public func transaction(_ mode: TransactionMode? = .deferred, block: () throws -> T) throws -> T {
168 | if let mode = mode {
169 | return try perform(
170 | "BEGIN \(mode.rawValue) TRANSACTION",
171 | block,
172 | "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
173 | } else {
174 | return try block()
175 | }
176 | }
177 |
178 | /// Performs the given operation within the databases mutex lock.
179 | public func mutex(block: () throws -> T) rethrows -> T {
180 | let lock = SQLite3.sqlite3_db_mutex(db)
181 | SQLite3.sqlite3_mutex_enter(lock)
182 | defer {
183 | SQLite3.sqlite3_mutex_leave(lock)
184 | // SQLite3.sqlite3_mutex_free(lock) // don't free!
185 | }
186 | return try block()
187 | }
188 |
189 | /// Performs the given operation in the context of a begin and commit/rollback statement.
190 | fileprivate func perform(_ begin: String, _ block: () throws -> T, _ commit: String, or rollback: String) throws -> T {
191 | try exec(sql: begin)
192 | do {
193 | let result = try block()
194 | try exec(sql: commit)
195 | return result
196 | } catch {
197 | try exec(sql: rollback)
198 | throw error
199 | }
200 | }
201 |
202 | private func checkClosed() throws {
203 | if closed {
204 | throw SQLContextClosedError()
205 | }
206 | }
207 |
208 | /// Issue a query and return all the rows in a single batch
209 | public func query(sql: String, parameters: [SQLValue] = []) throws -> [[SQLValue]] {
210 | try cursor(SQLExpression(sql, parameters)).map({ try $0.get() })
211 | }
212 |
213 | /// Issues a SQL query with the optional parameters and returns all the values.
214 | public func cursor(_ expr: SQLExpression) throws -> RowCursor<[SQLValue]> {
215 | let stmnt = try prepare(sql: expr.template)
216 | if !expr.bindings.isEmpty {
217 | try stmnt.bind(parameters: expr.bindings)
218 | }
219 | return RowCursor(statement: stmnt, creator: { $0.rowValues() })
220 | }
221 |
222 |
223 | // MARK: trace
224 |
225 | public typealias TraceAction = (String) -> Void
226 | private var traceHook: TraceHook?
227 |
228 | #if !SKIP
229 | typealias TraceBox = @convention(block) (UnsafeRawPointer) -> Void
230 | private typealias TraceHook = TraceBox
231 | #else
232 | private final class TraceHook : sqlite3_trace_hook {
233 | let action: TraceAction
234 | let context: SQLContext
235 |
236 | init(action: TraceAction, context: SQLContext) {
237 | self.action = action
238 | self.context = context
239 | }
240 |
241 | override func callback(type: sqlite3_unsigned, ctx: OpaquePointer?, pointer: OpaquePointer?, px: OpaquePointer?) -> Int32 {
242 | if let pointer,
243 | let expandedSQL: sqlite3_cstring_mutptr = context.SQLite3.sqlite3_expanded_sql(pointer) {
244 | action(expandedSQL.getString(0))
245 | context.SQLite3.sqlite3_free(expandedSQL)
246 | }
247 | return 0
248 | }
249 | }
250 | #endif
251 |
252 | /// Adds a callback that will be invoked with the expanded SQL whenever a statement is executed
253 | public func trace(_ action: TraceAction?) {
254 | guard let action else {
255 | // disable trace
256 | _ = SQLite3.sqlite3_trace_v2(db, 0, nil, nil)
257 | self.traceHook = nil
258 | return
259 | }
260 |
261 | #if !SKIP
262 | let box: TraceBox = { (pointer: UnsafeRawPointer) in
263 | if let expandedSQL: sqlite3_cstring_mutptr = self.SQLite3.sqlite3_expanded_sql(OpaquePointer(pointer)) {
264 | action(String(cString: expandedSQL))
265 | self.SQLite3.sqlite3_free(expandedSQL)
266 | }
267 | }
268 |
269 | _ = SQLite3.sqlite3_trace_v2(db, UInt32(SQLITE_TRACE_STMT), {
270 | (_: UInt32, context: UnsafeMutableRawPointer?, pointer: UnsafeMutableRawPointer?, _: UnsafeMutableRawPointer?) in
271 | if let pointer {
272 | unsafeBitCast(context, to: TraceBox.self)(pointer)
273 | }
274 | return Int32(0)
275 | },
276 | unsafeBitCast(box, to: UnsafeMutableRawPointer.self)
277 | )
278 | traceHook = box
279 | #else
280 | self.traceHook = TraceHook(action: action, context: self) // need to retain or it will be garbage collected eventually
281 | // The Kotlin update mechanism is different; it uses a TraceHook implementation, and doesn't pass a context pointer
282 | SQLite3.sqlite3_trace_v2(db, SQLITE_TRACE_STMT, self.traceHook, nil)
283 | #endif
284 | }
285 |
286 |
287 | // MARK: onUpdate
288 |
289 | private var updateHook: UpdateHook? = nil
290 |
291 | /// An action that can be registered to receive updates whenever a ROWID table changes.
292 | public typealias UpdateAction = (_ action: SQLAction, _ rowid: Int64, _ dbname: String, _ tblname: String) -> Void
293 |
294 | #if !SKIP
295 | private typealias UpdateHook = UpdateAction
296 | #else
297 | private final class UpdateHook : sqlite3_update_hook {
298 | let updateAction: UpdateAction
299 |
300 | init(action: UpdateAction) {
301 | self.updateAction = action
302 | }
303 |
304 | override func callback(ptr: OpaquePointer?, operation: Int32, databaseName: OpaquePointer?, tableName: OpaquePointer?, rowid: Int64) {
305 | if let operation = SQLAction(rawValue: operation),
306 | let dbnamePtr = databaseName, let tblnamePtr = tableName {
307 | updateAction(operation, rowid, String(cString: dbnamePtr), String(cString: tblnamePtr))
308 | }
309 | }
310 | }
311 | #endif
312 |
313 | /// Registers a function to be invoked whenever a ROWID table is changed.
314 | ///
315 | /// As described at https://www.sqlite.org/c3ref/update_hook.html , a given connection can only have a single update hook at a time, so setting this function will replace any pre-existing update hook.
316 | public func onUpdate(hook: UpdateAction?) {
317 | guard let hook else {
318 | // clear the update hook
319 | self.updateHook = nil
320 | return
321 | }
322 | #if !SKIP
323 | self.updateHook = hook
324 | let updateActionPtr = Unmanaged.passRetained(hook as AnyObject).toOpaque()
325 | func callback(updateActionPtr: UnsafeMutableRawPointer?, operation: Int32, dbname: UnsafePointer?, tblname: UnsafePointer?, rowid: sqlite3_int64) -> Void {
326 | if let operation = SQLAction(rawValue: operation),
327 | let updateActionPtr = updateActionPtr,
328 | let hook = Unmanaged.fromOpaque(updateActionPtr).takeUnretainedValue() as? UpdateAction,
329 | let dbnamePtr = dbname, let tblnamePtr = tblname {
330 | hook(operation, rowid, String(cString: dbnamePtr), String(cString: tblnamePtr))
331 | }
332 | }
333 | _ = SQLite3.sqlite3_update_hook(db, callback, updateActionPtr)
334 | #else
335 | self.updateHook = UpdateHook(action: hook) // need to retain or it will be garbage collected eventually
336 | // The Kotlin update mechanism is different; it uses a SQLiteUpdateHookCallback implementation, and doesn't pass a userData pointer
337 | SQLite3.sqlite3_update_hook(db, self.updateHook, nil)
338 | #endif
339 | }
340 | }
341 |
342 | public struct SQLExpression {
343 | public var template: String
344 | public var bindings: [SQLValue]
345 |
346 | public init(_ template: String, _ bindings: [SQLValue] = []) {
347 | self.template = template
348 | self.bindings = bindings
349 | }
350 | }
351 |
352 | extension String {
353 | /// Encodes the String so the given mark is doubled in the resulting string.
354 | public func quote(_ mark: Character = "\"") -> String {
355 | var quoted = ""
356 | quoted += mark.description
357 | for character in self {
358 | quoted += character.description
359 | if character == mark {
360 | quoted += character.description
361 | }
362 | }
363 | quoted += mark.description
364 | return quoted
365 | }
366 | }
367 |
368 | /// A lazy sequence of rows from the database
369 | public class RowCursor : Sequence {
370 | public typealias Element = Result
371 | let statement: SQLStatement
372 | let creator: (SQLStatement) throws -> Row
373 |
374 | public init(statement: SQLStatement, creator: @escaping (SQLStatement) throws -> Row) {
375 | self.statement = statement
376 | self.creator = creator
377 | }
378 |
379 | public func close() {
380 | do {
381 | try statement.close()
382 | } catch {
383 | }
384 | }
385 |
386 |
387 | #if !SKIP
388 | public func makeIterator() -> RowIterator {
389 | RowIterator(statement: statement, creator: creator)
390 | }
391 | #else
392 | override var iterable: kotlin.collections.Iterable {
393 | AbstractIterable {
394 | RowIterator(statement: statement, creator: creator)
395 | }
396 | }
397 | #endif
398 | }
399 |
400 | #if !SKIP
401 | typealias RowIteratorType = IteratorProtocol
402 | #else
403 | typealias RowIteratorType = kotlin.collections.Iterator>
404 |
405 | class AbstractIterable : kotlin.collections.Iterable> {
406 | let makeIterator: () -> RowIterator
407 |
408 | init(makeIterator: () -> RowIterator) {
409 | self.makeIterator = makeIterator
410 | }
411 |
412 | override func iterator() -> RowIterator {
413 | makeIterator()
414 | }
415 | }
416 | #endif
417 |
418 | public class RowIterator : RowIteratorType {
419 | public typealias Element = Result
420 | let stmnt: SQLStatement
421 | let creator: (SQLStatement) throws -> Row
422 | var errorOccurred = false
423 |
424 | init(statement: SQLStatement, creator: @escaping (SQLStatement) throws -> Row) {
425 | self.stmnt = statement
426 | self.creator = creator
427 | }
428 |
429 | deinit {
430 | close()
431 | }
432 |
433 | func close() {
434 | do {
435 | try stmnt.close()
436 | } catch {
437 | // ignore
438 | }
439 | }
440 |
441 | #if !SKIP
442 | public func next() -> Element? {
443 | if errorOccurred {
444 | return nil
445 | }
446 | do {
447 | if try stmnt.next() == false { return nil }
448 | return Result.success(try creator(stmnt))
449 | } catch {
450 | errorOccurred = true
451 | return Result.failure(error)
452 | }
453 | }
454 | #else
455 | var nextElement: Element? = nil
456 |
457 | override func next() -> Element {
458 | if let nextElement = nextElement {
459 | return nextElement
460 | } else {
461 | throw java.util.NoSuchElementException()
462 | }
463 | }
464 |
465 | override func hasNext() -> Bool {
466 | if errorOccurred {
467 | return false
468 | }
469 | do {
470 | if try stmnt.next() == false {
471 | close()
472 | return false
473 | }
474 | nextElement = Result.success(try creator(stmnt))
475 | return true
476 | } catch {
477 | errorOccurred = true
478 | nextElement = Result.failure(error)
479 | close()
480 | return false
481 | }
482 | }
483 | #endif
484 | }
485 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/SQLStatement.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if SKIP
4 | import SkipFFI
5 | #endif
6 | import Foundation
7 | import OSLog
8 |
9 | /// A database prepared statement.
10 | public final class SQLStatement {
11 | /// The SQLite3 library to use.
12 | fileprivate let SQLite3: SQLiteLibrary
13 |
14 | /// The pointer to the SQLite statement.
15 | fileprivate let stmnt: OpaquePointer
16 | fileprivate var closed = false
17 |
18 | deinit {
19 | #if !SKIP
20 | #if DEBUG
21 | // assert(isClosed, "SQLStatement must be closed before deinit")
22 | #endif
23 | #endif
24 | }
25 |
26 | internal init(stmnt: OpaquePointer, SQLite3: SQLiteLibrary) {
27 | self.stmnt = stmnt
28 | self.SQLite3 = SQLite3
29 | }
30 |
31 | /// The database pointer that created this statement.
32 | private var db: OpaquePointer {
33 | SQLite3.sqlite3_db_handle(stmnt)
34 | }
35 |
36 | public lazy var columnCount: Int32 = SQLite3.sqlite3_column_count(stmnt)
37 |
38 | public lazy var columnNames: [String] = Array((0..= 1, "bind index in sqlite starts at 1")
59 | switch value {
60 | case .null:
61 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_null(stmnt, index))
62 | case .long(let long):
63 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_int64(stmnt, index, long))
64 | case .text(let text):
65 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_text(stmnt, index, text, -1, SQLITE_TRANSIENT))
66 | case .real(let real):
67 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_double(stmnt, index, real))
68 | case .blob(let blob):
69 | let size = Int32(blob.count)
70 | if size == 0 {
71 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_zeroblob(stmnt, index, size))
72 | } else {
73 | try blob.withUnsafeBytes { ptr in
74 | try check(SQLite3, db: db, code: SQLite3.sqlite3_bind_blob(stmnt, index, ptr.baseAddress, size, SQLITE_TRANSIENT))
75 | }
76 | }
77 | }
78 | }
79 |
80 | /// Perform an update with the prepared statemement, resetting it once the update is complete.
81 | /// - Parameter params: the parameters to bind to the SQL statement
82 | public func update(parameters: [SQLValue] = []) throws {
83 | try checkClosed()
84 | defer { reset() }
85 | if !parameters.isEmpty {
86 | try bind(parameters: parameters)
87 | }
88 | let result = SQLite3.sqlite3_step(stmnt)
89 | try check(SQLite3, db: db, code: result, permit: [Int32(SQLITE_DONE)])
90 | }
91 |
92 | /// Binds the given parameters to the statement. The parameter count must match the number of `?` parameters in the statement.
93 | public func bind(parameters: [SQLValue]) throws {
94 | for (i, param) in parameters.enumerated() {
95 | try bind(param, at: Int32(i + 1)) // column index starts at 1
96 | }
97 | }
98 |
99 | /// After a prepared statement has been prepared this function must be called one or more times to evaluate the statement.
100 | public func next() throws -> Bool {
101 | try checkClosed()
102 | let result = SQLite3.sqlite3_step(stmnt)
103 | if result == SQLITE_ROW {
104 | return true
105 | } else if result == SQLITE_DONE {
106 | return false
107 | } else {
108 | try check(SQLite3, db: db, code: result) // try to extract the error message
109 | throw SQLStatementError(code: result)
110 | }
111 | }
112 |
113 | /// True if the statement has been closed.
114 | public var isClosed: Bool {
115 | closed
116 | }
117 |
118 | /// The application must close every prepared statement in order to avoid
119 | /// resource leaks. It is a grievous error for the application to try to use
120 | /// a prepared statement after it has been closed.
121 | public func close() throws {
122 | if !closed {
123 | reset() // need to reset interrupted statemets or an interrupted error will be throws
124 | try check(SQLite3, db: db, code: SQLite3.sqlite3_finalize(stmnt))
125 | closed = true
126 | }
127 | }
128 |
129 | public func reset() {
130 | reset(clearBindings: true)
131 | }
132 |
133 | internal func reset(clearBindings: Bool) {
134 | _ = SQLite3.sqlite3_reset(stmnt)
135 | if clearBindings {
136 | _ = SQLite3.sqlite3_clear_bindings(stmnt)
137 | }
138 | }
139 |
140 | /// Returns the type of the column at the given index.
141 | public func type(at idx: Int32) -> SQLType {
142 | SQLType(rawValue: SQLite3.sqlite3_column_type(stmnt, idx)) ?? .null
143 | }
144 |
145 | /// Returns the integer at the given index, coercing if necessary according to https://www.sqlite.org/datatype3.html
146 | public func long(at idx: Int32) -> Int64 {
147 | SQLite3.sqlite3_column_int64(stmnt, idx)
148 | }
149 |
150 | @available(*, deprecated, renamed: "long")
151 | public func integer(at idx: Int32) -> Int64 {
152 | long(at: idx)
153 | }
154 |
155 | /// Returns the double at the given index, coercing if necessary according to https://www.sqlite.org/datatype3.html
156 | public func real(at idx: Int32) -> Double {
157 | SQLite3.sqlite3_column_double(stmnt, idx)
158 | }
159 |
160 | @available(*, deprecated, renamed: "real")
161 | public func double(at idx: Int32) -> Double {
162 | real(at: idx)
163 | }
164 |
165 | /// Returns the string at the given index, coercing if necessary according to https://www.sqlite.org/datatype3.html
166 | public func text(at idx: Int32) -> String? {
167 | strptr(SQLite3.sqlite3_column_text(stmnt, idx))
168 | }
169 |
170 | @available(*, deprecated, renamed: "text")
171 | public func string(at idx: Int32) -> String? {
172 | text(at: idx)
173 | }
174 |
175 | /// Returns the blob Data at the given index, coercing if necessary according to https://www.sqlite.org/datatype3.html
176 | public func blob(at idx: Int32) -> Data? {
177 | if let pointer = SQLite3.sqlite3_column_blob(stmnt, idx) {
178 | let length = SQLite3.sqlite3_column_bytes(stmnt, idx)
179 | #if !SKIP
180 | return Data(bytes: pointer, count: Int(length))
181 | #else
182 | let byteArray = pointer.getByteArray(0, length)
183 | return Data(platformValue: byteArray)
184 | #endif
185 | } else {
186 | // The return value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
187 | // https://www.sqlite.org/c3ref/column_blob.html
188 | return nil
189 | }
190 | }
191 |
192 | /// Returns the value at the given index, based on the type returned from `type(at:)`.
193 | public func value(at idx: Int32) -> SQLValue {
194 | switch type(at: idx) {
195 | case SQLType.long:
196 | return SQLValue.long(long(at: idx))
197 | case SQLType.real:
198 | return SQLValue.real(real(at: idx))
199 | case SQLType.text:
200 | if let string = text(at: idx) {
201 | return SQLValue.text(string)
202 | } else {
203 | return SQLValue.null
204 | }
205 | case SQLType.blob:
206 | if let blob = blob(at: idx) {
207 | return SQLValue.blob(blob)
208 | } else {
209 | return SQLValue.null
210 | }
211 | case SQLType.null:
212 | return SQLValue.null
213 | }
214 | }
215 |
216 | public func rowValues() -> [SQLValue] {
217 | Array((0.. [SQLValue]? {
222 | try checkClosed()
223 |
224 | if !(try next()) {
225 | return nil
226 | }
227 |
228 | let values = rowValues()
229 |
230 | if close {
231 | try self.close()
232 | }
233 |
234 | return values
235 | }
236 |
237 | /// Returns the values of the current row as an array of strings, coercing if necessary according to https://www.sqlite.org/datatype3.html
238 | public func stringValues() -> [String?] {
239 | Array((0.. SQLValue {
204 | .real(value)
205 | }
206 |
207 | @available(*, deprecated, renamed: "long")
208 | static func integer(_ value: Int64) -> SQLValue {
209 | .long(value)
210 | }
211 | }
212 |
213 | public struct SQLContextClosedError : Error {
214 | }
215 |
216 | public struct SQLStatementCreationError : Error {
217 | }
218 |
219 | public struct SQLStatementClosedError : Error {
220 | }
221 |
222 | public struct InternalError : Error {
223 | public let code: Int32
224 |
225 | public init(code: Int32) {
226 | self.code = code
227 | }
228 | }
229 |
230 | public struct SQLError : Error, CustomStringConvertible {
231 | public let msg: String
232 | public let code: Int32
233 |
234 | public init(msg: String, code: Int32) {
235 | self.msg = msg
236 | self.code = code
237 | }
238 |
239 | public var description: String {
240 | "SQLite error code \(code): \(msg)"
241 | }
242 |
243 | public var localizedDescription: String {
244 | "SQLite error code \(code): \(msg)"
245 | }
246 | }
247 |
248 | public struct SQLStatementError : Error {
249 | public let code: Int32
250 | }
251 |
252 |
253 | internal func check(_ SQLite3: SQLiteLibrary, db: OpaquePointer?, code: Int32, permit: Set? = nil) throws {
254 | if code != 0 && permit?.contains(code) != true {
255 | if let db = db, let msg = SQLite3.sqlite3_errmsg(db) {
256 | throw SQLError(msg: String(cString: msg), code: code)
257 | } else {
258 | throw SQLError(msg: "Unknown SQLite error", code: code)
259 | }
260 | }
261 | }
262 |
263 | #if SKIP
264 | internal func strptr(_ ptr: OpaquePointer?) -> String? {
265 | guard let ptr = ptr else { return nil }
266 | return String(cString: ptr)
267 | }
268 | #else
269 | internal func strptr(_ ptr: UnsafePointer?) -> String? {
270 | guard let ptr = ptr else { return nil }
271 | return String(cString: ptr)
272 | }
273 |
274 | internal func strptr(_ ptr: UnsafePointer?) -> String? {
275 | guard let ptr = ptr else { return nil }
276 | return String(cString: ptr)
277 | }
278 | #endif
279 |
280 |
281 | #if SKIP
282 |
283 |
284 | // MARK: SQLite Result Codes
285 |
286 | let SQLITE_OK = 0 /* Successful result */
287 | let SQLITE_ERROR = 1 /* Generic error */
288 | let SQLITE_INTERNAL = 2 /* Internal logic error in SQLite */
289 | let SQLITE_PERM = 3 /* Access permission denied */
290 | let SQLITE_ABORT = 4 /* Callback routine requested an abort */
291 | let SQLITE_BUSY = 5 /* The database file is locked */
292 | let SQLITE_LOCKED = 6 /* A table in the database is locked */
293 | let SQLITE_NOMEM = 7 /* A malloc() failed */
294 | let SQLITE_READONLY = 8 /* Attempt to write a readonly database */
295 | let SQLITE_INTERRUPT = 9 /* Operation terminated by sqlite3_interrupt()*/
296 | let SQLITE_IOERR = 10 /* Some kind of disk I/O error occurred */
297 | let SQLITE_CORRUPT = 11 /* The database disk image is malformed */
298 | let SQLITE_NOTFOUND = 12 /* Unknown opcode in sqlite3_file_control() */
299 | let SQLITE_FULL = 13 /* Insertion failed because database is full */
300 | let SQLITE_CANTOPEN = 14 /* Unable to open the database file */
301 | let SQLITE_PROTOCOL = 15 /* Database lock protocol error */
302 | let SQLITE_EMPTY = 16 /* Internal use only */
303 | let SQLITE_SCHEMA = 17 /* The database schema changed */
304 | let SQLITE_TOOBIG = 18 /* String or BLOB exceeds size limit */
305 | let SQLITE_CONSTRAINT = 19 /* Abort due to constraint violation */
306 | let SQLITE_MISMATCH = 20 /* Data type mismatch */
307 | let SQLITE_MISUSE = 21 /* Library used incorrectly */
308 | let SQLITE_NOLFS = 22 /* Uses OS features not supported on host */
309 | let SQLITE_AUTH = 23 /* Authorization denied */
310 | let SQLITE_FORMAT = 24 /* Not used */
311 | let SQLITE_RANGE = 25 /* 2nd parameter to sqlite3_bind out of range */
312 | let SQLITE_NOTADB = 26 /* File opened that is not a database file */
313 | let SQLITE_NOTICE = 27 /* Notifications from sqlite3_log() */
314 | let SQLITE_WARNING = 28 /* Warnings from sqlite3_log() */
315 | let SQLITE_ROW = 100 /* sqlite3_step() has another row ready */
316 | let SQLITE_DONE = 101 /* sqlite3_step() has finished executing */
317 |
318 | // MARK Extended Result Codes
319 |
320 | let SQLITE_ERROR_MISSING_COLLSEQ = (SQLITE_ERROR | (1<<8))
321 | let SQLITE_ERROR_RETRY = (SQLITE_ERROR | (2<<8))
322 | let SQLITE_ERROR_SNAPSHOT = (SQLITE_ERROR | (3<<8))
323 | let SQLITE_IOERR_READ = (SQLITE_IOERR | (1<<8))
324 | let SQLITE_IOERR_SHORT_READ = (SQLITE_IOERR | (2<<8))
325 | let SQLITE_IOERR_WRITE = (SQLITE_IOERR | (3<<8))
326 | let SQLITE_IOERR_FSYNC = (SQLITE_IOERR | (4<<8))
327 | let SQLITE_IOERR_DIR_FSYNC = (SQLITE_IOERR | (5<<8))
328 | let SQLITE_IOERR_TRUNCATE = (SQLITE_IOERR | (6<<8))
329 | let SQLITE_IOERR_FSTAT = (SQLITE_IOERR | (7<<8))
330 | let SQLITE_IOERR_UNLOCK = (SQLITE_IOERR | (8<<8))
331 | let SQLITE_IOERR_RDLOCK = (SQLITE_IOERR | (9<<8))
332 | let SQLITE_IOERR_DELETE = (SQLITE_IOERR | (10<<8))
333 | let SQLITE_IOERR_BLOCKED = (SQLITE_IOERR | (11<<8))
334 | let SQLITE_IOERR_NOMEM = (SQLITE_IOERR | (12<<8))
335 | let SQLITE_IOERR_ACCESS = (SQLITE_IOERR | (13<<8))
336 | let SQLITE_IOERR_CHECKRESERVEDLOCK = (SQLITE_IOERR | (14<<8))
337 | let SQLITE_IOERR_LOCK = (SQLITE_IOERR | (15<<8))
338 | let SQLITE_IOERR_CLOSE = (SQLITE_IOERR | (16<<8))
339 | let SQLITE_IOERR_DIR_CLOSE = (SQLITE_IOERR | (17<<8))
340 | let SQLITE_IOERR_SHMOPEN = (SQLITE_IOERR | (18<<8))
341 | let SQLITE_IOERR_SHMSIZE = (SQLITE_IOERR | (19<<8))
342 | let SQLITE_IOERR_SHMLOCK = (SQLITE_IOERR | (20<<8))
343 | let SQLITE_IOERR_SHMMAP = (SQLITE_IOERR | (21<<8))
344 | let SQLITE_IOERR_SEEK = (SQLITE_IOERR | (22<<8))
345 | let SQLITE_IOERR_DELETE_NOENT = (SQLITE_IOERR | (23<<8))
346 | let SQLITE_IOERR_MMAP = (SQLITE_IOERR | (24<<8))
347 | let SQLITE_IOERR_GETTEMPPATH = (SQLITE_IOERR | (25<<8))
348 | let SQLITE_IOERR_CONVPATH = (SQLITE_IOERR | (26<<8))
349 | let SQLITE_IOERR_VNODE = (SQLITE_IOERR | (27<<8))
350 | let SQLITE_IOERR_AUTH = (SQLITE_IOERR | (28<<8))
351 | let SQLITE_IOERR_BEGIN_ATOMIC = (SQLITE_IOERR | (29<<8))
352 | let SQLITE_IOERR_COMMIT_ATOMIC = (SQLITE_IOERR | (30<<8))
353 | let SQLITE_IOERR_ROLLBACK_ATOMIC = (SQLITE_IOERR | (31<<8))
354 | let SQLITE_IOERR_DATA = (SQLITE_IOERR | (32<<8))
355 | let SQLITE_IOERR_CORRUPTFS = (SQLITE_IOERR | (33<<8))
356 | let SQLITE_IOERR_IN_PAGE = (SQLITE_IOERR | (34<<8))
357 | let SQLITE_LOCKED_SHAREDCACHE = (SQLITE_LOCKED | (1<<8))
358 | let SQLITE_LOCKED_VTAB = (SQLITE_LOCKED | (2<<8))
359 | let SQLITE_BUSY_RECOVERY = (SQLITE_BUSY | (1<<8))
360 | let SQLITE_BUSY_SNAPSHOT = (SQLITE_BUSY | (2<<8))
361 | let SQLITE_BUSY_TIMEOUT = (SQLITE_BUSY | (3<<8))
362 | let SQLITE_CANTOPEN_NOTEMPDIR = (SQLITE_CANTOPEN | (1<<8))
363 | let SQLITE_CANTOPEN_ISDIR = (SQLITE_CANTOPEN | (2<<8))
364 | let SQLITE_CANTOPEN_FULLPATH = (SQLITE_CANTOPEN | (3<<8))
365 | let SQLITE_CANTOPEN_CONVPATH = (SQLITE_CANTOPEN | (4<<8))
366 | let SQLITE_CANTOPEN_DIRTYWAL = (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
367 | let SQLITE_CANTOPEN_SYMLINK = (SQLITE_CANTOPEN | (6<<8))
368 | let SQLITE_CORRUPT_VTAB = (SQLITE_CORRUPT | (1<<8))
369 | let SQLITE_CORRUPT_SEQUENCE = (SQLITE_CORRUPT | (2<<8))
370 | let SQLITE_CORRUPT_INDEX = (SQLITE_CORRUPT | (3<<8))
371 | let SQLITE_READONLY_RECOVERY = (SQLITE_READONLY | (1<<8))
372 | let SQLITE_READONLY_CANTLOCK = (SQLITE_READONLY | (2<<8))
373 | let SQLITE_READONLY_ROLLBACK = (SQLITE_READONLY | (3<<8))
374 | let SQLITE_READONLY_DBMOVED = (SQLITE_READONLY | (4<<8))
375 | let SQLITE_READONLY_CANTINIT = (SQLITE_READONLY | (5<<8))
376 | let SQLITE_READONLY_DIRECTORY = (SQLITE_READONLY | (6<<8))
377 | let SQLITE_ABORT_ROLLBACK = (SQLITE_ABORT | (2<<8))
378 | let SQLITE_CONSTRAINT_CHECK = (SQLITE_CONSTRAINT | (1<<8))
379 | let SQLITE_CONSTRAINT_COMMITHOOK = (SQLITE_CONSTRAINT | (2<<8))
380 | let SQLITE_CONSTRAINT_FOREIGNKEY = (SQLITE_CONSTRAINT | (3<<8))
381 | let SQLITE_CONSTRAINT_FUNCTION = (SQLITE_CONSTRAINT | (4<<8))
382 | let SQLITE_CONSTRAINT_NOTNULL = (SQLITE_CONSTRAINT | (5<<8))
383 | let SQLITE_CONSTRAINT_PRIMARYKEY = (SQLITE_CONSTRAINT | (6<<8))
384 | let SQLITE_CONSTRAINT_TRIGGER = (SQLITE_CONSTRAINT | (7<<8))
385 | let SQLITE_CONSTRAINT_UNIQUE = (SQLITE_CONSTRAINT | (8<<8))
386 | let SQLITE_CONSTRAINT_VTAB = (SQLITE_CONSTRAINT | (9<<8))
387 | let SQLITE_CONSTRAINT_ROWID = (SQLITE_CONSTRAINT | (10<<8))
388 | let SQLITE_CONSTRAINT_PINNED = (SQLITE_CONSTRAINT | (11<<8))
389 | let SQLITE_CONSTRAINT_DATATYPE = (SQLITE_CONSTRAINT | (12<<8))
390 | let SQLITE_NOTICE_RECOVER_WAL = (SQLITE_NOTICE | (1<<8))
391 | let SQLITE_NOTICE_RECOVER_ROLLBACK = (SQLITE_NOTICE | (2<<8))
392 | let SQLITE_NOTICE_RBU = (SQLITE_NOTICE | (3<<8))
393 | let SQLITE_WARNING_AUTOINDEX = (SQLITE_WARNING | (1<<8))
394 | let SQLITE_AUTH_USER = (SQLITE_AUTH | (1<<8))
395 | let SQLITE_OK_LOAD_PERMANENTLY = (SQLITE_OK | (1<<8))
396 | let SQLITE_OK_SYMLINK = (SQLITE_OK | (2<<8)) /* internal use only */
397 |
398 |
399 | // MARK: SQLite Open File Flags
400 |
401 | let SQLITE_OPEN_READONLY = 0x00000001 /* Ok for sqlite3_open_v2() */
402 | let SQLITE_OPEN_READWRITE = 0x00000002 /* Ok for sqlite3_open_v2() */
403 | let SQLITE_OPEN_CREATE = 0x00000004 /* Ok for sqlite3_open_v2() */
404 | let SQLITE_OPEN_DELETEONCLOSE = 0x00000008 /* VFS only */
405 | let SQLITE_OPEN_EXCLUSIVE = 0x00000010 /* VFS only */
406 | let SQLITE_OPEN_AUTOPROXY = 0x00000020 /* VFS only */
407 | let SQLITE_OPEN_URI = 0x00000040 /* Ok for sqlite3_open_v2() */
408 | let SQLITE_OPEN_MEMORY = 0x00000080 /* Ok for sqlite3_open_v2() */
409 | let SQLITE_OPEN_MAIN_DB = 0x00000100 /* VFS only */
410 | let SQLITE_OPEN_TEMP_DB = 0x00000200 /* VFS only */
411 | let SQLITE_OPEN_TRANSIENT_DB = 0x00000400 /* VFS only */
412 | let SQLITE_OPEN_MAIN_JOURNAL = 0x00000800 /* VFS only */
413 | let SQLITE_OPEN_TEMP_JOURNAL = 0x00001000 /* VFS only */
414 | let SQLITE_OPEN_SUBJOURNAL = 0x00002000 /* VFS only */
415 | let SQLITE_OPEN_SUPER_JOURNAL = 0x00004000 /* VFS only */
416 | let SQLITE_OPEN_NOMUTEX = 0x00008000 /* Ok for sqlite3_open_v2() */
417 | let SQLITE_OPEN_FULLMUTEX = 0x00010000 /* Ok for sqlite3_open_v2() */
418 | let SQLITE_OPEN_SHAREDCACHE = 0x00020000 /* Ok for sqlite3_open_v2() */
419 | let SQLITE_OPEN_PRIVATECACHE = 0x00040000 /* Ok for sqlite3_open_v2() */
420 | let SQLITE_OPEN_WAL = 0x00080000 /* VFS only */
421 | let SQLITE_OPEN_NOFOLLOW = 0x01000000 /* Ok for sqlite3_open_v2() */
422 | let SQLITE_OPEN_EXRESCODE = 0x02000000 /* Extended result codes */
423 |
424 | let SQLITE_TRANSIENT = Int64(-1)
425 |
426 | #endif
427 |
428 |
429 | // https://sqlite.org/c3ref/c_trace.html
430 |
431 | let SQLITE_TRACE_STMT = 0x01
432 | let SQLITE_TRACE_PROFILE = 0x02
433 | let SQLITE_TRACE_ROW = 0x04
434 | let SQLITE_TRACE_CLOSE = 0x08
435 |
436 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/SQLiteCLibrary.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if !SKIP
4 | import SQLite3
5 |
6 | public typealias sqlite3_int64 = SQLite3.sqlite3_int64
7 | /// An action that can be registered to receive updates whenever a ROWID table changes
8 | /// `((UnsafeMutableRawPointer?, Int32, UnsafePointer?, UnsafePointer?, sqlite3_int64) -> Void)`
9 | public typealias sqlite3_update_hook = @convention(c) (_ updateActionPtr: UnsafeMutableRawPointer?, _ operation: Int32, _ dbname: UnsafePointer?, _ tblname: UnsafePointer?, _ rowid: sqlite3_int64) -> ()
10 |
11 | /// A trace callback is invoked with four arguments: callback(T,C,P,X). The T argument is one of the `SQLITE_TRACE` constants to indicate why the callback was invoked. The C argument is a copy of the context pointer. The P and X arguments are pointers whose meanings depend on T.
12 | public typealias sqlite3_trace_hook = @convention(c) (_ type: UInt32, _ context: UnsafeMutableRawPointer?, _ p: UnsafeMutableRawPointer?, _ px: UnsafeMutableRawPointer?) -> Int32
13 |
14 | public let SQLITE_DONE = 101
15 | public let SQLITE_ROW = 100
16 |
17 | public typealias sqlite3_destructor_type = SQLite3.sqlite3_destructor_type
18 | public typealias sqlite3_callback = SQLite3.sqlite3_callback
19 |
20 | public let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
21 |
22 | /// The vendored SQLite3 library on Darwin platforms.
23 | /// The version of this library will vary between OS version, so some features (e.g., JSON support) might not be available.
24 | final class SQLiteCLibrary : SQLiteLibrary {
25 | static let shared = SQLiteCLibrary()
26 |
27 | init() {
28 | }
29 |
30 | func sqlite3_sleep(_ duration: Int32) -> Int32 {
31 | SQLite3.sqlite3_sleep(duration)
32 | }
33 |
34 | func sqlite3_open(_ filename: String, _ ppDb: sqlite3_openarg?) -> Int32 {
35 | SQLite3.sqlite3_open(filename, ppDb)
36 | }
37 |
38 | func sqlite3_open_v2(_ filename: String, _ ppDb: sqlite3_openarg?, _ flags: Int32, _ vfs: String?) -> Int32 {
39 | SQLite3.sqlite3_open_v2(filename, ppDb, flags, vfs)
40 | }
41 |
42 | func sqlite3_close(_ db: OpaquePointer) -> Int32 {
43 | SQLite3.sqlite3_close(db)
44 | }
45 |
46 | func sqlite3_errcode(_ db: OpaquePointer) -> Int32 {
47 | SQLite3.sqlite3_errcode(db)
48 | }
49 |
50 | func sqlite3_errmsg(_ db: OpaquePointer) -> sqlite3_cstring_ptr? {
51 | SQLite3.sqlite3_errmsg(db)
52 | }
53 |
54 | func sqlite3_last_insert_rowid(_ db: OpaquePointer) -> Int64 {
55 | SQLite3.sqlite3_last_insert_rowid(db)
56 | }
57 |
58 | func sqlite3_total_changes(_ db: OpaquePointer) -> Int32 {
59 | SQLite3.sqlite3_total_changes(db)
60 | }
61 |
62 | func sqlite3_changes(_ db: OpaquePointer) -> Int32 {
63 | SQLite3.sqlite3_changes(db)
64 | }
65 |
66 | func sqlite3_interrupt(_ db: OpaquePointer) {
67 | SQLite3.sqlite3_interrupt(db)
68 | }
69 |
70 | func sqlite3_exec(_ db: OpaquePointer, _ sql: String, _ callback: sqlite3_callback?, _ pArg: UnsafeMutableRawPointer?, _ errmsg: sqlite_error_ptr?) -> Int32 {
71 | SQLite3.sqlite3_exec(db, sql, callback, pArg, errmsg)
72 | }
73 |
74 | func sqlite3_prepare_v2(_ db: OpaquePointer, _ sql: String, _ nBytes: Int32, _ ppStmt: sqlite3_openarg, _ tail: UnsafeMutablePointer?>?) -> Int32 {
75 | SQLite3.sqlite3_prepare_v2(db, sql, nBytes, ppStmt, tail)
76 | }
77 |
78 | func sqlite3_step(_ stmt: OpaquePointer) -> Int32 {
79 | SQLite3.sqlite3_step(stmt)
80 | }
81 |
82 | func sqlite3_finalize(_ stmt: OpaquePointer) -> Int32 {
83 | SQLite3.sqlite3_finalize(stmt)
84 | }
85 |
86 | func sqlite3_reset(_ stmt: OpaquePointer) -> Int32 {
87 | SQLite3.sqlite3_reset(stmt)
88 | }
89 |
90 | func sqlite3_column_count(_ stmt: OpaquePointer) -> Int32 {
91 | SQLite3.sqlite3_column_count(stmt)
92 | }
93 |
94 | func sqlite3_bind_parameter_count(_ stmnt: OpaquePointer) -> Int32 {
95 | SQLite3.sqlite3_bind_parameter_count(stmnt)
96 | }
97 |
98 | func sqlite3_bind_parameter_name(_ stmnt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
99 | SQLite3.sqlite3_bind_parameter_name(stmnt, columnIndex)
100 | }
101 |
102 | func sqlite3_bind_parameter_index(_ stmnt: OpaquePointer, _ name: String) -> Int32 {
103 | SQLite3.sqlite3_bind_parameter_index(stmnt, name)
104 | }
105 |
106 | func sqlite3_clear_bindings(_ stmnt: OpaquePointer) -> Int32 {
107 | SQLite3.sqlite3_clear_bindings(stmnt)
108 | }
109 |
110 | func sqlite3_column_name(_ stmt: OpaquePointer!, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
111 | SQLite3.sqlite3_column_name(stmt!, columnIndex)
112 | }
113 |
114 | func sqlite3_column_decltype(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
115 | SQLite3.sqlite3_column_decltype(stmt, columnIndex)
116 | }
117 |
118 | func sqlite3_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_ptr? {
119 | SQLite3.sqlite3_sql(stmt)
120 | }
121 |
122 | func sqlite3_expanded_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_mutptr? {
123 | SQLite3.sqlite3_expanded_sql(stmt)
124 | }
125 |
126 | func sqlite3_db_handle(_ stmt: OpaquePointer) -> OpaquePointer {
127 | SQLite3.sqlite3_db_handle(stmt)
128 | }
129 |
130 | func sqlite3_bind_null(_ stmt: OpaquePointer, _ paramIndex: Int32) -> Int32 {
131 | SQLite3.sqlite3_bind_null(stmt, paramIndex)
132 | }
133 |
134 | func sqlite3_bind_int(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int32) -> Int32 {
135 | SQLite3.sqlite3_bind_int(stmt, paramIndex, value)
136 | }
137 |
138 | func sqlite3_bind_int64(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int64) -> Int32 {
139 | SQLite3.sqlite3_bind_int64(stmt, paramIndex, value)
140 | }
141 |
142 | func sqlite3_bind_double(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Double) -> Int32 {
143 | SQLite3.sqlite3_bind_double(stmt, paramIndex, value)
144 | }
145 |
146 | func sqlite3_bind_text(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: String, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32 {
147 | SQLite3.sqlite3_bind_text(stmt, paramIndex, value, length, destructor)
148 | }
149 |
150 | func sqlite3_bind_blob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: UnsafeRawPointer?, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32 {
151 | SQLite3.sqlite3_bind_blob(stmt, paramIndex, value, length, destructor)
152 | }
153 |
154 | func sqlite3_bind_zeroblob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ length: Int32) -> Int32 {
155 | SQLite3.sqlite3_bind_zeroblob(stmt, paramIndex, length)
156 | }
157 |
158 | func sqlite3_column_type(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
159 | SQLite3.sqlite3_column_type(stmt, columnIndex)
160 | }
161 |
162 | func sqlite3_column_int(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
163 | SQLite3.sqlite3_column_int(stmt, columnIndex)
164 | }
165 |
166 | func sqlite3_column_int64(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int64 {
167 | SQLite3.sqlite3_column_int64(stmt, columnIndex)
168 | }
169 |
170 | func sqlite3_column_double(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Double {
171 | SQLite3.sqlite3_column_double(stmt, columnIndex)
172 | }
173 |
174 | func sqlite3_column_text(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_uint8_ptr? {
175 | SQLite3.sqlite3_column_text(stmt, columnIndex)
176 | }
177 |
178 | func sqlite3_column_blob(_ stmt: OpaquePointer, _ columnIndex: Int32) -> UnsafeRawPointer? {
179 | SQLite3.sqlite3_column_blob(stmt, columnIndex)
180 | }
181 |
182 | func sqlite3_column_bytes(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
183 | SQLite3.sqlite3_column_bytes(stmt, columnIndex)
184 | }
185 |
186 | func sqlite3_backup_init(_ destDb: OpaquePointer, _ destName: String, _ sourceDb: OpaquePointer?, _ sourceName: String) -> OpaquePointer {
187 | SQLite3.sqlite3_backup_init(destDb, destName, sourceDb, sourceName)
188 | }
189 |
190 | func sqlite3_backup_step(_ backup: OpaquePointer, _ pages: Int32) -> Int32 {
191 | SQLite3.sqlite3_backup_step(backup, pages)
192 | }
193 |
194 | func sqlite3_backup_finish(_ backup: OpaquePointer) -> Int32 {
195 | SQLite3.sqlite3_backup_finish(backup)
196 | }
197 |
198 | func sqlite3_backup_remaining(_ backup: OpaquePointer) -> Int32 {
199 | SQLite3.sqlite3_backup_remaining(backup)
200 | }
201 |
202 | func sqlite3_backup_pagecount(_ backup: OpaquePointer) -> Int32 {
203 | SQLite3.sqlite3_backup_pagecount(backup)
204 | }
205 |
206 | func sqlite3_initialize() -> Int32 {
207 | SQLite3.sqlite3_initialize()
208 | }
209 |
210 | func sqlite3_shutdown() -> Int32 {
211 | SQLite3.sqlite3_shutdown()
212 | }
213 |
214 | func sqlite3_extended_result_codes(_ db: OpaquePointer, _ on: Int32) -> Int32 {
215 | SQLite3.sqlite3_extended_result_codes(db, on)
216 | }
217 |
218 | func sqlite3_free(_ ptr: sqlite3_pointer_type) {
219 | SQLite3.sqlite3_free(ptr)
220 | }
221 |
222 | func sqlite3_db_mutex(_ db: OpaquePointer?) -> OpaquePointer? {
223 | SQLite3.sqlite3_db_mutex(db)
224 | }
225 |
226 | func sqlite3_mutex_free(_ lock: OpaquePointer?) {
227 | SQLite3.sqlite3_mutex_free(lock)
228 | }
229 |
230 | func sqlite3_mutex_enter(_ lock: OpaquePointer?) {
231 | SQLite3.sqlite3_mutex_enter(lock)
232 | }
233 |
234 | func sqlite3_mutex_leave(_ lock: OpaquePointer?) {
235 | SQLite3.sqlite3_mutex_leave(lock)
236 | }
237 |
238 | func sqlite3_update_hook(_ db: OpaquePointer?, _ callback: sqlite3_update_hook?, _ pArg: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
239 | SQLite3.sqlite3_update_hook(db, callback, pArg)
240 | }
241 |
242 | func sqlite3_trace_v2(_ db: OpaquePointer?, _ mask: sqlite3_unsigned, _ callback: sqlite3_trace_hook?, _ pCtx: UnsafeMutableRawPointer?) -> Int32 {
243 | SQLite3.sqlite3_trace_v2(db, mask, callback, pCtx)
244 | }
245 | }
246 | #endif
247 |
248 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/SQLiteJLibrary.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if SKIP
4 | import Foundation
5 | import OSLog
6 | import SkipFFI
7 |
8 | /// The argument to `sqlite3_update_hook`
9 | public protocol sqlite3_update_hook : NativeCallback {
10 | // public typealias sqlite3_update_hook = @convention(c) (_ updateActionPtr: UnsafeMutableRawPointer?, _ operation: Int32, _ dbname: UnsafePointer?, _ tblname: UnsafePointer?, _ rowid: sqlite3_int64) -> ()
11 | func callback(userData: OpaquePointer?, operation: Int32, databaseName: OpaquePointer?, tableName: OpaquePointer?, rowid: Int64)
12 | }
13 |
14 | /// The argument to `sqlite3_trace_v2`
15 | public protocol sqlite3_trace_hook : NativeCallback {
16 | // public typealias sqlite3_trace_hook = @convention(c) (_ type: UInt32, _ context: UnsafeMutableRawPointer?, _ p: UnsafeMutableRawPointer?, _ px: UnsafeMutableRawPointer?) -> Int32
17 | func callback(type: sqlite3_unsigned, context: OpaquePointer?, p: OpaquePointer?, px: OpaquePointer?) -> Int32
18 | }
19 |
20 |
21 | /// A concrete implementation of the `SQLiteLibrary` interface that declares `external` methods to use [JNA Direct Mapping](https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md) to cache native method lookups.
22 | internal final class SQLiteJNALibrary : SQLiteLibrary {
23 | static let shared = SQLiteJNALibrary()
24 |
25 | private init() {
26 | do {
27 | com.sun.jna.Native.register((SQLiteJNALibrary.self as kotlin.reflect.KClass).java, "sqlite3")
28 | } catch let error as java.lang.UnsatisfiedLinkError { // "Unable to load library 'sqlite3'"
29 | com.sun.jna.Native.register((SQLiteJNALibrary.self as kotlin.reflect.KClass).java, nil as String?)
30 | }
31 | }
32 |
33 | /* SKIP INSERT: external */ func sqlite3_sleep(_ duration: Int32) -> Int32
34 | /* SKIP INSERT: external override */ public func sqlite3_open(_ filename: String, _ ppDb: sqlite3_openarg?) -> Int32
35 | /* SKIP INSERT: external override */ public func sqlite3_open_v2(_ filename: String, _ ppDb: sqlite3_openarg?, _ flags: Int32, _ vfs: String?) -> Int32
36 | /* SKIP INSERT: external */ func sqlite3_close(_ db: OpaquePointer) -> Int32
37 | /* SKIP INSERT: external */ func sqlite3_errcode(_ db: OpaquePointer) -> Int32
38 | /* SKIP INSERT: external */ func sqlite3_errmsg(_ db: OpaquePointer) -> sqlite3_cstring_ptr?
39 | /* SKIP INSERT: external */ func sqlite3_last_insert_rowid(_ db: OpaquePointer) -> Int64
40 | /* SKIP INSERT: external */ func sqlite3_total_changes(_ db: OpaquePointer) -> Int32
41 | /* SKIP INSERT: external */ func sqlite3_changes(_ db: OpaquePointer) -> Int32
42 | // /* SKIP INSERT: external */ func sqlite3_total_changes64(_ db: OpaquePointer) -> Int64
43 | // /* SKIP INSERT: external */ func sqlite3_changes64(_ db: OpaquePointer) -> Int64 // unavailable on Android
44 | /* SKIP INSERT: external */ func sqlite3_interrupt(_ db: OpaquePointer)
45 | /* SKIP INSERT: external override */ public func sqlite3_exec(_ db: OpaquePointer, _ sql: String, _ callback: sqlite3_callback?, _ pArg: UnsafeMutableRawPointer?, _ errmsg: sqlite_error_ptr?) -> Int32
46 | /* SKIP INSERT: external override */ public func sqlite3_prepare_v2(_ db: OpaquePointer, _ sql: String, _ nBytes: Int32, _ ppStmt: sqlite3_openarg, _ tail: sqlite_tail_ptr?) -> Int32
47 | /* SKIP INSERT: external */ func sqlite3_step(_ stmt: OpaquePointer) -> Int32
48 | /* SKIP INSERT: external */ func sqlite3_finalize(_ stmt: OpaquePointer) -> Int32
49 | /* SKIP INSERT: external */ func sqlite3_reset(_ stmt: OpaquePointer) -> Int32
50 | /* SKIP INSERT: external */ func sqlite3_column_count(_ stmt: OpaquePointer) -> Int32
51 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_count(_ stmnt: OpaquePointer) -> Int32
52 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_name(_ stmnt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
53 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_index(_ stmnt: OpaquePointer, _ name: String) -> Int32
54 | /* SKIP INSERT: external */ func sqlite3_clear_bindings(_ stmnt: OpaquePointer) -> Int32
55 | /* SKIP INSERT: external */ func sqlite3_column_name(_ stmt: OpaquePointer!, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
56 | // /* SKIP INSERT: external */ func sqlite3_column_database_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? // unavailable on Android
57 | // /* SKIP INSERT: external */ func sqlite3_column_origin_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
58 | /* SKIP INSERT: external */ func sqlite3_column_decltype(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
59 | /* SKIP INSERT: external */ func sqlite3_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_ptr?
60 | /* SKIP INSERT: external */ func sqlite3_expanded_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_mutptr?
61 | /* SKIP INSERT: external */ func sqlite3_db_handle(_ stmt: OpaquePointer) -> OpaquePointer
62 | /* SKIP INSERT: external */ func sqlite3_bind_null(_ stmt: OpaquePointer, _ paramIndex: Int32) -> Int32
63 | /* SKIP INSERT: external */ func sqlite3_bind_int(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int32) -> Int32
64 | /* SKIP INSERT: external */ func sqlite3_bind_int64(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int64) -> Int32
65 | /* SKIP INSERT: external */ func sqlite3_bind_double(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Double) -> Int32
66 | /* SKIP INSERT: external */ func sqlite3_bind_text(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: String, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
67 | /* SKIP INSERT: external override */ public func sqlite3_bind_blob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: UnsafeRawPointer?, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
68 | /* SKIP INSERT: external */ func sqlite3_bind_zeroblob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ length: Int32) -> Int32
69 | /* SKIP INSERT: external */ func sqlite3_column_type(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
70 | /* SKIP INSERT: external */ func sqlite3_column_int(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
71 | /* SKIP INSERT: external */ func sqlite3_column_int64(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int64
72 | /* SKIP INSERT: external */ func sqlite3_column_double(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Double
73 | /* SKIP INSERT: external */ func sqlite3_column_text(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_uint8_ptr?
74 | /* SKIP INSERT: external */ func sqlite3_column_blob(_ stmt: OpaquePointer, _ columnIndex: Int32) -> UnsafeRawPointer?
75 | /* SKIP INSERT: external */ func sqlite3_column_bytes(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
76 | /* SKIP INSERT: external */ func sqlite3_backup_init(_ destDb: OpaquePointer, _ destName: String, _ sourceDb: OpaquePointer?, _ sourceName: String) -> OpaquePointer
77 | /* SKIP INSERT: external */ func sqlite3_backup_step(_ backup: OpaquePointer, _ pages: Int32) -> Int32
78 | /* SKIP INSERT: external */ func sqlite3_backup_finish(_ backup: OpaquePointer) -> Int32
79 | /* SKIP INSERT: external */ func sqlite3_backup_remaining(_ backup: OpaquePointer) -> Int32
80 | /* SKIP INSERT: external */ func sqlite3_backup_pagecount(_ backup: OpaquePointer) -> Int32
81 | /* SKIP INSERT: external */ func sqlite3_initialize() -> Int32
82 | /* SKIP INSERT: external */ func sqlite3_shutdown() -> Int32
83 | /* SKIP INSERT: external */ func sqlite3_extended_result_codes(_ db: OpaquePointer, _ on: Int32) -> Int32
84 | /* SKIP INSERT: external */ func sqlite3_free(_ ptr: OpaquePointer)
85 | /* SKIP INSERT: external */ func sqlite3_db_mutex(_ db: OpaquePointer?) -> OpaquePointer?
86 | /* SKIP INSERT: external */ func sqlite3_mutex_free(_ lock: OpaquePointer?)
87 | /* SKIP INSERT: external */ func sqlite3_mutex_enter(_ lock: OpaquePointer?)
88 | /* SKIP INSERT: external */ func sqlite3_mutex_leave(_ lock: OpaquePointer?)
89 | /* SKIP INSERT: external */ func sqlite3_update_hook(_ db: OpaquePointer?, _ callback: sqlite3_update_hook?, _ pArg: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?
90 | /* SKIP INSERT: external */ func sqlite3_trace_v2(_ db: OpaquePointer?, _ mask: sqlite3_unsigned, _ callback: sqlite3_trace_hook?, _ pCtx: UnsafeMutableRawPointer?) -> Int32
91 | }
92 |
93 | #endif
94 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/SQLiteLibrary.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if SKIP
4 | import SkipFFI
5 |
6 | public typealias NativeLibrary = com.sun.jna.Library
7 | public typealias NativeCallback = com.sun.jna.Callback
8 |
9 | public typealias sqlite3_openarg = UnsafeMutableRawPointer
10 | public typealias sqlite3_cstring_ptr = OpaquePointer
11 | public typealias sqlite3_cstring_mutptr = OpaquePointer
12 | public typealias sqlite3_uint8_ptr = OpaquePointer
13 | public typealias sqlite_error_ptr = UnsafeMutableRawPointer
14 | public typealias sqlite3_destructor_type = Int64
15 | public typealias sqlite3_callback = UnsafeMutableRawPointer
16 |
17 | public typealias UnsafeRawPointer = OpaquePointer
18 | public typealias sqlite_tail_ptr = UnsafeMutableRawPointer
19 |
20 | //public typealias sqlite3_pointer_type = UnsafeMutableRawPointer
21 | public typealias sqlite3_pointer_type = OpaquePointer
22 |
23 | public typealias sqlite3_unsigned = Int32 // JNA has no UInt understanding
24 |
25 | #else
26 | public typealias NativeLibrary = AnyObject
27 | public typealias NativeCallback = AnyObject
28 |
29 | public typealias sqlite3_openarg = UnsafeMutablePointer // UnsafeMutableRawPointer?
30 | public typealias sqlite3_cstring_ptr = UnsafePointer
31 | public typealias sqlite3_cstring_mutptr = UnsafeMutablePointer
32 | public typealias sqlite3_uint8_ptr = UnsafePointer
33 |
34 | public typealias sqlite_error_ptr = UnsafeMutablePointer?>
35 | //typealias sqlite3_destructor_type = (@convention(c) (UnsafeMutableRawPointer?) -> Void)
36 | public typealias sqlite_tail_ptr = UnsafeMutablePointer?>
37 |
38 | public typealias sqlite3_unsigned = UInt32
39 | public typealias sqlite3_pointer_type = UnsafeMutableRawPointer
40 | #endif
41 |
42 | public protocol SQLiteLibrary : NativeLibrary {
43 | func sqlite3_sleep(_ duration: Int32) -> Int32
44 |
45 | // Database Connection API
46 | func sqlite3_open(_ filename: String, _ ppDb: sqlite3_openarg?) -> Int32
47 | func sqlite3_open_v2(_ filename: String, _ ppDb: sqlite3_openarg?, _ flags: Int32, _ vfs: String?) -> Int32
48 | func sqlite3_close(_ db: OpaquePointer) -> Int32
49 | func sqlite3_errcode(_ db: OpaquePointer) -> Int32
50 | func sqlite3_errmsg(_ db: OpaquePointer) -> sqlite3_cstring_ptr?
51 | func sqlite3_last_insert_rowid(_ db: OpaquePointer) -> Int64
52 | func sqlite3_total_changes(_ db: OpaquePointer) -> Int32
53 | func sqlite3_changes(_ db: OpaquePointer) -> Int32
54 | func sqlite3_interrupt(_ db: OpaquePointer)
55 |
56 | func sqlite3_exec(_ db: OpaquePointer, _ sql: String, _ callback: sqlite3_callback?, _ pArg: UnsafeMutableRawPointer?, _ errmsg: sqlite_error_ptr?) -> Int32
57 | func sqlite3_prepare_v2(_ db: OpaquePointer, _ sql: String, _ nBytes: Int32, _ ppStmt: sqlite3_openarg, _ tail: sqlite_tail_ptr?) -> Int32
58 |
59 | // Statement API
60 | func sqlite3_step(_ stmt: OpaquePointer) -> Int32
61 | func sqlite3_finalize(_ stmt: OpaquePointer) -> Int32
62 | func sqlite3_reset(_ stmt: OpaquePointer) -> Int32
63 | func sqlite3_column_count(_ stmt: OpaquePointer) -> Int32
64 | func sqlite3_bind_parameter_count(_ stmnt: OpaquePointer) -> Int32
65 | func sqlite3_bind_parameter_name(_ stmnt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
66 | func sqlite3_bind_parameter_index(_ stmnt: OpaquePointer, _ name: String) -> Int32
67 | func sqlite3_clear_bindings(_ stmnt: OpaquePointer) -> Int32
68 |
69 | func sqlite3_column_name(_ stmt: OpaquePointer!, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
70 |
71 | // Unavailable in Android's sqlite build
72 | //func sqlite3_column_table_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
73 |
74 | //func sqlite3_column_origin_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
75 | func sqlite3_column_decltype(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
76 |
77 | func sqlite3_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_ptr?
78 | func sqlite3_expanded_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_mutptr?
79 | func sqlite3_db_handle(_ stmt: OpaquePointer) -> OpaquePointer
80 |
81 | // Parameter Binding
82 | func sqlite3_bind_null(_ stmt: OpaquePointer, _ paramIndex: Int32) -> Int32
83 | func sqlite3_bind_int(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int32) -> Int32
84 | func sqlite3_bind_int64(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int64) -> Int32
85 | func sqlite3_bind_double(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Double) -> Int32
86 | func sqlite3_bind_text(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: String, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
87 | func sqlite3_bind_blob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: UnsafeRawPointer?, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
88 | func sqlite3_bind_zeroblob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ length: Int32) -> Int32
89 |
90 |
91 | // Column Value API
92 | func sqlite3_column_type(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
93 | func sqlite3_column_int(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
94 | func sqlite3_column_int64(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int64
95 | func sqlite3_column_double(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Double
96 | func sqlite3_column_text(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_uint8_ptr?
97 | func sqlite3_column_blob(_ stmt: OpaquePointer, _ columnIndex: Int32) -> UnsafeRawPointer?
98 | func sqlite3_column_bytes(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
99 |
100 | // Backup API
101 | func sqlite3_backup_init(_ destDb: OpaquePointer, _ destName: String, _ sourceDb: OpaquePointer?, _ sourceName: String) -> OpaquePointer
102 | func sqlite3_backup_step(_ backup: OpaquePointer, _ pages: Int32) -> Int32
103 | func sqlite3_backup_finish(_ backup: OpaquePointer) -> Int32
104 | func sqlite3_backup_remaining(_ backup: OpaquePointer) -> Int32
105 | func sqlite3_backup_pagecount(_ backup: OpaquePointer) -> Int32
106 |
107 | // Other Functions
108 | func sqlite3_initialize() -> Int32
109 | func sqlite3_shutdown() -> Int32
110 | //func sqlite3_config(option: Int32, values: Object...) -> Int32
111 | func sqlite3_extended_result_codes(_ db: OpaquePointer, _ on: Int32) -> Int32
112 | #if SKIP
113 | // otherwise: 'sqlite3_free' hides member of supertype 'SQLiteLibrary' and needs an 'override' modifier.
114 | func sqlite3_free(_ ptr: OpaquePointer)
115 | #else
116 | func sqlite3_free(_ ptr: sqlite3_pointer_type)
117 | #endif
118 |
119 | // Locks
120 | func sqlite3_db_mutex(_ db: OpaquePointer?) -> OpaquePointer?
121 | func sqlite3_mutex_free(_ lock: OpaquePointer?)
122 | func sqlite3_mutex_enter(_ lock: OpaquePointer?)
123 | func sqlite3_mutex_leave(_ lock: OpaquePointer?)
124 | //func int sqlite3_mutex_try(sqlite3_mutex*);
125 |
126 | func sqlite3_update_hook(_ db: OpaquePointer?, _ callback: sqlite3_update_hook?, _ pArg: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?
127 |
128 | func sqlite3_trace_v2(_ db: OpaquePointer?, _ mask: sqlite3_unsigned, _ callback: sqlite3_trace_hook?, _ pCtx: UnsafeMutableRawPointer?) -> Int32
129 | }
130 |
--------------------------------------------------------------------------------
/Sources/SkipSQL/Skip/skip.yml:
--------------------------------------------------------------------------------
1 | # skip.tools per-configuration file
2 |
3 | #skip:
4 | # package: 'skip.sql'
5 |
6 | # the blocks to add to the build.gradle.kts
7 | build:
8 | contents:
9 | - block: 'dependencies'
10 | contents:
11 |
--------------------------------------------------------------------------------
/Sources/SkipSQLPlus/SQLPlus.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | import SkipSQL
4 |
5 | extension SQLiteConfiguration {
6 | /// The platform-provided SQLite library.
7 | ///
8 | /// This will use the the vendored sqlite libraries that are provided by the operating system.
9 | /// The version will vary.
10 | public static let plus: SQLiteConfiguration = {
11 | #if SKIP
12 | SQLiteConfiguration(library: SQLPlusJNALibrary.shared)
13 | #else
14 | SQLiteConfiguration(library: SQLPlusCLibrary.shared)
15 | #endif
16 | }()
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/SkipSQLPlus/SQLPlusCLibrary.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if !SKIP
4 | import SQLExt
5 | import SkipSQL
6 |
7 | /// A `SQLiteLibrary` implementation that uses the locally built `SQLExt` library
8 | /// to provide a consistent SQLite build with full-text-search (FTS) and encryption (sqlcipher)
9 | /// extensions enabled.
10 | internal final class SQLPlusCLibrary : SQLiteLibrary {
11 | static let shared = SQLPlusCLibrary()
12 |
13 | init() {
14 | }
15 |
16 | func sqlite3_sleep(_ duration: Int32) -> Int32 {
17 | SQLExt.sqlite3_sleep(duration)
18 | }
19 |
20 | func sqlite3_open(_ filename: String, _ ppDb: sqlite3_openarg?) -> Int32 {
21 | SQLExt.sqlite3_open(filename, ppDb)
22 | }
23 |
24 | func sqlite3_open_v2(_ filename: String, _ ppDb: sqlite3_openarg?, _ flags: Int32, _ vfs: String?) -> Int32 {
25 | SQLExt.sqlite3_open_v2(filename, ppDb, flags, vfs)
26 | }
27 |
28 | func sqlite3_close(_ db: OpaquePointer) -> Int32 {
29 | SQLExt.sqlite3_close(db)
30 | }
31 |
32 | func sqlite3_errcode(_ db: OpaquePointer) -> Int32 {
33 | SQLExt.sqlite3_errcode(db)
34 | }
35 |
36 | func sqlite3_errmsg(_ db: OpaquePointer) -> sqlite3_cstring_ptr? {
37 | SQLExt.sqlite3_errmsg(db)
38 | }
39 |
40 | func sqlite3_last_insert_rowid(_ db: OpaquePointer) -> Int64 {
41 | SQLExt.sqlite3_last_insert_rowid(db)
42 | }
43 |
44 | func sqlite3_total_changes(_ db: OpaquePointer) -> Int32 {
45 | SQLExt.sqlite3_total_changes(db)
46 | }
47 |
48 | func sqlite3_changes(_ db: OpaquePointer) -> Int32 {
49 | SQLExt.sqlite3_changes(db)
50 | }
51 |
52 | func sqlite3_interrupt(_ db: OpaquePointer) {
53 | SQLExt.sqlite3_interrupt(db)
54 | }
55 |
56 | func sqlite3_exec(_ db: OpaquePointer, _ sql: String, _ callback: sqlite3_callback?, _ pArg: UnsafeMutableRawPointer?, _ errmsg: sqlite_error_ptr?) -> Int32 {
57 | SQLExt.sqlite3_exec(db, sql, callback, pArg, errmsg)
58 | }
59 |
60 | func sqlite3_prepare_v2(_ db: OpaquePointer, _ sql: String, _ nBytes: Int32, _ ppStmt: sqlite3_openarg, _ tail: UnsafeMutablePointer?>?) -> Int32 {
61 | SQLExt.sqlite3_prepare_v2(db, sql, nBytes, ppStmt, tail)
62 | }
63 |
64 | func sqlite3_step(_ stmt: OpaquePointer) -> Int32 {
65 | SQLExt.sqlite3_step(stmt)
66 | }
67 |
68 | func sqlite3_finalize(_ stmt: OpaquePointer) -> Int32 {
69 | SQLExt.sqlite3_finalize(stmt)
70 | }
71 |
72 | func sqlite3_reset(_ stmt: OpaquePointer) -> Int32 {
73 | SQLExt.sqlite3_reset(stmt)
74 | }
75 |
76 | func sqlite3_column_count(_ stmt: OpaquePointer) -> Int32 {
77 | SQLExt.sqlite3_column_count(stmt)
78 | }
79 |
80 | func sqlite3_bind_parameter_count(_ stmnt: OpaquePointer) -> Int32 {
81 | SQLExt.sqlite3_bind_parameter_count(stmnt)
82 | }
83 |
84 | func sqlite3_bind_parameter_name(_ stmnt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
85 | SQLExt.sqlite3_bind_parameter_name(stmnt, columnIndex)
86 | }
87 |
88 | func sqlite3_bind_parameter_index(_ stmnt: OpaquePointer, _ name: String) -> Int32 {
89 | SQLExt.sqlite3_bind_parameter_index(stmnt, name)
90 | }
91 |
92 | func sqlite3_clear_bindings(_ stmnt: OpaquePointer) -> Int32 {
93 | SQLExt.sqlite3_clear_bindings(stmnt)
94 | }
95 |
96 | func sqlite3_column_name(_ stmt: OpaquePointer!, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
97 | SQLExt.sqlite3_column_name(stmt!, columnIndex)
98 | }
99 |
100 | func sqlite3_column_decltype(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? {
101 | SQLExt.sqlite3_column_decltype(stmt, columnIndex)
102 | }
103 |
104 | func sqlite3_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_ptr? {
105 | SQLExt.sqlite3_sql(stmt)
106 | }
107 |
108 | func sqlite3_expanded_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_mutptr? {
109 | SQLExt.sqlite3_expanded_sql(stmt)
110 | }
111 |
112 | func sqlite3_db_handle(_ stmt: OpaquePointer) -> OpaquePointer {
113 | SQLExt.sqlite3_db_handle(stmt)
114 | }
115 |
116 | func sqlite3_bind_null(_ stmt: OpaquePointer, _ paramIndex: Int32) -> Int32 {
117 | SQLExt.sqlite3_bind_null(stmt, paramIndex)
118 | }
119 |
120 | func sqlite3_bind_int(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int32) -> Int32 {
121 | SQLExt.sqlite3_bind_int(stmt, paramIndex, value)
122 | }
123 |
124 | func sqlite3_bind_int64(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int64) -> Int32 {
125 | SQLExt.sqlite3_bind_int64(stmt, paramIndex, value)
126 | }
127 |
128 | func sqlite3_bind_double(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Double) -> Int32 {
129 | SQLExt.sqlite3_bind_double(stmt, paramIndex, value)
130 | }
131 |
132 | func sqlite3_bind_text(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: String, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32 {
133 | SQLExt.sqlite3_bind_text(stmt, paramIndex, value, length, destructor)
134 | }
135 |
136 | func sqlite3_bind_blob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: UnsafeRawPointer?, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32 {
137 | SQLExt.sqlite3_bind_blob(stmt, paramIndex, value, length, destructor)
138 | }
139 |
140 | func sqlite3_bind_zeroblob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ length: Int32) -> Int32 {
141 | SQLExt.sqlite3_bind_zeroblob(stmt, paramIndex, length)
142 | }
143 |
144 | func sqlite3_column_type(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
145 | SQLExt.sqlite3_column_type(stmt, columnIndex)
146 | }
147 |
148 | func sqlite3_column_int(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
149 | SQLExt.sqlite3_column_int(stmt, columnIndex)
150 | }
151 |
152 | func sqlite3_column_int64(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int64 {
153 | SQLExt.sqlite3_column_int64(stmt, columnIndex)
154 | }
155 |
156 | func sqlite3_column_double(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Double {
157 | SQLExt.sqlite3_column_double(stmt, columnIndex)
158 | }
159 |
160 | func sqlite3_column_text(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_uint8_ptr? {
161 | SQLExt.sqlite3_column_text(stmt, columnIndex)
162 | }
163 |
164 | func sqlite3_column_blob(_ stmt: OpaquePointer, _ columnIndex: Int32) -> UnsafeRawPointer? {
165 | SQLExt.sqlite3_column_blob(stmt, columnIndex)
166 | }
167 |
168 | func sqlite3_column_bytes(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32 {
169 | SQLExt.sqlite3_column_bytes(stmt, columnIndex)
170 | }
171 |
172 | func sqlite3_backup_init(_ destDb: OpaquePointer, _ destName: String, _ sourceDb: OpaquePointer?, _ sourceName: String) -> OpaquePointer {
173 | SQLExt.sqlite3_backup_init(destDb, destName, sourceDb, sourceName)
174 | }
175 |
176 | func sqlite3_backup_step(_ backup: OpaquePointer, _ pages: Int32) -> Int32 {
177 | SQLExt.sqlite3_backup_step(backup, pages)
178 | }
179 |
180 | func sqlite3_backup_finish(_ backup: OpaquePointer) -> Int32 {
181 | SQLExt.sqlite3_backup_finish(backup)
182 | }
183 |
184 | func sqlite3_backup_remaining(_ backup: OpaquePointer) -> Int32 {
185 | SQLExt.sqlite3_backup_remaining(backup)
186 | }
187 |
188 | func sqlite3_backup_pagecount(_ backup: OpaquePointer) -> Int32 {
189 | SQLExt.sqlite3_backup_pagecount(backup)
190 | }
191 |
192 | func sqlite3_initialize() -> Int32 {
193 | SQLExt.sqlite3_initialize()
194 | }
195 |
196 | func sqlite3_shutdown() -> Int32 {
197 | SQLExt.sqlite3_shutdown()
198 | }
199 |
200 | func sqlite3_extended_result_codes(_ db: OpaquePointer, _ on: Int32) -> Int32 {
201 | SQLExt.sqlite3_extended_result_codes(db, on)
202 | }
203 |
204 | func sqlite3_free(_ ptr: sqlite3_pointer_type) {
205 | SQLExt.sqlite3_free(ptr)
206 | }
207 |
208 | func sqlite3_db_mutex(_ db: OpaquePointer?) -> OpaquePointer? {
209 | SQLExt.sqlite3_db_mutex(db)
210 | }
211 |
212 | func sqlite3_mutex_free(_ lock: OpaquePointer?) {
213 | SQLExt.sqlite3_mutex_free(lock)
214 | }
215 |
216 | func sqlite3_mutex_enter(_ lock: OpaquePointer?) {
217 | SQLExt.sqlite3_mutex_enter(lock)
218 | }
219 |
220 | func sqlite3_mutex_leave(_ lock: OpaquePointer?) {
221 | SQLExt.sqlite3_mutex_leave(lock)
222 | }
223 |
224 | func sqlite3_update_hook(_ db: OpaquePointer?, _ callback: sqlite3_update_hook?, _ pArg: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
225 | SQLExt.sqlite3_update_hook(db, callback, pArg)
226 | }
227 |
228 | func sqlite3_trace_v2(_ db: OpaquePointer?, _ mask: sqlite3_unsigned, _ callback: sqlite3_trace_hook?, _ pCtx: UnsafeMutableRawPointer?) -> Int32 {
229 | SQLExt.sqlite3_trace_v2(db, mask, callback, pCtx)
230 | }
231 | }
232 | #endif
233 |
234 |
--------------------------------------------------------------------------------
/Sources/SkipSQLPlus/SQLPlusJLibrary.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if SKIP
4 | import Foundation
5 | import OSLog
6 | import SkipFFI
7 | import SkipSQL
8 |
9 | /// A concrete implementation of the `SQLiteLibrary` interface that declared `external` methods to use [JNA Direct Mapping](https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md) to cache native method lookups.
10 | ///
11 | /// Note that this is identical to the `SkipSQL.SQLLiteJNALibrary`, but it is registered
12 | /// to the locally-built `sqlext` library.
13 | internal final class SQLPlusJNALibrary : SQLiteLibrary {
14 | static let shared = registerNatives(SQLPlusJNALibrary(), frameworkName: "SkipSQLPlus", libraryName: "sqlext")
15 |
16 | /* SKIP INSERT: external */ func sqlite3_sleep(_ duration: Int32) -> Int32
17 | /* SKIP INSERT: external override */ public func sqlite3_open(_ filename: String, _ ppDb: sqlite3_openarg?) -> Int32
18 | /* SKIP INSERT: external override */ public func sqlite3_open_v2(_ filename: String, _ ppDb: sqlite3_openarg?, _ flags: Int32, _ vfs: String?) -> Int32
19 | /* SKIP INSERT: external */ func sqlite3_close(_ db: OpaquePointer) -> Int32
20 | /* SKIP INSERT: external */ func sqlite3_errcode(_ db: OpaquePointer) -> Int32
21 | /* SKIP INSERT: external */ func sqlite3_errmsg(_ db: OpaquePointer) -> sqlite3_cstring_ptr?
22 | /* SKIP INSERT: external */ func sqlite3_last_insert_rowid(_ db: OpaquePointer) -> Int64
23 | /* SKIP INSERT: external */ func sqlite3_total_changes(_ db: OpaquePointer) -> Int32
24 | /* SKIP INSERT: external */ func sqlite3_changes(_ db: OpaquePointer) -> Int32
25 | // /* SKIP INSERT: external */ func sqlite3_total_changes64(_ db: OpaquePointer) -> Int64
26 | // /* SKIP INSERT: external */ func sqlite3_changes64(_ db: OpaquePointer) -> Int64 // unavailable on Android
27 | /* SKIP INSERT: external */ func sqlite3_interrupt(_ db: OpaquePointer)
28 | /* SKIP INSERT: external override */ public func sqlite3_exec(_ db: OpaquePointer, _ sql: String, _ callback: sqlite3_callback?, _ pArg: UnsafeMutableRawPointer?, _ errmsg: sqlite_error_ptr?) -> Int32
29 | /* SKIP INSERT: external override */ public func sqlite3_prepare_v2(_ db: OpaquePointer, _ sql: String, _ nBytes: Int32, _ ppStmt: sqlite3_openarg, _ tail: sqlite_tail_ptr?) -> Int32
30 | /* SKIP INSERT: external */ func sqlite3_step(_ stmt: OpaquePointer) -> Int32
31 | /* SKIP INSERT: external */ func sqlite3_finalize(_ stmt: OpaquePointer) -> Int32
32 | /* SKIP INSERT: external */ func sqlite3_reset(_ stmt: OpaquePointer) -> Int32
33 | /* SKIP INSERT: external */ func sqlite3_column_count(_ stmt: OpaquePointer) -> Int32
34 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_count(_ stmnt: OpaquePointer) -> Int32
35 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_name(_ stmnt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
36 | /* SKIP INSERT: external */ func sqlite3_bind_parameter_index(_ stmnt: OpaquePointer, _ name: String) -> Int32
37 | /* SKIP INSERT: external */ func sqlite3_clear_bindings(_ stmnt: OpaquePointer) -> Int32
38 | /* SKIP INSERT: external */ func sqlite3_column_name(_ stmt: OpaquePointer!, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
39 | // /* SKIP INSERT: external */ func sqlite3_column_database_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr? // unavailable on Android
40 | // /* SKIP INSERT: external */ func sqlite3_column_origin_name(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
41 | /* SKIP INSERT: external */ func sqlite3_column_decltype(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_cstring_ptr?
42 | /* SKIP INSERT: external */ func sqlite3_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_ptr?
43 | /* SKIP INSERT: external */ func sqlite3_expanded_sql(_ stmt: OpaquePointer) -> sqlite3_cstring_mutptr?
44 | /* SKIP INSERT: external */ func sqlite3_db_handle(_ stmt: OpaquePointer) -> OpaquePointer
45 | /* SKIP INSERT: external */ func sqlite3_bind_null(_ stmt: OpaquePointer, _ paramIndex: Int32) -> Int32
46 | /* SKIP INSERT: external */ func sqlite3_bind_int(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int32) -> Int32
47 | /* SKIP INSERT: external */ func sqlite3_bind_int64(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Int64) -> Int32
48 | /* SKIP INSERT: external */ func sqlite3_bind_double(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: Double) -> Int32
49 | /* SKIP INSERT: external */ func sqlite3_bind_text(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: String, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
50 | /* SKIP INSERT: external override */ public func sqlite3_bind_blob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ value: UnsafeRawPointer?, _ length: Int32, _ destructor: sqlite3_destructor_type) -> Int32
51 | /* SKIP INSERT: external */ func sqlite3_bind_zeroblob(_ stmt: OpaquePointer, _ paramIndex: Int32, _ length: Int32) -> Int32
52 | /* SKIP INSERT: external */ func sqlite3_column_type(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
53 | /* SKIP INSERT: external */ func sqlite3_column_int(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
54 | /* SKIP INSERT: external */ func sqlite3_column_int64(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int64
55 | /* SKIP INSERT: external */ func sqlite3_column_double(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Double
56 | /* SKIP INSERT: external */ func sqlite3_column_text(_ stmt: OpaquePointer, _ columnIndex: Int32) -> sqlite3_uint8_ptr?
57 | /* SKIP INSERT: external */ func sqlite3_column_blob(_ stmt: OpaquePointer, _ columnIndex: Int32) -> UnsafeRawPointer?
58 | /* SKIP INSERT: external */ func sqlite3_column_bytes(_ stmt: OpaquePointer, _ columnIndex: Int32) -> Int32
59 | /* SKIP INSERT: external */ func sqlite3_backup_init(_ destDb: OpaquePointer, _ destName: String, _ sourceDb: OpaquePointer?, _ sourceName: String) -> OpaquePointer
60 | /* SKIP INSERT: external */ func sqlite3_backup_step(_ backup: OpaquePointer, _ pages: Int32) -> Int32
61 | /* SKIP INSERT: external */ func sqlite3_backup_finish(_ backup: OpaquePointer) -> Int32
62 | /* SKIP INSERT: external */ func sqlite3_backup_remaining(_ backup: OpaquePointer) -> Int32
63 | /* SKIP INSERT: external */ func sqlite3_backup_pagecount(_ backup: OpaquePointer) -> Int32
64 | /* SKIP INSERT: external */ func sqlite3_initialize() -> Int32
65 | /* SKIP INSERT: external */ func sqlite3_shutdown() -> Int32
66 | /* SKIP INSERT: external */ func sqlite3_extended_result_codes(_ db: OpaquePointer, _ on: Int32) -> Int32
67 | /* SKIP INSERT: external */ func sqlite3_free(_ ptr: OpaquePointer)
68 | /* SKIP INSERT: external */ func sqlite3_db_mutex(_ db: OpaquePointer?) -> OpaquePointer?
69 | /* SKIP INSERT: external */ func sqlite3_mutex_free(_ lock: OpaquePointer?)
70 | /* SKIP INSERT: external */ func sqlite3_mutex_enter(_ lock: OpaquePointer?)
71 | /* SKIP INSERT: external */ func sqlite3_mutex_leave(_ lock: OpaquePointer?)
72 | /* SKIP INSERT: external */ func sqlite3_update_hook(_ db: OpaquePointer?, _ callback: sqlite3_update_hook?, _ pArg: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?
73 | /* SKIP INSERT: external */ func sqlite3_trace_v2(_ db: OpaquePointer?, _ mask: sqlite3_unsigned, _ callback: sqlite3_trace_hook?, _ pCtx: UnsafeMutableRawPointer?) -> Int32
74 | }
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/Sources/SkipSQLPlus/Skip/skip.yml:
--------------------------------------------------------------------------------
1 | # skip.tools per-configuration file
2 |
3 | #skip:
4 | # package: 'skip.sql'
5 |
6 | # the blocks to add to the build.gradle.kts
7 | build:
8 | contents:
9 | - block: 'dependencies'
10 | contents:
11 |
--------------------------------------------------------------------------------
/Tests/SkipSQLPlusTests/SQLContextTestConfiguration.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | import SkipSQL
4 | import SkipSQLPlus
5 |
6 | extension SQLiteConfiguration {
7 | /// The shared SQLContextTests uses thus local variable to determine the configuration to use
8 | public static let test = SQLiteConfiguration.plus
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/SkipSQLPlusTests/SQLContextTests.swift:
--------------------------------------------------------------------------------
1 | ../SkipSQLTests/SQLContextTests.swift
--------------------------------------------------------------------------------
/Tests/SkipSQLPlusTests/SQLPlusTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | import XCTest
4 | import OSLog
5 | import Foundation
6 | import SkipSQL
7 | import SkipSQLPlus
8 |
9 | final class SQLPlusTests: XCTestCase {
10 | let logger: Logger = Logger(subsystem: "skip.sql", category: "SQLPlusTests")
11 |
12 | func testSQLPlus() throws {
13 | let sqlplus = SQLContext(configuration: .plus)
14 | _ = try sqlplus.query(sql: "SELECT 1")
15 | _ = try sqlplus.query(sql: "SELECT CURRENT_TIMESTAMP")
16 | _ = try sqlplus.query(sql: "PRAGMA compile_options")
17 |
18 | // ensure that FTS works
19 | _ = try sqlplus.query(sql: "CREATE VIRTUAL TABLE \"documents\" USING fts5(content)")
20 |
21 | let stmnt = try sqlplus.prepare(sql: "SELECT 1")
22 | XCTAssertEqual("SELECT 1", stmnt.sql)
23 |
24 | XCTAssertEqual(0, stmnt.parameterCount)
25 | try stmnt.close()
26 |
27 | // the locally built SQLite version (contrast with the macOS version 3.43.2)
28 | XCTAssertEqual([SQLValue.text("3.46.1")], try sqlplus.query(sql: "SELECT sqlite_version()").first)
29 | XCTAssertEqual([SQLValue.text("ATOMIC_INTRINSICS=1")], try sqlplus.query(sql: "PRAGMA compile_options").first)
30 | XCTAssertEqual([SQLValue.text("4.6.1 community")], try sqlplus.query(sql: "PRAGMA cipher_version").first)
31 | //XCTAssertEqual([SQLValue.text("PRAGMA cipher_default_kdf_iter = 256000")], try sqlplus.query(sql: "PRAGMA cipher_default_settings").first)
32 | //XCTAssertEqual([SQLValue.text("XXX")], try sqlplus.query(sql: "PRAGMA cipher_provider").first)
33 | //XCTAssertEqual([SQLValue.text("XXX")], try sqlplus.query(sql: "PRAGMA cipher_provider_version").first)
34 | }
35 |
36 | func testSQLiteJSON() throws {
37 | let sqlplus = SQLContext(configuration: .plus)
38 | // The $[#] path feature in the JSON functions was added in version 3.31.0
39 | XCTAssertEqual([SQLValue.text("3.46.1")], try sqlplus.query(sql: "SELECT sqlite_version()").first)
40 |
41 | try sqlplus.exec(sql: #"CREATE TABLE users (id INTEGER PRIMARY KEY, profile JSON)"#)
42 |
43 | try sqlplus.exec(sql: #"INSERT INTO users (id, profile) VALUES (1, ?)"#, parameters: [.text(#"{"name": "Alice", "age": 30}"#)])
44 | try sqlplus.exec(sql: #"INSERT INTO users (id, profile) VALUES (2, ?)"#, parameters: [.text(#"{"name": "Bob", "age": 25}"#)])
45 |
46 | let j1 = try sqlplus.query(sql: "SELECT json_extract(profile, '$.name') as name FROM users WHERE id = ?", parameters: [.integer(1)]).first
47 | XCTAssertEqual([.text("Alice")], j1)
48 |
49 | let j2 = try sqlplus.query(sql: "SELECT json_extract(profile, '$.name') as name, json_extract(profile, '$.age') as age FROM users WHERE id = ?", parameters: [.integer(2)]).first
50 | XCTAssertEqual([.text("Bob"), .integer(25)], j2)
51 |
52 | XCTAssertEqual([.text("[1]")], try sqlplus.query(sql: "SELECT JSON_QUOTE(JSON('[1]'))").first)
53 | XCTAssertEqual([.integer(0)], try sqlplus.query(sql: "SELECT JSON_VALID('{\"x\":35')").first)
54 | XCTAssertEqual([.text("array")], try sqlplus.query(sql: "SELECT JSON_TYPE('{\"a\":[2,3.5,true,false,null,\"x\"]}', '$.a')").first)
55 | XCTAssertEqual([.text("[1,3,4]")], try sqlplus.query(sql: "SELECT JSON_REMOVE('[0,1,2,3,4]', '$[2]','$[0]')").first)
56 | XCTAssertEqual([.text("[1,3,4]")], try sqlplus.query(sql: "SELECT JSON_REMOVE('[0,1,2,3,4]', '$[2]','$[0]')").first)
57 | XCTAssertEqual([.text("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}")], try sqlplus.query(sql: "SELECT JSON_PATCH('{\"a\":1,\"b\":2}','{\"c\":3,\"d\":4}')").first)
58 | XCTAssertEqual([.text("{\"c\":{\"e\":5}}")], try sqlplus.query(sql: "SELECT JSON_OBJECT('c', JSON('{\"e\":5}'))").first)
59 | XCTAssertEqual([.text("{\"a\":99,\"c\":4}")], try sqlplus.query(sql: "SELECT JSON_SET('{\"a\":2,\"c\":4}', '$.a', 99)").first)
60 | XCTAssertEqual([.text("{\"a\":99,\"c\":4}")], try sqlplus.query(sql: "SELECT JSON_REPLACE('{\"a\":2,\"c\":4}', '$.a', 99)").first)
61 | XCTAssertEqual([.text("[1,2,3,4,99]")], try sqlplus.query(sql: "SELECT JSON_INSERT('[1,2,3,4]','$[#]',99)").first)
62 | XCTAssertEqual([.text("[[4,5],2]")], try sqlplus.query(sql: "SELECT JSON_EXTRACT('{\"a\":2,\"c\":[4,5]}','$.c','$.a')").first)
63 | XCTAssertEqual([.integer(3)], try sqlplus.query(sql: "SELECT JSON_ARRAY_LENGTH('{\"one\":[1,2,3]}', '$.one')").first)
64 | XCTAssertEqual([.integer(4)], try sqlplus.query(sql: "SELECT JSON_ARRAY_LENGTH('[1,2,3,4]')").first)
65 | XCTAssertEqual([.text("[1,2,\"3\",4]")], try sqlplus.query(sql: "SELECT JSON_ARRAY(1, 2, '3', 4)").first)
66 | XCTAssertEqual([.text("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}")], try sqlplus.query(sql: "SELECT JSON_PATCH('{\"a\":1,\"b\":2}', '{\"c\":3,\"d\":4}')").first)
67 | }
68 |
69 | func testSQLCipher() throws {
70 | func createDB(key: String?, plaintextHeader: Int? = nil, string: String) throws -> Data {
71 | let dbPath = URL.temporaryDirectory.appendingPathComponent(UUID().uuidString).appendingPathExtension("db")
72 |
73 | logger.log("testEncryption: checking db: \(dbPath.path)")
74 | let db = try SQLContext(path: dbPath.path, flags: [.create, .readWrite], configuration: .plus)
75 | if let key = key {
76 | _ = try db.query(sql: "PRAGMA key = '\(key)'")
77 | }
78 | if let plaintextHeader = plaintextHeader {
79 | _ = try db.query(sql: "PRAGMA cipher_plaintext_header_size = \(plaintextHeader)")
80 | }
81 |
82 | //_ = try db.query(sql: #"PRAGMA cipher_plaintext_header_size = 32"#)
83 | //_ = try db.query(sql: #"PRAGMA cipher_salt = "x'01010101010101010101010101010101'""#)
84 | //_ = try db.query(sql: #"PRAGMA user_version = 1; -- force header write"#)
85 |
86 | try db.exec(sql: #"CREATE TABLE SOME_TABLE(col)"#)
87 | try db.exec(sql: #"INSERT INTO SOME_TABLE(col) VALUES(?)"#, parameters: [.text(string)])
88 |
89 | try db.close()
90 |
91 | let dbContents = try Data(contentsOf: dbPath)
92 | return dbContents
93 | }
94 |
95 | let str = "SOME_STRING"
96 | let data1 = try createDB(key: nil, string: str)
97 | let data2 = try createDB(key: "passkey", string: str)
98 | let data3 = try createDB(key: "passkey", plaintextHeader: 32, string: str)
99 |
100 | // check the header of the database file
101 | // an encrypted data (that does not use PRAGMA cipher_plaintext_header_size = X) should not contains the standard sqlite header
102 | let sqliteHeader = "SQLite format 3"
103 | XCTAssertEqual(sqliteHeader.utf8.hex(), "53514c69746520666f726d61742033")
104 |
105 | XCTAssertTrue(data1.hex().hasPrefix(sqliteHeader.utf8.hex()), "unencrypted database should have contained the SQLite header")
106 | XCTAssertFalse(data2.hex().hasPrefix(sqliteHeader.utf8.hex()), "encrypted database should not have contained the SQLite header")
107 | XCTAssertTrue(data3.hex().hasPrefix(sqliteHeader.utf8.hex()), "encrypted database should have contained the SQLite header when using cipher_plaintext_header_size")
108 |
109 | XCTAssertTrue(data1.hex().contains(str.utf8.hex()), "unencrypted database should have contained the test string")
110 | XCTAssertFalse(data2.hex().contains(str.utf8.hex()), "encrypted database should not have contained the test string")
111 | XCTAssertFalse(data3.hex().contains(str.utf8.hex()), "encrypted database should not have contained the test string")
112 |
113 |
114 | }
115 | }
116 |
117 | extension Sequence where Element == UInt8 {
118 | /// Convert this sequence of bytes into a hex string
119 | public func hex() -> String {
120 | #if SKIP
121 | // java.util.IllegalFormatConversionException: x != kotlin.UByte
122 | //map { String(format: "%02x", $0) }.joined()
123 | // This declaration needs opt-in. Its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)'
124 | //kotlin.ByteArray(self).toHexString()
125 | map { String(format: "%02x", Int($0)) }.joined()
126 | #else
127 | map { String(format: "%02x", $0) }.joined()
128 | #endif
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Tests/SkipSQLPlusTests/Skip/skip.yml:
--------------------------------------------------------------------------------
1 | # skip.tools per-configuration file
2 |
3 | # the blocks to add to the build.gradle.kts
4 | #build:
5 | # contents:
6 | # - block: 'dependencies'
7 | # contents:
8 | # - '// no new dependencies in SkipSQLKtTests'
9 | # skip.tools per-configuration file
10 |
--------------------------------------------------------------------------------
/Tests/SkipSQLPlusTests/XCSkipTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if os(macOS)
4 | import SkipTest
5 |
6 | /// This test case will run the transpiled tests for the Skip module.
7 | @available(macOS 13, macCatalyst 16, *)
8 | final class XCSkipTests: XCTestCase, XCGradleHarness {
9 | public func testSkipModule() async throws {
10 | // Run the transpiled JUnit tests for the current test module.
11 | // These tests will be executed locally using Robolectric.
12 | // Connected device or emulator tests can be run by setting the
13 | // `ANDROID_SERIAL` environment variable to an `adb devices`
14 | // ID in the scheme's Run settings.
15 | //
16 | // Note that it isn't currently possible to filter the tests to run.
17 | try await runGradleTests()
18 | }
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/Tests/SkipSQLTests/SQLContextTestConfiguration.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | import SkipSQL
4 |
5 | extension SQLiteConfiguration {
6 | /// The shared SQLContextTests uses thus local variable to determine the configuration to use
7 | public static let test = SQLiteConfiguration.platform
8 | }
9 |
--------------------------------------------------------------------------------
/Tests/SkipSQLTests/Skip/skip.yml:
--------------------------------------------------------------------------------
1 | # skip.tools per-configuration file
2 |
3 | # the blocks to add to the build.gradle.kts
4 | #build:
5 | # contents:
6 | # - block: 'dependencies'
7 | # contents:
8 | # - '// no new dependencies in SkipSQLKtTests'
9 | # skip.tools per-configuration file
10 |
--------------------------------------------------------------------------------
/Tests/SkipSQLTests/XCSkipTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2023–2025 Skip
2 | // SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
3 | #if os(macOS)
4 | import SkipTest
5 |
6 | /// This test case will run the transpiled tests for the Skip module.
7 | @available(macOS 13, macCatalyst 16, *)
8 | final class XCSkipTests: XCTestCase, XCGradleHarness {
9 | public func testSkipModule() async throws {
10 | // Run the transpiled JUnit tests for the current test module.
11 | // These tests will be executed locally using Robolectric.
12 | // Connected device or emulator tests can be run by setting the
13 | // `ANDROID_SERIAL` environment variable to an `adb devices`
14 | // ID in the scheme's Run settings.
15 | //
16 | // Note that it isn't currently possible to filter the tests to run.
17 | try await runGradleTests()
18 | }
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------