@unvired/cordova-plugin-unvired-electron-db 0.0.36
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/README.md +93 -0
- package/package.json +41 -0
- package/plugin.xml +79 -0
- package/src/android/DBPlugin.java +317 -0
- package/src/android/xml/file_provider_paths.xml +21 -0
- package/src/browser/DbPluginProxy.js +375 -0
- package/src/browser/bootstrap.min.js +17 -0
- package/src/browser/codemirror.js +9755 -0
- package/src/browser/jquery-3.7.1.js +2 -0
- package/src/browser/sql-wasm.wasm +0 -0
- package/src/browser/sql.js +203 -0
- package/src/browser/src_index_worker_js.unvired-db-worker.js +231 -0
- package/src/browser/unvired-db-worker.js +166 -0
- package/src/browser/vendors-node_modules_comlink_dist_esm_comlink_mjs.unvired-db-worker.js +22 -0
- package/src/electron/package.json +17 -0
- package/src/electron/unvired-db-proxy.js +215 -0
- package/src/ios/UnviredDB.h +34 -0
- package/src/ios/UnviredDB.m +486 -0
- package/www/unvired-db.js +29 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UnviredDB.m
|
|
3
|
+
// RemindTrac
|
|
4
|
+
//
|
|
5
|
+
// Created by VENKADESH on 13/06/17.
|
|
6
|
+
//
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import "UnviredDB.h"
|
|
10
|
+
|
|
11
|
+
static const NSString *DBTypeAppDb = @"AppDb";
|
|
12
|
+
static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
|
|
13
|
+
|
|
14
|
+
@interface UnviredDB () {
|
|
15
|
+
@private sqlite3 *fwDb;
|
|
16
|
+
@private sqlite3 *appDb;
|
|
17
|
+
}
|
|
18
|
+
@property (nonatomic, strong)NSString *fwDbPath;
|
|
19
|
+
@property (nonatomic, strong)NSString *appDbPath;
|
|
20
|
+
@end
|
|
21
|
+
|
|
22
|
+
@implementation UnviredDB
|
|
23
|
+
|
|
24
|
+
- (void)create:(CDVInvokedUrlCommand*)command
|
|
25
|
+
{
|
|
26
|
+
NSLog(@"OPEN FUNCTION CALLED");
|
|
27
|
+
|
|
28
|
+
[self.commandDelegate runInBackground: ^{
|
|
29
|
+
@try {
|
|
30
|
+
CDVPluginResult *pluginResult = nil;
|
|
31
|
+
|
|
32
|
+
NSDictionary *dataObjects = [command.arguments objectAtIndex:0];
|
|
33
|
+
NSString *userId = dataObjects[@"userId"];
|
|
34
|
+
// NSString *encryptionKey = dataObjects[@"key"];
|
|
35
|
+
NSArray *location = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
36
|
+
NSString *userDirectory = [location[0] stringByAppendingPathComponent:userId];
|
|
37
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
38
|
+
|
|
39
|
+
// Check if directory exists
|
|
40
|
+
BOOL isDir = NO;
|
|
41
|
+
if (![fileManager fileExistsAtPath:userDirectory isDirectory:&isDir] || !isDir) {
|
|
42
|
+
NSError *error = nil;
|
|
43
|
+
BOOL success = [fileManager createDirectoryAtPath:userDirectory
|
|
44
|
+
withIntermediateDirectories:YES
|
|
45
|
+
attributes:nil
|
|
46
|
+
error:&error];
|
|
47
|
+
if (!success) {
|
|
48
|
+
NSLog(@"Failed to create directory: %@", error.localizedDescription);
|
|
49
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:@{@"error": error.localizedDescription}];
|
|
50
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
51
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
52
|
+
return;
|
|
53
|
+
} else {
|
|
54
|
+
NSLog(@"Directory created at path: %@", userDirectory);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
NSLog(@"Directory already exists: %@", userDirectory);
|
|
58
|
+
}
|
|
59
|
+
self.fwDbPath = [NSString stringWithFormat:@"%@/framework.db", userDirectory];
|
|
60
|
+
NSLog(@"🔵🔵🔵 FRAMEWORK DB PATH : %@", self.fwDbPath);
|
|
61
|
+
self.appDbPath = [NSString stringWithFormat:@"%@/app.db", userDirectory];
|
|
62
|
+
NSLog(@"🔵🔵🔵 APP DB PATH : %@", self.appDbPath);
|
|
63
|
+
|
|
64
|
+
// Close existing database connections if they are already open
|
|
65
|
+
if (self->fwDb != NULL) {
|
|
66
|
+
NSLog(@"Closing existing fwDb connection");
|
|
67
|
+
sqlite3_close(self->fwDb);
|
|
68
|
+
self->fwDb = NULL;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (self->appDb != NULL) {
|
|
72
|
+
NSLog(@"Closing existing appDb connection");
|
|
73
|
+
sqlite3_close(self->appDb);
|
|
74
|
+
self->appDb = NULL;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
|
|
78
|
+
|
|
79
|
+
int fwDatabaseResult = sqlite3_open_v2([self.fwDbPath UTF8String], &self->fwDb,
|
|
80
|
+
SQLITE_OPEN_CREATE |
|
|
81
|
+
SQLITE_OPEN_READWRITE |
|
|
82
|
+
SQLITE_OPEN_FULLMUTEX, 0);
|
|
83
|
+
NSLog(@"FW DB RESULT:%d", fwDatabaseResult);
|
|
84
|
+
|
|
85
|
+
if (fwDatabaseResult != SQLITE_OK) {
|
|
86
|
+
NSString *errorMsg = [NSString stringWithFormat:@"Failed to open framework database: %s", sqlite3_errmsg(self->fwDb)];
|
|
87
|
+
NSLog(@"%@", errorMsg);
|
|
88
|
+
if (self->fwDb) {
|
|
89
|
+
sqlite3_close(self->fwDb);
|
|
90
|
+
self->fwDb = NULL;
|
|
91
|
+
}
|
|
92
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:@{@"error": errorMsg}];
|
|
93
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
94
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// const char *key = [encryptionKey UTF8String];
|
|
99
|
+
|
|
100
|
+
// int fwResult = sqlite3_key(self->fwDb, key, strlen(key));
|
|
101
|
+
// NSLog(@"ENCRYPTED FW DB RESULT:%d", fwResult);
|
|
102
|
+
|
|
103
|
+
int appDatabaseResult = sqlite3_open_v2([self.appDbPath UTF8String], &self->appDb,
|
|
104
|
+
SQLITE_OPEN_CREATE |
|
|
105
|
+
SQLITE_OPEN_READWRITE |
|
|
106
|
+
SQLITE_OPEN_FULLMUTEX, 0);
|
|
107
|
+
NSLog(@"APP DB RESULT:%d", appDatabaseResult);
|
|
108
|
+
if (appDatabaseResult != SQLITE_OK) {
|
|
109
|
+
NSString *errorMsg = [NSString stringWithFormat:@"Failed to open app database: %s", sqlite3_errmsg(self->appDb)];
|
|
110
|
+
NSLog(@"%@", errorMsg);
|
|
111
|
+
// Close fwDb if it was opened successfully
|
|
112
|
+
if (self->fwDb) {
|
|
113
|
+
sqlite3_close(self->fwDb);
|
|
114
|
+
self->fwDb = NULL;
|
|
115
|
+
}
|
|
116
|
+
if (self->appDb) {
|
|
117
|
+
sqlite3_close(self->appDb);
|
|
118
|
+
self->appDb = NULL;
|
|
119
|
+
}
|
|
120
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:@{@"error": errorMsg}];
|
|
121
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
122
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// int appResult = sqlite3_key(self->appDb, key, strlen(key));
|
|
127
|
+
// NSLog(@"ENCRYPTED APP DB RESULT:%d", appResult);
|
|
128
|
+
|
|
129
|
+
// enable foreign Keys ON
|
|
130
|
+
NSError *error = NULL;
|
|
131
|
+
|
|
132
|
+
[self executeQuery:@"PRAGMA journal_mode = WAL;" sqlDb:self->fwDb error:&error];
|
|
133
|
+
[self executeQuery:@"PRAGMA read_uncommitted = 1;" sqlDb:self->fwDb error:&error];
|
|
134
|
+
|
|
135
|
+
[self executeQuery:@"PRAGMA journal_mode = WAL;" sqlDb:self->appDb error:&error];
|
|
136
|
+
[self executeQuery:@"PRAGMA foreign_keys = ON;" sqlDb:self->appDb error:&error];
|
|
137
|
+
[self executeQuery:@"PRAGMA read_uncommitted = 1;" sqlDb:self->appDb error:&error];
|
|
138
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:true];
|
|
139
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
140
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
141
|
+
} @catch (NSException *exception) {
|
|
142
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
143
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
144
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
145
|
+
}
|
|
146
|
+
}];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
- (void)execute:(CDVInvokedUrlCommand*)command {
|
|
150
|
+
|
|
151
|
+
[self.commandDelegate runInBackground: ^{
|
|
152
|
+
|
|
153
|
+
@try {
|
|
154
|
+
|
|
155
|
+
CDVPluginResult *pluginResult = nil;
|
|
156
|
+
NSError *error = NULL;
|
|
157
|
+
NSArray *result = [NSArray array];
|
|
158
|
+
NSDictionary *dataObjects = [command.arguments objectAtIndex:0];
|
|
159
|
+
|
|
160
|
+
NSString *userId = dataObjects[@"userId"];
|
|
161
|
+
NSString *dbType = dataObjects[@"dbType"];
|
|
162
|
+
NSString *query = dataObjects[@"query"];
|
|
163
|
+
|
|
164
|
+
sqlite3 *sql = [dbType isEqualToString:DBTypeFrameworkDb] ? self->fwDb : self->appDb;
|
|
165
|
+
|
|
166
|
+
// Check if database connection is valid
|
|
167
|
+
if (sql == NULL) {
|
|
168
|
+
NSString *dbName = [dbType isEqualToString:DBTypeFrameworkDb] ? @"framework" : @"app";
|
|
169
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"%@ database is not open. Please call create() first.", dbName]];
|
|
170
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
171
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// NSLog(@"EXECUTE QUERY: %@", query);
|
|
176
|
+
if ([[query lowercaseString] containsString:@"create table"])
|
|
177
|
+
[self executeCreate:query sqlDb:sql error:&error];
|
|
178
|
+
else {
|
|
179
|
+
result = [self executeQuery:query sqlDb:sql error:&error];
|
|
180
|
+
}
|
|
181
|
+
if (error == NULL) {
|
|
182
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:result];
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.localizedDescription];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
189
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
190
|
+
|
|
191
|
+
} @catch (NSException *exception) {
|
|
192
|
+
CDVPluginResult *pluginResult = nil;
|
|
193
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
194
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
195
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
196
|
+
}
|
|
197
|
+
}];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
- (void)close:(CDVInvokedUrlCommand*)command {
|
|
201
|
+
[self.commandDelegate runInBackground: ^{
|
|
202
|
+
@try {
|
|
203
|
+
CDVPluginResult *pluginResult = nil;
|
|
204
|
+
NSError *error = NULL;
|
|
205
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
206
|
+
|
|
207
|
+
int fwDatabaseResult = sqlite3_close(fwDb);
|
|
208
|
+
if (fwDatabaseResult == SQLITE_OK) {
|
|
209
|
+
|
|
210
|
+
BOOL isFileRemoved = [fileManager removeItemAtPath:self.fwDbPath
|
|
211
|
+
error:&error];
|
|
212
|
+
if (isFileRemoved) {
|
|
213
|
+
self->fwDb = nil;
|
|
214
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:error.localizedDescription];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"File does not exist."];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
int appDatabaseResult = sqlite3_close(appDb);
|
|
225
|
+
if (appDatabaseResult == SQLITE_OK) {
|
|
226
|
+
BOOL isFileRemoved = [fileManager removeItemAtPath:self.appDbPath
|
|
227
|
+
error:&error];
|
|
228
|
+
if (isFileRemoved) {
|
|
229
|
+
self->appDb = nil;
|
|
230
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:nil];
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:error.localizedDescription];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"File does not exist."];
|
|
238
|
+
}
|
|
239
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
240
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
241
|
+
} @catch (NSException *exception) {
|
|
242
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
243
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
244
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
245
|
+
}
|
|
246
|
+
}];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
- (void)getDBFilePath:(CDVInvokedUrlCommand*)command {
|
|
250
|
+
[self.commandDelegate runInBackground: ^{
|
|
251
|
+
@try {
|
|
252
|
+
NSDictionary *dataObjects = [command.arguments objectAtIndex:0];
|
|
253
|
+
NSString *dbType = dataObjects[@"dbType"] != nil ? dataObjects[@"dbType"] : @"";
|
|
254
|
+
NSString *dbPath = [dbType isEqualToString:DBTypeFrameworkDb] ? self.fwDbPath : self.appDbPath;
|
|
255
|
+
|
|
256
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:dbPath];
|
|
257
|
+
if (dbPath == nil) {
|
|
258
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Database path not available."];
|
|
259
|
+
}
|
|
260
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
261
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
262
|
+
} @catch (NSException *exception) {
|
|
263
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
264
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
265
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
266
|
+
}
|
|
267
|
+
}];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
- (void)getUserDirectoryPath:(CDVInvokedUrlCommand *)command {
|
|
271
|
+
|
|
272
|
+
[self.commandDelegate runInBackground: ^{
|
|
273
|
+
@try {
|
|
274
|
+
NSDictionary *dataObjects = [command.arguments objectAtIndex:0];
|
|
275
|
+
NSString *userId = dataObjects[@"userId"];
|
|
276
|
+
|
|
277
|
+
NSArray *location = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
278
|
+
NSString *userDirectory = [NSString stringWithFormat:@"%@/%@/",location[0],userId];
|
|
279
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:userDirectory];
|
|
280
|
+
if (userDirectory == nil) {
|
|
281
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Directory not available."];
|
|
282
|
+
}
|
|
283
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
284
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
285
|
+
} @catch (NSException *exception) {
|
|
286
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
287
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
288
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
289
|
+
}
|
|
290
|
+
}];
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
- (BOOL)executeCreate:(NSString *)sqlStatement sqlDb:(sqlite3 *)sql error:(NSError **)error {
|
|
294
|
+
NSMutableString *msg = [NSMutableString stringWithFormat:@"Query : %@", sqlStatement];
|
|
295
|
+
|
|
296
|
+
char *err = NULL;
|
|
297
|
+
int result = sqlite3_exec(sql, [sqlStatement UTF8String], NULL, NULL, &err);
|
|
298
|
+
|
|
299
|
+
if (result != SQLITE_OK) {
|
|
300
|
+
// Construct an NSError
|
|
301
|
+
if (error != NULL) {
|
|
302
|
+
// Return a Complete Error Description.
|
|
303
|
+
NSString *dbErrorDescription = [NSString stringWithFormat:@"DB Error: %@. Query: %@.", [self getSQLError:sql], sqlStatement];
|
|
304
|
+
NSLog(@"UnviredDB(executeCreate:) %@ \n %@", dbErrorDescription, msg);
|
|
305
|
+
*error = [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: dbErrorDescription}];
|
|
306
|
+
}
|
|
307
|
+
return NO;
|
|
308
|
+
}
|
|
309
|
+
return YES;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
- (NSArray *)executeQuery:(NSString *)sqlStatement sqlDb:(sqlite3 *)sql error:(NSError **)error {
|
|
313
|
+
|
|
314
|
+
sqlite3_stmt *statement;
|
|
315
|
+
statement = [self prepareStatement:sqlStatement sqlDb:sql error:error];
|
|
316
|
+
|
|
317
|
+
if (statement == NULL) {
|
|
318
|
+
return NULL;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
NSLog(@"Statement: %@", sqlStatement);
|
|
322
|
+
|
|
323
|
+
NSMutableArray *cursor = [NSMutableArray array];
|
|
324
|
+
|
|
325
|
+
int columnCount = sqlite3_column_count(statement);
|
|
326
|
+
|
|
327
|
+
if (statement) {
|
|
328
|
+
while (sqlite3_step(statement) == SQLITE_ROW) {
|
|
329
|
+
NSMutableDictionary *row = [NSMutableDictionary dictionary];
|
|
330
|
+
for (int i = 0; i < columnCount; i++) {
|
|
331
|
+
NSString *columnName = @((char *)sqlite3_column_name(statement, i));
|
|
332
|
+
|
|
333
|
+
switch (sqlite3_column_type(statement, i)) {
|
|
334
|
+
case SQLITE_INTEGER:
|
|
335
|
+
{
|
|
336
|
+
row[columnName] = @((long long)sqlite3_column_int64(statement, i));
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
|
|
340
|
+
case SQLITE_FLOAT:
|
|
341
|
+
{
|
|
342
|
+
row[columnName] = @(sqlite3_column_double(statement, i));
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
|
|
346
|
+
case SQLITE_BLOB:
|
|
347
|
+
{
|
|
348
|
+
const void *blob = sqlite3_column_blob(statement, i);
|
|
349
|
+
int bytesLength = sqlite3_column_bytes(statement, i);
|
|
350
|
+
if (blob == NULL || bytesLength == 0) {
|
|
351
|
+
row[columnName] = [NSNull null];
|
|
352
|
+
} else {
|
|
353
|
+
NSData *data = [NSData dataWithBytes:blob length:bytesLength];
|
|
354
|
+
// Encode to base64 string for JSON-safe transport
|
|
355
|
+
NSString *b64 = [data respondsToSelector:@selector(base64EncodedStringWithOptions:)]
|
|
356
|
+
? [data base64EncodedStringWithOptions:0]
|
|
357
|
+
: nil;
|
|
358
|
+
if (b64) {
|
|
359
|
+
row[columnName] = b64;
|
|
360
|
+
} else {
|
|
361
|
+
// Fallback: if base64 is unavailable, return hex string
|
|
362
|
+
const unsigned char *bytes = (const unsigned char *)data.bytes;
|
|
363
|
+
NSMutableString *hex = [NSMutableString stringWithCapacity:bytesLength * 2];
|
|
364
|
+
for (int j = 0; j < bytesLength; j++) {
|
|
365
|
+
[hex appendFormat:@"%02x", bytes[j]];
|
|
366
|
+
}
|
|
367
|
+
row[columnName] = hex;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
break;
|
|
372
|
+
|
|
373
|
+
case SQLITE_NULL: // Bind NSNull Object to indicate that it is a NULL Object.
|
|
374
|
+
{
|
|
375
|
+
row[columnName] = [NSNull null];
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
|
|
379
|
+
case SQLITE_TEXT:
|
|
380
|
+
{
|
|
381
|
+
row[columnName] = @((char *)sqlite3_column_text(statement, i));
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
|
|
385
|
+
default:
|
|
386
|
+
{
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
[cursor addObject:row];
|
|
392
|
+
}
|
|
393
|
+
int sqlResult = sqlite3_finalize(statement);
|
|
394
|
+
NSLog(@"SQL Result: %@", sqlStatement);
|
|
395
|
+
if (sqlResult != SQLITE_OK) {
|
|
396
|
+
// Get the Complete Error Description.
|
|
397
|
+
// There is an error.
|
|
398
|
+
if (error != NULL) {
|
|
399
|
+
NSString *dbErrorDescription = [NSString stringWithFormat:@"DB Error: %@. Query: %@.", [self getSQLError:sql], sqlStatement];
|
|
400
|
+
NSLog(@"UnviredDB(executeQuery:):%@", dbErrorDescription);
|
|
401
|
+
*error = [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: dbErrorDescription}];
|
|
402
|
+
return nil;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return cursor;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
- (sqlite3_stmt *)prepareStatement:(NSString *)query sqlDb:(sqlite3 *)sql error:(NSError **)error {
|
|
410
|
+
sqlite3_stmt *statement = 0X0;
|
|
411
|
+
int databaseResult = sqlite3_prepare_v2(sql, [query UTF8String], -1, &statement, NULL);
|
|
412
|
+
|
|
413
|
+
if (databaseResult != SQLITE_OK) {
|
|
414
|
+
// Construct an NSError
|
|
415
|
+
if (error != NULL) {
|
|
416
|
+
NSString *dbErrorDesc = [NSString stringWithFormat:@"DB Error: %@. Query: %@", [self getSQLError:sql], query];
|
|
417
|
+
NSLog(@"UnviredDB(prepareStatement:):%@", dbErrorDesc);
|
|
418
|
+
*error = [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: dbErrorDesc}];
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return statement;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
- (NSString *)getSQLError:(sqlite3 *)sql {
|
|
425
|
+
return [NSString stringWithFormat:@"%s", sqlite3_errmsg(sql)];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
- (void)saveWebDB:(CDVInvokedUrlCommand*)command {
|
|
429
|
+
[self.commandDelegate runInBackground: ^{
|
|
430
|
+
@try {
|
|
431
|
+
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Web DB save is only for browser."] callbackId:command.callbackId];
|
|
432
|
+
} @catch (NSException *exception) {
|
|
433
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
434
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
435
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
436
|
+
}
|
|
437
|
+
}];
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
- (void)deleteUserData:(CDVInvokedUrlCommand*)command {
|
|
441
|
+
[self.commandDelegate runInBackground: ^{
|
|
442
|
+
@try {
|
|
443
|
+
NSDictionary *dataObjects = [command.arguments objectAtIndex:0];
|
|
444
|
+
NSString *userId = dataObjects[@"userId"];
|
|
445
|
+
NSArray *location = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
446
|
+
NSString *userDirectory = [location[0] stringByAppendingPathComponent:userId];
|
|
447
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
448
|
+
NSError *error = nil;
|
|
449
|
+
BOOL exists = [fileManager fileExistsAtPath:userDirectory];
|
|
450
|
+
CDVPluginResult *pluginResult = nil;
|
|
451
|
+
if (!exists) {
|
|
452
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"User directory does not exist: %@", userDirectory]];
|
|
453
|
+
} else {
|
|
454
|
+
// Close databases if open and set to nil
|
|
455
|
+
if (self->appDb) {
|
|
456
|
+
int appDbCloseResult = sqlite3_close(self->appDb);
|
|
457
|
+
if (appDbCloseResult != SQLITE_OK) {
|
|
458
|
+
NSLog(@"Error closing appDb during user data deletion: %s", sqlite3_errmsg(self->appDb));
|
|
459
|
+
}
|
|
460
|
+
self->appDb = nil;
|
|
461
|
+
}
|
|
462
|
+
if (self->fwDb) {
|
|
463
|
+
int fwDbCloseResult = sqlite3_close(self->fwDb);
|
|
464
|
+
if (fwDbCloseResult != SQLITE_OK) {
|
|
465
|
+
NSLog(@"Error closing fwDb during user data deletion: %s", sqlite3_errmsg(self->fwDb));
|
|
466
|
+
}
|
|
467
|
+
self->fwDb = nil;
|
|
468
|
+
}
|
|
469
|
+
BOOL removed = [fileManager removeItemAtPath:userDirectory error:&error];
|
|
470
|
+
if (removed) {
|
|
471
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[NSString stringWithFormat:@"User directory deleted: %@", userDirectory]];
|
|
472
|
+
} else {
|
|
473
|
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"Failed to delete user directory: %@", error.localizedDescription]];
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
477
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
478
|
+
} @catch (NSException *exception) {
|
|
479
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[exception description]];
|
|
480
|
+
[pluginResult setKeepCallbackAsBool:true];
|
|
481
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
482
|
+
}
|
|
483
|
+
}];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
@end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var exec = require('cordova/exec');
|
|
2
|
+
|
|
3
|
+
exports.create = function (arg0, successCallback, errorCallback) {
|
|
4
|
+
exec(successCallback, errorCallback, "UnviredDB", 'create', [arg0]);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
exports.execute = function (arg0, successCallback, errorCallback) {
|
|
8
|
+
exec(successCallback, errorCallback, "UnviredDB", 'execute', [arg0]);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
exports.close = function (arg0, successCallback, errorCallback) {
|
|
12
|
+
exec(successCallback, errorCallback, "UnviredDB", 'close', [arg0]);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
exports.getDBFilePath = function (arg0, successCallback, errorCallback) {
|
|
16
|
+
exec(successCallback, errorCallback, "UnviredDB", 'getDBFilePath', [arg0]);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
exports.getUserDirectoryPath = function (arg0, successCallback, errorCallback) {
|
|
20
|
+
exec(successCallback, errorCallback, "UnviredDB", 'getUserDirectoryPath', [arg0]);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
exports.saveWebDB = function (arg0, successCallback, errorCallback) {
|
|
24
|
+
exec(successCallback, errorCallback, "UnviredDB", 'saveWebDB', [arg0]);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
exports.deleteUserData = function (arg0, successCallback, errorCallback) {
|
|
28
|
+
exec(successCallback, errorCallback, "UnviredDB", 'deleteUserData', [arg0]);
|
|
29
|
+
}
|