react-native-bg-geolocation 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BgGeolocation.podspec +39 -0
- package/LICENSE +20 -0
- package/README.md +366 -0
- package/android/build.gradle +69 -0
- package/android/src/main/AndroidManifest.xml +53 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationActivityRecognitionReceiver.kt +116 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationBootReceiver.kt +44 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationForegroundService.kt +373 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationGeofenceReceiver.kt +55 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationHeadlessTask.kt +138 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationModule.kt +1030 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationMotionStateMachine.kt +159 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationPackage.kt +31 -0
- package/android/src/main/res/drawable/bg_geo_notification.xml +9 -0
- package/ios/BgGeolocation.h +14 -0
- package/ios/BgGeolocation.mm +709 -0
- package/ios/engine/AtomicBoolean.swift +48 -0
- package/ios/engine/BGActivityChangeEvent.swift +20 -0
- package/ios/engine/BGActivityConfig.swift +71 -0
- package/ios/engine/BGAppConfig.swift +92 -0
- package/ios/engine/BGAppState.swift +147 -0
- package/ios/engine/BGAuthorization.swift +85 -0
- package/ios/engine/BGAuthorizationAlertPresenter.swift +39 -0
- package/ios/engine/BGAuthorizationConfig.swift +50 -0
- package/ios/engine/BGAuthorizationEvent.swift +40 -0
- package/ios/engine/BGBackgroundTaskManager.swift +143 -0
- package/ios/engine/BGCLRouter.swift +101 -0
- package/ios/engine/BGCallback.swift +19 -0
- package/ios/engine/BGConfig.swift +440 -0
- package/ios/engine/BGConfigModuleBase.swift +180 -0
- package/ios/engine/BGConfigOLD.swift +582 -0
- package/ios/engine/BGConnectivityChangeEvent.swift +15 -0
- package/ios/engine/BGCrashDetector.swift +122 -0
- package/ios/engine/BGCurrentPositionRequest.swift +87 -0
- package/ios/engine/BGDataStore.swift +75 -0
- package/ios/engine/BGDatabase.swift +677 -0
- package/ios/engine/BGDatabasePool.swift +220 -0
- package/ios/engine/BGDatabaseQueue.swift +215 -0
- package/ios/engine/BGDateUtils.swift +26 -0
- package/ios/engine/BGDeviceInfo.swift +54 -0
- package/ios/engine/BGDeviceManager.swift +65 -0
- package/ios/engine/BGEnabledChangeEvent.swift +11 -0
- package/ios/engine/BGEnv.swift +17 -0
- package/ios/engine/BGEventBus.swift +83 -0
- package/ios/engine/BGEventManager.swift +169 -0
- package/ios/engine/BGEventNames.swift +51 -0
- package/ios/engine/BGGeofence.swift +233 -0
- package/ios/engine/BGGeofenceDAO.swift +152 -0
- package/ios/engine/BGGeofenceEvent.swift +42 -0
- package/ios/engine/BGGeofenceLocationRequest.swift +94 -0
- package/ios/engine/BGGeofenceManager.swift +315 -0
- package/ios/engine/BGGeofenceTransition.swift +97 -0
- package/ios/engine/BGGeofencesChangeEvent.swift +26 -0
- package/ios/engine/BGGeolocationConfig.swift +136 -0
- package/ios/engine/BGHeartbeatEvent.swift +31 -0
- package/ios/engine/BGHeartbeatService.swift +51 -0
- package/ios/engine/BGHttpConfig.swift +105 -0
- package/ios/engine/BGHttpErrorCodes.swift +63 -0
- package/ios/engine/BGHttpEvent.swift +34 -0
- package/ios/engine/BGHttpRequest.swift +126 -0
- package/ios/engine/BGHttpResponse.swift +93 -0
- package/ios/engine/BGHttpService.swift +428 -0
- package/ios/engine/BGKalmanFilter.swift +105 -0
- package/ios/engine/BGLMActionNames.swift +55 -0
- package/ios/engine/BGLicenseManager.swift +26 -0
- package/ios/engine/BGLiveActivityManager.swift +327 -0
- package/ios/engine/BGLocation.swift +311 -0
- package/ios/engine/BGLocationAuthorization.swift +427 -0
- package/ios/engine/BGLocationDAO.swift +252 -0
- package/ios/engine/BGLocationErrors.swift +28 -0
- package/ios/engine/BGLocationEvent.swift +43 -0
- package/ios/engine/BGLocationFilter.swift +82 -0
- package/ios/engine/BGLocationFilterConfig.swift +57 -0
- package/ios/engine/BGLocationHelper.swift +54 -0
- package/ios/engine/BGLocationManager.swift +662 -0
- package/ios/engine/BGLocationMetricsEngine.swift +116 -0
- package/ios/engine/BGLocationRequestService.swift +459 -0
- package/ios/engine/BGLocationSatisfier.swift +14 -0
- package/ios/engine/BGLocationStreamEvent.swift +27 -0
- package/ios/engine/BGLog.swift +337 -0
- package/ios/engine/BGLogLevel.swift +26 -0
- package/ios/engine/BGLoggerConfig.swift +60 -0
- package/ios/engine/BGMotionActivity.swift +31 -0
- package/ios/engine/BGMotionActivityClassifier.swift +108 -0
- package/ios/engine/BGMotionActivityManagerAdapter.swift +40 -0
- package/ios/engine/BGMotionActivitySource.swift +46 -0
- package/ios/engine/BGMotionDetector.swift +377 -0
- package/ios/engine/BGMotionPermissionManager.swift +50 -0
- package/ios/engine/BGNativeLogger.swift +48 -0
- package/ios/engine/BGNotificaitons.swift +37 -0
- package/ios/engine/BGOdometer.swift +66 -0
- package/ios/engine/BGPersistenceConfig.swift +29 -0
- package/ios/engine/BGPolygonStreamRequest.swift +48 -0
- package/ios/engine/BGPowerSaveChangeEvent.swift +12 -0
- package/ios/engine/BGPropertySpec.swift +29 -0
- package/ios/engine/BGProviderChangeEvent.swift +31 -0
- package/ios/engine/BGQueue.swift +50 -0
- package/ios/engine/BGRPC.swift +194 -0
- package/ios/engine/BGReachability.swift +58 -0
- package/ios/engine/BGResultSet.swift +157 -0
- package/ios/engine/BGSchedule.swift +228 -0
- package/ios/engine/BGScheduleEvent.swift +13 -0
- package/ios/engine/BGScheduler.swift +116 -0
- package/ios/engine/BGSingleLocationRequest.swift +49 -0
- package/ios/engine/BGStreamLocationRequest.swift +42 -0
- package/ios/engine/BGTemplate.swift +54 -0
- package/ios/engine/BGTimerService.swift +46 -0
- package/ios/engine/BGTrackingAudioManager.swift +286 -0
- package/ios/engine/BGTrackingService.swift +879 -0
- package/ios/engine/BGWatchPositionRequest.swift +63 -0
- package/ios/engine/DatabaseQueue.swift +47 -0
- package/ios/engine/LogQuery.swift +10 -0
- package/ios/engine/SQLQuery.swift +65 -0
- package/ios/engine/TransistorAuthorizationToken.swift +182 -0
- package/ios/liveactivity/BGLiveTrackingAttributes.swift +52 -0
- package/ios/locationpush/BGLocationPushDeliverer.swift +260 -0
- package/ios/locationpush/BGLocationPushService.swift +161 -0
- package/ios/locationpush/BGLocationPushShared.swift +98 -0
- package/ios/locationpush/BGLocationPushSocketClient.swift +198 -0
- package/lib/module/NativeBgGeolocation.js +5 -0
- package/lib/module/NativeBgGeolocation.js.map +1 -0
- package/lib/module/events.js +20 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/index.js +706 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeBgGeolocation.d.ts +57 -0
- package/lib/typescript/src/NativeBgGeolocation.d.ts.map +1 -0
- package/lib/typescript/src/events.d.ts +18 -0
- package/lib/typescript/src/events.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +238 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +229 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +141 -0
- package/src/NativeBgGeolocation.ts +236 -0
- package/src/events.ts +17 -0
- package/src/index.tsx +935 -0
- package/src/types.ts +254 -0
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SQLite3
|
|
3
|
+
|
|
4
|
+
private let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
|
|
5
|
+
|
|
6
|
+
@objc public class BGStatement: NSObject {
|
|
7
|
+
|
|
8
|
+
@objc public var query: String = ""
|
|
9
|
+
@objc public var useCount: Int = 0
|
|
10
|
+
@objc public var inUse: Bool = false
|
|
11
|
+
var statement: OpaquePointer?
|
|
12
|
+
|
|
13
|
+
@objc public func reset() {
|
|
14
|
+
if let stmt = statement {
|
|
15
|
+
sqlite3_reset(stmt)
|
|
16
|
+
}
|
|
17
|
+
inUse = false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@objc public func close() {
|
|
21
|
+
if let stmt = statement {
|
|
22
|
+
sqlite3_finalize(stmt)
|
|
23
|
+
statement = nil
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@objc public override var description: String {
|
|
28
|
+
return "<BGStatement query=\(query) useCount=\(useCount)>"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
deinit {
|
|
32
|
+
close()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@objc public class BGDatabase: NSObject {
|
|
37
|
+
|
|
38
|
+
@objc public var databasePath: String?
|
|
39
|
+
@objc public var databaseURL: URL?
|
|
40
|
+
@objc public var logsErrors: Bool = true
|
|
41
|
+
@objc public var crashOnErrors: Bool = false
|
|
42
|
+
@objc public var traceExecution: Bool = false
|
|
43
|
+
@objc public var shouldCacheStatements: Bool = false
|
|
44
|
+
@objc public var isOpen: Bool = false
|
|
45
|
+
@objc public var inTransaction: Bool = false
|
|
46
|
+
@objc public var checkedOut: Bool = false
|
|
47
|
+
@objc public var maxBusyRetryTimeInterval: TimeInterval = 2.0
|
|
48
|
+
@objc public var busyRetryTimeout: Int = 0
|
|
49
|
+
|
|
50
|
+
var db: OpaquePointer?
|
|
51
|
+
var cachedStatements: [String: BGStatement] = [:]
|
|
52
|
+
var openResultSets: NSMutableSet = NSMutableSet()
|
|
53
|
+
var dateFormat: DateFormatter?
|
|
54
|
+
|
|
55
|
+
@objc public class func database(withPath path: String) -> BGDatabase {
|
|
56
|
+
return BGDatabase(path: path)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc public class func database(withURL url: URL) -> BGDatabase {
|
|
60
|
+
return BGDatabase(url: url)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@objc public class func isSQLiteThreadSafe() -> Bool {
|
|
64
|
+
return sqlite3_threadsafe() != 0
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@objc public class func sqliteLibVersion() -> String {
|
|
68
|
+
return String(cString: sqlite3_libversion())
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@objc public class func BGDBVersion() -> Int32 {
|
|
72
|
+
return sqlite3_libversion_number()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@objc public class func BGDBUserVersion() -> Int32 {
|
|
76
|
+
return 0
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@objc public class func storeableDate(format: String) -> DateFormatter {
|
|
80
|
+
let fmt = DateFormatter()
|
|
81
|
+
fmt.dateFormat = format
|
|
82
|
+
fmt.locale = Locale(identifier: "en_US_POSIX")
|
|
83
|
+
fmt.timeZone = TimeZone(abbreviation: "UTC")
|
|
84
|
+
return fmt
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@objc public init(path: String) {
|
|
88
|
+
self.databasePath = path
|
|
89
|
+
self.databaseURL = URL(fileURLWithPath: path)
|
|
90
|
+
super.init()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@objc public init(url: URL) {
|
|
94
|
+
self.databaseURL = url
|
|
95
|
+
self.databasePath = url.path
|
|
96
|
+
super.init()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc public override init() {
|
|
100
|
+
super.init()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@objc public func open() -> Bool {
|
|
104
|
+
if isOpen { return true }
|
|
105
|
+
let path = databasePath ?? ":memory:"
|
|
106
|
+
let flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
|
107
|
+
let rc = sqlite3_open_v2(path, &db, flags, nil)
|
|
108
|
+
if rc == SQLITE_OK {
|
|
109
|
+
isOpen = true
|
|
110
|
+
return true
|
|
111
|
+
}
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@objc public func open(withFlags flags: Int32) -> Bool {
|
|
116
|
+
if isOpen { return true }
|
|
117
|
+
let path = databasePath ?? ":memory:"
|
|
118
|
+
let rc = sqlite3_open_v2(path, &db, flags, nil)
|
|
119
|
+
if rc == SQLITE_OK {
|
|
120
|
+
isOpen = true
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@objc public func open(withFlags flags: Int32, vfs: String?) -> Bool {
|
|
127
|
+
if isOpen { return true }
|
|
128
|
+
let path = databasePath ?? ":memory:"
|
|
129
|
+
let rc = sqlite3_open_v2(path, &db, flags, vfs)
|
|
130
|
+
if rc == SQLITE_OK {
|
|
131
|
+
isOpen = true
|
|
132
|
+
return true
|
|
133
|
+
}
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@objc public func close() -> Bool {
|
|
138
|
+
clearCachedStatements()
|
|
139
|
+
closeOpenResultSets()
|
|
140
|
+
if db != nil {
|
|
141
|
+
sqlite3_close(db)
|
|
142
|
+
db = nil
|
|
143
|
+
}
|
|
144
|
+
isOpen = false
|
|
145
|
+
return true
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@objc public func goodConnection() -> Bool {
|
|
149
|
+
if !isOpen { return false }
|
|
150
|
+
let rs = executeQuery("SELECT name FROM sqlite_master WHERE type='table'")
|
|
151
|
+
rs?.close()
|
|
152
|
+
return rs != nil
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@objc public func databaseExists() -> Bool {
|
|
156
|
+
guard let path = databasePath else { return false }
|
|
157
|
+
return FileManager.default.fileExists(atPath: path)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@objc public func sqliteHandle() -> OpaquePointer? {
|
|
161
|
+
return db
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@objc public func sqlitePath() -> String {
|
|
165
|
+
return databasePath ?? ""
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@objc public func lastInsertRowId() -> Int64 {
|
|
169
|
+
return sqlite3_last_insert_rowid(db)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@objc public func changes() -> Int32 {
|
|
173
|
+
return sqlite3_changes(db)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@objc public func hadError() -> Bool {
|
|
177
|
+
return lastErrorCode() != SQLITE_OK
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@objc public func lastError() -> Error {
|
|
181
|
+
return NSError(domain: "BGDatabase", code: Int(lastErrorCode()), userInfo: [NSLocalizedDescriptionKey: lastErrorMessage()])
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@objc public func lastErrorCode() -> Int32 {
|
|
185
|
+
return sqlite3_errcode(db)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@objc public func lastExtendedErrorCode() -> Int32 {
|
|
189
|
+
return sqlite3_extended_errcode(db)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@objc public func lastErrorMessage() -> String {
|
|
193
|
+
return String(cString: sqlite3_errmsg(db))
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@objc public func error(withMessage message: String) -> NSError {
|
|
197
|
+
return NSError(domain: "BGDatabase", code: Int(lastErrorCode()), userInfo: [NSLocalizedDescriptionKey: message])
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@objc public func interrupt() {
|
|
201
|
+
sqlite3_interrupt(db)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@objc public func warnInUse() {
|
|
205
|
+
if logsErrors {
|
|
206
|
+
print("[BGDatabase] Warning: database in use")
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// MARK: - Statements
|
|
211
|
+
|
|
212
|
+
@objc public func cachedStatement(forQuery query: String) -> BGStatement? {
|
|
213
|
+
return cachedStatements[query]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@objc public func setCachedStatement(_ stmt: BGStatement, forQuery query: String) {
|
|
217
|
+
cachedStatements[query] = stmt
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@objc public func clearCachedStatements() {
|
|
221
|
+
for (_, stmt) in cachedStatements {
|
|
222
|
+
stmt.close()
|
|
223
|
+
}
|
|
224
|
+
cachedStatements.removeAll()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@objc public func closeOpenResultSets() {
|
|
228
|
+
let sets = openResultSets.copy() as! NSSet
|
|
229
|
+
for obj in sets {
|
|
230
|
+
if let rs = obj as? BGResultSet {
|
|
231
|
+
rs.close()
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@objc public func hasOpenResultSets() -> Bool {
|
|
237
|
+
return openResultSets.count > 0
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@objc public func resultSetDidClose(_ rs: BGResultSet) {
|
|
241
|
+
openResultSets.remove(rs)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// MARK: - Execute
|
|
245
|
+
|
|
246
|
+
@objc public func executeUpdate(_ sql: String) -> Bool {
|
|
247
|
+
return executeUpdate(sql, withArgumentsInArray: [])
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@objc public func executeUpdate(_ sql: String, withArgumentsInArray args: [Any]) -> Bool {
|
|
251
|
+
var stmt: OpaquePointer?
|
|
252
|
+
var rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nil)
|
|
253
|
+
if rc != SQLITE_OK {
|
|
254
|
+
if logsErrors { print("[BGDatabase] executeUpdate prepare error: \(lastErrorMessage())") }
|
|
255
|
+
return false
|
|
256
|
+
}
|
|
257
|
+
defer { sqlite3_finalize(stmt) }
|
|
258
|
+
for (i, arg) in args.enumerated() {
|
|
259
|
+
bind(object: arg, toColumn: Int32(i + 1), inStatement: stmt!)
|
|
260
|
+
}
|
|
261
|
+
rc = sqlite3_step(stmt)
|
|
262
|
+
if rc != SQLITE_DONE && rc != SQLITE_ROW {
|
|
263
|
+
if logsErrors { print("[BGDatabase] executeUpdate step error: \(lastErrorMessage())") }
|
|
264
|
+
return false
|
|
265
|
+
}
|
|
266
|
+
return true
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@objc public func executeUpdate(_ sql: String, withParameterDictionary params: [String: Any]) -> Bool {
|
|
270
|
+
return executeUpdate(sql, withArgumentsInArray: Array(params.values))
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
public func executeUpdate(_ sql: String, values: [Any], error: UnsafeMutablePointer<NSError?>?) throws -> Bool {
|
|
274
|
+
return executeUpdate(sql, withArgumentsInArray: values)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public func executeUpdate(withFormat sql: String, _ args: CVarArg...) -> Bool {
|
|
278
|
+
return executeUpdate(String(format: sql, args))
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
public func executeUpdate(_ sql: String, error: UnsafeMutablePointer<NSError?>?, withArgumentsInArray args: [Any]?, orDictionary dict: [String: Any]?, orVAList valist: CVaListPointer) -> Bool {
|
|
282
|
+
if let a = args { return executeUpdate(sql, withArgumentsInArray: a) }
|
|
283
|
+
if let d = dict { return executeUpdate(sql, withParameterDictionary: d) }
|
|
284
|
+
return executeUpdate(sql)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@objc public func update(_ sql: String, withErrorAndBindings bindings: [Any]) -> Bool {
|
|
288
|
+
return executeUpdate(sql, withArgumentsInArray: bindings)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
@objc public func executeUpdate(_ sql: String, withErrorAndBindings bindings: [Any]) -> Bool {
|
|
292
|
+
return executeUpdate(sql, withArgumentsInArray: bindings)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@objc public func executeStatements(_ sql: String) -> Bool {
|
|
296
|
+
var errMsg: UnsafeMutablePointer<Int8>?
|
|
297
|
+
let rc = sqlite3_exec(db, sql, nil, nil, &errMsg)
|
|
298
|
+
if rc != SQLITE_OK {
|
|
299
|
+
if logsErrors {
|
|
300
|
+
let msg = errMsg.map { String(cString: $0) } ?? "unknown error"
|
|
301
|
+
print("[BGDatabase] executeStatements error: \(msg)")
|
|
302
|
+
}
|
|
303
|
+
sqlite3_free(errMsg)
|
|
304
|
+
return false
|
|
305
|
+
}
|
|
306
|
+
return true
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
@objc public func executeStatements(_ sql: String, withResultBlock block: ((NSDictionary) -> Int32)?) -> Bool {
|
|
310
|
+
return executeStatements(sql)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@objc public func executeQuery(_ sql: String) -> BGResultSet? {
|
|
314
|
+
return executeQuery(sql, withArgumentsInArray: [])
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@objc public func executeQuery(_ sql: String, withArgumentsInArray args: [Any]) -> BGResultSet? {
|
|
318
|
+
var stmt: OpaquePointer?
|
|
319
|
+
let rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nil)
|
|
320
|
+
if rc != SQLITE_OK {
|
|
321
|
+
if logsErrors { print("[BGDatabase] executeQuery prepare error: \(lastErrorMessage())") }
|
|
322
|
+
return nil
|
|
323
|
+
}
|
|
324
|
+
for (i, arg) in args.enumerated() {
|
|
325
|
+
bind(object: arg, toColumn: Int32(i + 1), inStatement: stmt!)
|
|
326
|
+
}
|
|
327
|
+
let rs = BGResultSet()
|
|
328
|
+
rs.statement = BGStatement()
|
|
329
|
+
rs.statement?.statement = stmt
|
|
330
|
+
rs.statement?.query = sql
|
|
331
|
+
rs.parentDB = self
|
|
332
|
+
openResultSets.add(rs)
|
|
333
|
+
return rs
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
public func executeQuery(_ sql: String, values: [Any], error: UnsafeMutablePointer<NSError?>?) throws -> BGResultSet? {
|
|
337
|
+
return executeQuery(sql, withArgumentsInArray: values)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
@objc public func executeQuery(_ sql: String, withParameterDictionary params: [String: Any]) -> BGResultSet? {
|
|
341
|
+
return executeQuery(sql, withArgumentsInArray: Array(params.values))
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
public func executeQuery(_ sql: String, withVAList valist: CVaListPointer) -> BGResultSet? {
|
|
345
|
+
return executeQuery(sql)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
public func executeQuery(withFormat sql: String, _ args: CVarArg...) -> BGResultSet? {
|
|
349
|
+
return executeQuery(String(format: sql, args))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
public func executeQuery(_ sql: String, withArgumentsInArray args: [Any]?, orDictionary dict: [String: Any]?, orVAList valist: CVaListPointer) -> BGResultSet? {
|
|
353
|
+
if let a = args { return executeQuery(sql, withArgumentsInArray: a) }
|
|
354
|
+
if let d = dict { return executeQuery(sql, withParameterDictionary: d) }
|
|
355
|
+
return executeQuery(sql)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// MARK: - Transactions
|
|
359
|
+
|
|
360
|
+
@objc public func beginTransaction() -> Bool {
|
|
361
|
+
let ok = executeUpdate("BEGIN EXCLUSIVE TRANSACTION")
|
|
362
|
+
if ok { inTransaction = true }
|
|
363
|
+
return ok
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@objc public func beginDeferredTransaction() -> Bool {
|
|
367
|
+
let ok = executeUpdate("BEGIN DEFERRED TRANSACTION")
|
|
368
|
+
if ok { inTransaction = true }
|
|
369
|
+
return ok
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
@objc public func beginImmediateTransaction() -> Bool {
|
|
373
|
+
let ok = executeUpdate("BEGIN IMMEDIATE TRANSACTION")
|
|
374
|
+
if ok { inTransaction = true }
|
|
375
|
+
return ok
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
@objc public func beginExclusiveTransaction() -> Bool {
|
|
379
|
+
let ok = executeUpdate("BEGIN EXCLUSIVE TRANSACTION")
|
|
380
|
+
if ok { inTransaction = true }
|
|
381
|
+
return ok
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
@objc public func commit() -> Bool {
|
|
385
|
+
let ok = executeUpdate("COMMIT TRANSACTION")
|
|
386
|
+
if ok { inTransaction = false }
|
|
387
|
+
return ok
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@objc public func rollback() -> Bool {
|
|
391
|
+
let ok = executeUpdate("ROLLBACK TRANSACTION")
|
|
392
|
+
if ok { inTransaction = false }
|
|
393
|
+
return ok
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@objc public func isInTransaction() -> Bool {
|
|
397
|
+
return inTransaction
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@objc public func startSavePoint(withName name: String, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
401
|
+
return executeUpdate("SAVEPOINT \(name)")
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@objc public func releaseSavePoint(withName name: String, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
405
|
+
return executeUpdate("RELEASE SAVEPOINT \(name)")
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
@objc public func rollbackToSavePoint(withName name: String, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
409
|
+
return executeUpdate("ROLLBACK TO SAVEPOINT \(name)")
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@objc public func inSavePoint(_ block: (UnsafeMutablePointer<ObjCBool>) -> Void) -> Error? {
|
|
413
|
+
let savepointName = "FMDB_\(arc4random())"
|
|
414
|
+
var shouldRollback = ObjCBool(false)
|
|
415
|
+
_ = startSavePoint(withName: savepointName, error: nil)
|
|
416
|
+
block(&shouldRollback)
|
|
417
|
+
if shouldRollback.boolValue {
|
|
418
|
+
_ = rollbackToSavePoint(withName: savepointName, error: nil)
|
|
419
|
+
} else {
|
|
420
|
+
_ = releaseSavePoint(withName: savepointName, error: nil)
|
|
421
|
+
}
|
|
422
|
+
return nil
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// MARK: - Checkpoint
|
|
426
|
+
|
|
427
|
+
@objc public func checkpoint(_ checkpointMode: Int32, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
428
|
+
return sqlite3_wal_checkpoint_v2(db, nil, checkpointMode, nil, nil) == SQLITE_OK
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
@objc public func checkpoint(_ checkpointMode: Int32, name: String?, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
432
|
+
return sqlite3_wal_checkpoint_v2(db, name, checkpointMode, nil, nil) == SQLITE_OK
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@objc public func checkpoint(_ checkpointMode: Int32, name: String?, logFrameCount: UnsafeMutablePointer<Int32>?, checkpointCount: UnsafeMutablePointer<Int32>?, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
436
|
+
return sqlite3_wal_checkpoint_v2(db, name, checkpointMode, logFrameCount, checkpointCount) == SQLITE_OK
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// MARK: - Key management
|
|
440
|
+
|
|
441
|
+
@objc public func setKey(_ key: String) -> Bool { return true }
|
|
442
|
+
@objc public func setKey(withData keyData: Data) -> Bool { return true }
|
|
443
|
+
@objc public func rekey(_ key: String) -> Bool { return true }
|
|
444
|
+
@objc public func rekey(withData keyData: Data) -> Bool { return true }
|
|
445
|
+
|
|
446
|
+
// MARK: - Date helpers
|
|
447
|
+
|
|
448
|
+
@objc public func hasDateFormatter() -> Bool {
|
|
449
|
+
return dateFormat != nil
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
@objc public func setDateFormat(_ fmt: DateFormatter) {
|
|
453
|
+
dateFormat = fmt
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
@objc public func date(fromString dateString: String) -> Date? {
|
|
457
|
+
return dateFormat?.date(from: dateString)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
@objc public func string(fromDate date: Date) -> String {
|
|
461
|
+
return dateFormat?.string(from: date) ?? ""
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// MARK: - Custom functions
|
|
465
|
+
|
|
466
|
+
@objc public func makeFunctionNamed(_ name: String, arguments nArgs: Int32, block: @escaping ([AnyObject]) -> AnyObject?) {
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
@objc public func makeFunctionNamed(_ name: String, maximumArguments nArgs: Int32, with block: @escaping ([AnyObject]) -> Void) {
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
@objc public func resultInt(_ value: Int32, context: OpaquePointer) {
|
|
473
|
+
sqlite3_result_int(context, value)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
@objc public func resultLong(_ value: Int64, context: OpaquePointer) {
|
|
477
|
+
sqlite3_result_int64(context, value)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
@objc public func resultDouble(_ value: Double, context: OpaquePointer) {
|
|
481
|
+
sqlite3_result_double(context, value)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
@objc public func resultString(_ value: String, context: OpaquePointer) {
|
|
485
|
+
sqlite3_result_text(context, value, -1, SQLITE_TRANSIENT)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
@objc public func resultData(_ value: Data, context: OpaquePointer) {
|
|
489
|
+
value.withUnsafeBytes { bytes in
|
|
490
|
+
sqlite3_result_blob(context, bytes.baseAddress, Int32(value.count), SQLITE_TRANSIENT)
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
@objc public func resultNull(inContext context: OpaquePointer) {
|
|
495
|
+
sqlite3_result_null(context)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
@objc public func resultError(_ value: String, context: OpaquePointer) {
|
|
499
|
+
sqlite3_result_error(context, value, -1)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
@objc public func resultErrorCode(_ value: Int32, context: OpaquePointer) {
|
|
503
|
+
sqlite3_result_error_code(context, value)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
@objc public func resultErrorNoMemory(inContext context: OpaquePointer) {
|
|
507
|
+
sqlite3_result_error_nomem(context)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
@objc public func resultErrorTooBig(inContext context: OpaquePointer) {
|
|
511
|
+
sqlite3_result_error_toobig(context)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
@objc public func valueString(_ value: OpaquePointer) -> String? {
|
|
515
|
+
return sqlite3_value_text(value).map { String(cString: $0) }
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
@objc public func valueData(_ value: OpaquePointer) -> Data? {
|
|
519
|
+
guard let bytes = sqlite3_value_blob(value) else { return nil }
|
|
520
|
+
let len = sqlite3_value_bytes(value)
|
|
521
|
+
return Data(bytes: bytes, count: Int(len))
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
@objc public func valueInt(_ value: OpaquePointer) -> Int32 {
|
|
525
|
+
return sqlite3_value_int(value)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
@objc public func valueLong(_ value: OpaquePointer) -> Int64 {
|
|
529
|
+
return sqlite3_value_int64(value)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
@objc public func valueDouble(_ value: OpaquePointer) -> Double {
|
|
533
|
+
return sqlite3_value_double(value)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
@objc public func valueType(_ value: OpaquePointer) -> Int32 {
|
|
537
|
+
return sqlite3_value_type(value)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// MARK: - Bind helpers
|
|
541
|
+
|
|
542
|
+
func bind(object obj: Any, toColumn idx: Int32, inStatement stmt: OpaquePointer) {
|
|
543
|
+
if let num = obj as? NSNumber {
|
|
544
|
+
let type = String(cString: num.objCType)
|
|
545
|
+
if type == "d" || type == "f" {
|
|
546
|
+
sqlite3_bind_double(stmt, idx, num.doubleValue)
|
|
547
|
+
} else if type == "q" || type == "Q" {
|
|
548
|
+
sqlite3_bind_int64(stmt, idx, num.int64Value)
|
|
549
|
+
} else {
|
|
550
|
+
sqlite3_bind_int(stmt, idx, num.int32Value)
|
|
551
|
+
}
|
|
552
|
+
} else if let str = obj as? String {
|
|
553
|
+
sqlite3_bind_text(stmt, idx, str, -1, SQLITE_TRANSIENT)
|
|
554
|
+
} else if let data = obj as? Data {
|
|
555
|
+
data.withUnsafeBytes { bytes in
|
|
556
|
+
sqlite3_bind_blob(stmt, idx, bytes.baseAddress, Int32(data.count), SQLITE_TRANSIENT)
|
|
557
|
+
}
|
|
558
|
+
} else if let date = obj as? Date {
|
|
559
|
+
let str = String(date.timeIntervalSince1970)
|
|
560
|
+
sqlite3_bind_text(stmt, idx, str, -1, SQLITE_TRANSIENT)
|
|
561
|
+
} else {
|
|
562
|
+
sqlite3_bind_null(stmt, idx)
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
public func extractSQL(_ sql: String, argumentsList args: CVaListPointer, into outSQL: UnsafeMutablePointer<NSString?>, arguments: NSMutableArray) -> Bool {
|
|
567
|
+
return true
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// MARK: - BGDatabaseAdditions
|
|
572
|
+
|
|
573
|
+
extension BGDatabase {
|
|
574
|
+
|
|
575
|
+
public func string(forQuery query: String, _ args: Any...) -> String? {
|
|
576
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return nil }
|
|
577
|
+
defer { rs.close() }
|
|
578
|
+
return rs.string(forColumn: 0)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
public func int(forQuery query: String, _ args: Any...) -> Int32 {
|
|
582
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return 0 }
|
|
583
|
+
defer { rs.close() }
|
|
584
|
+
return rs.int(forColumn: 0)
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
public func long(forQuery query: String, _ args: Any...) -> Int64 {
|
|
588
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return 0 }
|
|
589
|
+
defer { rs.close() }
|
|
590
|
+
return rs.long(forColumn: 0)
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
public func bool(forQuery query: String, _ args: Any...) -> Bool {
|
|
594
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return false }
|
|
595
|
+
defer { rs.close() }
|
|
596
|
+
return rs.bool(forColumn: 0)
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
public func double(forQuery query: String, _ args: Any...) -> Double {
|
|
600
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return 0 }
|
|
601
|
+
defer { rs.close() }
|
|
602
|
+
return rs.double(forColumn: 0)
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
public func data(forQuery query: String, _ args: Any...) -> Data? {
|
|
606
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return nil }
|
|
607
|
+
defer { rs.close() }
|
|
608
|
+
return rs.data(forColumn: 0)
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
public func date(forQuery query: String, _ args: Any...) -> Date? {
|
|
612
|
+
guard let rs = executeQuery(query, withArgumentsInArray: args), rs.next() else { return nil }
|
|
613
|
+
defer { rs.close() }
|
|
614
|
+
return rs.date(forColumn: 0)
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
@objc public func tableExists(_ tableName: String) -> Bool {
|
|
618
|
+
guard let rs = executeQuery("SELECT [sql] FROM (SELECT [sql] FROM sqlite_master UNION ALL SELECT [sql] FROM sqlite_temp_master) WHERE type != 'meta' AND name LIKE ?", withArgumentsInArray: [tableName]), rs.next() else { return false }
|
|
619
|
+
rs.close()
|
|
620
|
+
return true
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
@objc public func columnExists(_ column: String, inTableWithName table: String) -> Bool {
|
|
624
|
+
var exists = false
|
|
625
|
+
if let rs = executeQuery("PRAGMA table_info('\(table)')") {
|
|
626
|
+
while rs.next() {
|
|
627
|
+
if let name = rs.string(forColumn: "name"), name.lowercased() == column.lowercased() {
|
|
628
|
+
exists = true
|
|
629
|
+
break
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
rs.close()
|
|
633
|
+
}
|
|
634
|
+
return exists
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
@objc public func columnExists(_ column: String, columnName: String) -> Bool {
|
|
638
|
+
return columnExists(column, inTableWithName: columnName)
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
@objc public func getSchema() -> BGResultSet? {
|
|
642
|
+
return executeQuery("SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name")
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
@objc public func getTableSchema(_ tableName: String) -> BGResultSet? {
|
|
646
|
+
return executeQuery("PRAGMA table_info('\(tableName)')")
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
@objc public func userVersion() -> UInt32 {
|
|
650
|
+
guard let rs = executeQuery("PRAGMA user_version"), rs.next() else { return 0 }
|
|
651
|
+
let v = UInt32(bitPattern: rs.int(forColumn: 0))
|
|
652
|
+
rs.close()
|
|
653
|
+
return v
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
@objc public func setUserVersion(_ version: UInt32) {
|
|
657
|
+
_ = executeUpdate("PRAGMA user_version = \(version)")
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
@objc public func applicationID() -> UInt32 {
|
|
661
|
+
guard let rs = executeQuery("PRAGMA application_id"), rs.next() else { return 0 }
|
|
662
|
+
let v = UInt32(bitPattern: rs.int(forColumn: 0))
|
|
663
|
+
rs.close()
|
|
664
|
+
return v
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
@objc public func setApplicationID(_ appID: UInt32) {
|
|
668
|
+
_ = executeUpdate("PRAGMA application_id = \(appID)")
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
@objc public func validateSQL(_ sql: String, error: UnsafeMutablePointer<NSError?>?) -> Bool {
|
|
672
|
+
var stmt: OpaquePointer?
|
|
673
|
+
let rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nil)
|
|
674
|
+
if stmt != nil { sqlite3_finalize(stmt) }
|
|
675
|
+
return rc == SQLITE_OK
|
|
676
|
+
}
|
|
677
|
+
}
|