@unvired/cordova-plugin-unvired-electron-db 0.0.42 → 0.0.44

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unvired/cordova-plugin-unvired-electron-db",
3
3
  "displayName": "Unvired DB",
4
- "version": "0.0.42",
4
+ "version": "0.0.44",
5
5
  "description": "Unvired DB Native Support for Cordova",
6
6
  "scripts": {},
7
7
  "keywords": [
package/plugin.xml CHANGED
@@ -1,7 +1,7 @@
1
1
  <?xml version='1.0' encoding='utf-8'?>
2
2
  <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
3
3
  id="@unvired/cordova-plugin-unvired-electron-db"
4
- version="0.0.42"
4
+ version="0.0.44"
5
5
  xmlns:android="http://schemas.android.com/apk/res/android">
6
6
  <name>Unvired DB</name>
7
7
  <description>Unvired DB Native Support for Cordova</description>
@@ -117,6 +117,7 @@ public class DBPlugin extends CordovaPlugin {
117
117
  String userId = params.getString("userId");
118
118
  String dbType = params.getString("dbType");
119
119
  String query = params.getString("query");
120
+ JSONArray queryArgs = params.optJSONArray("args");
120
121
 
121
122
  if (userId == null || userId.isEmpty()) {
122
123
  callbackContext.error("userId is required");
@@ -145,44 +146,48 @@ public class DBPlugin extends CordovaPlugin {
145
146
  }
146
147
 
147
148
  try {
148
- if (query.toUpperCase().contains("SELECT")) {
149
- JSONArray results = new JSONArray();
150
- android.database.Cursor cursor = db.rawQuery(query, null);
151
- if (cursor != null) {
152
- try {
153
- String[] columnNames = cursor.getColumnNames();
154
- while (cursor.moveToNext()) {
155
- JSONObject row = new JSONObject();
156
- for (String columnName : columnNames) {
157
- int columnIndex = cursor.getColumnIndex(columnName);
158
- switch (cursor.getType(columnIndex)) {
159
- case android.database.Cursor.FIELD_TYPE_INTEGER:
160
- row.put(columnName, cursor.getLong(columnIndex));
161
- break;
162
- case android.database.Cursor.FIELD_TYPE_FLOAT:
163
- row.put(columnName, cursor.getDouble(columnIndex));
164
- break;
165
- case android.database.Cursor.FIELD_TYPE_STRING:
166
- row.put(columnName, cursor.getString(columnIndex));
167
- break;
168
- case android.database.Cursor.FIELD_TYPE_BLOB:
169
- row.put(columnName, cursor.getBlob(columnIndex));
170
- break;
171
- default:
172
- row.put(columnName, JSONObject.NULL);
173
- }
149
+ String[] selectionArgs = null;
150
+ if (queryArgs != null && queryArgs.length() > 0) {
151
+ selectionArgs = new String[queryArgs.length()];
152
+ for (int i = 0; i < queryArgs.length(); i++) {
153
+ Object val = queryArgs.get(i);
154
+ selectionArgs[i] = (val == null || val == JSONObject.NULL) ? null : String.valueOf(val);
155
+ }
156
+ }
157
+
158
+ JSONArray results = new JSONArray();
159
+ android.database.Cursor cursor = db.rawQuery(query, selectionArgs);
160
+ if (cursor != null) {
161
+ try {
162
+ String[] columnNames = cursor.getColumnNames();
163
+ while (cursor.moveToNext()) {
164
+ JSONObject row = new JSONObject();
165
+ for (String columnName : columnNames) {
166
+ int columnIndex = cursor.getColumnIndex(columnName);
167
+ switch (cursor.getType(columnIndex)) {
168
+ case android.database.Cursor.FIELD_TYPE_INTEGER:
169
+ row.put(columnName, cursor.getLong(columnIndex));
170
+ break;
171
+ case android.database.Cursor.FIELD_TYPE_FLOAT:
172
+ row.put(columnName, cursor.getDouble(columnIndex));
173
+ break;
174
+ case android.database.Cursor.FIELD_TYPE_STRING:
175
+ row.put(columnName, cursor.getString(columnIndex));
176
+ break;
177
+ case android.database.Cursor.FIELD_TYPE_BLOB:
178
+ row.put(columnName, cursor.getBlob(columnIndex));
179
+ break;
180
+ default:
181
+ row.put(columnName, JSONObject.NULL);
174
182
  }
175
- results.put(row);
176
183
  }
177
- } finally {
178
- cursor.close();
184
+ results.put(row);
179
185
  }
186
+ } finally {
187
+ cursor.close();
180
188
  }
181
- callbackContext.success(results);
182
- } else {
183
- db.execSQL(query);
184
- callbackContext.success("Success");
185
189
  }
190
+ callbackContext.success(results);
186
191
  } catch (SQLiteException e) {
187
192
  Log.e(TAG, "Error executing query", e);
188
193
  callbackContext.error("Error executing query: " + e.getMessage());
@@ -27,35 +27,37 @@ module.exports.create = async function (sucessCallback, errorCallback, options)
27
27
  module.exports.execute = async function (sucessCallback, errorCallback, options) {
28
28
  const dbType = options[0].dbType
29
29
  const query = options[0].query;
30
+ const args = options[0].args || [];
30
31
  try {
31
32
  const db = dbType == DBType.FrameworkDb ? webDb.fwDb : webDb.appDb;
32
33
 
33
- // Check if query is a SELECT statement (starts with SELECT or WITH for CTEs)
34
- // Using regex to handle leading whitespace and ensure it's the start of the command
35
- const isSelect = /^\s*\(?\s*(SELECT|WITH|PRAGMA|VALUES|EXPLAIN)\b/i.test(query);
36
-
37
- if (isSelect) {
38
- let rows = [];
39
- var stmt = db.prepare(query);
40
- while (stmt.step()) {
41
- var row = stmt.getAsObject();
42
- rows.push(row);
34
+ var parsedQuery = {query: query, values: []}
35
+ if (args.length > 0) {
36
+ parsedQuery = {
37
+ query: query,
38
+ values: args
43
39
  }
44
- stmt.free();
45
- sucessCallback(rows);
40
+ }
41
+ else {
42
+ parsedQuery = webDb.parseQueryToPrepared(query);
43
+ }
44
+
45
+ let stmt;
46
+ if (parsedQuery.values.length > 0) {
47
+ stmt = db.prepare(parsedQuery.query);
48
+ stmt.bind(parsedQuery.values);
46
49
  } else {
47
- // Parse query and convert to prepared statement with bound values
48
- const parsedQuery = webDb.parseQueryToPrepared(query);
49
- if (parsedQuery.isPrepared) {
50
- var stmt = db.prepare(parsedQuery.query);
51
- stmt.run(parsedQuery.values);
52
- stmt.free();
53
- } else {
54
- // Fallback to exec for queries without parameters
55
- db.exec(query);
56
- }
57
- sucessCallback("Success");
50
+ stmt = db.prepare(query);
58
51
  }
52
+
53
+ // Execute statement and capture results if any
54
+ let rows = [];
55
+ while (stmt.step()) {
56
+ rows.push(stmt.getAsObject());
57
+ }
58
+ stmt.free();
59
+
60
+ sucessCallback(rows);
59
61
  }
60
62
  catch (err) {
61
63
  console.error("Error executing query: " + query, err);
@@ -252,7 +254,7 @@ var webDb = /** @class */ (function () {
252
254
 
253
255
  // If query already contains positional placeholders, don't attempt to re-parameterize it.
254
256
  if (query.indexOf('?') !== -1) {
255
- return { isPrepared: false, query: query, values: [] };
257
+ return { query: query, values: [] };
256
258
  }
257
259
  if (queryUpper.startsWith('CREATE') ||
258
260
  queryUpper.startsWith('DROP') ||
@@ -276,7 +278,7 @@ var webDb = /** @class */ (function () {
276
278
  // DDL/transactional statements and similar should not be parameterized.
277
279
  // Note: INSERT ... VALUES will be parameterized below so large
278
280
  // string/numeric literals (eg. base64 blobs) can be bound safely.
279
- return { isPrepared: false, query: query, values: [] };
281
+ return { query: query, values: [] };
280
282
  }
281
283
 
282
284
 
@@ -285,7 +287,7 @@ var webDb = /** @class */ (function () {
285
287
  const hasNumericLiterals = /\b\d+\.?\d*\b/.test(query);
286
288
 
287
289
  if (!hasStringLiterals && !hasNumericLiterals) {
288
- return { isPrepared: false, query: query, values: [] };
290
+ return { query: query, values: [] };
289
291
  }
290
292
 
291
293
  // We'll scan the original query left-to-right and replace literals with
@@ -333,7 +335,7 @@ var webDb = /** @class */ (function () {
333
335
 
334
336
  if (!closed) {
335
337
  // Unmatched quote; bail out to safe fallback to avoid errors
336
- return { isPrepared: false, query: query, values: [] };
338
+ return { query: query, values: [] };
337
339
  }
338
340
 
339
341
  // Extract content and handle escaped quotes
@@ -396,13 +398,13 @@ var webDb = /** @class */ (function () {
396
398
 
397
399
  // If we didn't find any bindable literals, don't treat as prepared
398
400
  if (values.length === 0) {
399
- return { isPrepared: false, query: query, values: [] };
401
+ return { query: query, values: [] };
400
402
  }
401
403
 
402
- return { isPrepared: true, query: preparedQuery, values: values };
404
+ return { query: preparedQuery, values: values };
403
405
  } catch (err) {
404
406
  console.warn('Error parsing query to prepared statement:', err);
405
- return { isPrepared: false, query: query, values: [] };
407
+ return { query: query, values: [] };
406
408
  }
407
409
  };
408
410
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordova-plugin-unvired-electron-db",
3
- "version": "0.0.42",
3
+ "version": "0.0.44",
4
4
  "description": "Unvired DB Native Support for Cordova",
5
5
  "main": "unvired-db-proxy.js",
6
6
  "author": "Unvired Inc",
@@ -52,6 +52,7 @@ const execute = (args) => {
52
52
  const userId = args[0].userId
53
53
  const dbType = args[0].dbType
54
54
  const query = args[0].query;
55
+ const queryArgs = args[0].args || [];
55
56
 
56
57
  if (userId == undefined || userId == null || userId == "") {
57
58
  reject("userId is required")
@@ -79,24 +80,13 @@ const execute = (args) => {
79
80
  }
80
81
  }
81
82
 
82
- if (query.toUpperCase().includes("SELECT")) {
83
- db.all(query, [], (err, rows) => {
84
- if (err) {
85
- reject(err)
86
- } else {
87
- resolve(rows)
88
- }
89
- });
90
- }
91
- else {
92
- db.run(query, (err) => {
93
- if (err) {
94
- reject(err)
95
- } else {
96
- resolve("Success")
97
- }
98
- });
99
- }
83
+ db.all(query, queryArgs, (err, rows) => {
84
+ if (err) {
85
+ reject(err)
86
+ } else {
87
+ resolve(rows || []) // Ensure we return an array
88
+ }
89
+ });
100
90
  });
101
91
  }
102
92
 
@@ -129,12 +129,12 @@ static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
129
129
  // enable foreign Keys ON
130
130
  NSError *error = NULL;
131
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];
132
+ [self executeQuery:@"PRAGMA journal_mode = WAL;" args:nil sqlDb:self->fwDb error:&error];
133
+ [self executeQuery:@"PRAGMA read_uncommitted = 1;" args:nil sqlDb:self->fwDb error:&error];
134
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];
135
+ [self executeQuery:@"PRAGMA journal_mode = WAL;" args:nil sqlDb:self->appDb error:&error];
136
+ [self executeQuery:@"PRAGMA foreign_keys = ON;" args:nil sqlDb:self->appDb error:&error];
137
+ [self executeQuery:@"PRAGMA read_uncommitted = 1;" args:nil sqlDb:self->appDb error:&error];
138
138
  pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:true];
139
139
  [pluginResult setKeepCallbackAsBool:true];
140
140
  [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
@@ -160,6 +160,7 @@ static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
160
160
  NSString *userId = dataObjects[@"userId"];
161
161
  NSString *dbType = dataObjects[@"dbType"];
162
162
  NSString *query = dataObjects[@"query"];
163
+ NSArray *args = dataObjects[@"args"];
163
164
 
164
165
  sqlite3 *sql = [dbType isEqualToString:DBTypeFrameworkDb] ? self->fwDb : self->appDb;
165
166
 
@@ -173,11 +174,7 @@ static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
173
174
  }
174
175
 
175
176
  // 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
- }
177
+ result = [self executeQuery:query args:args sqlDb:sql error:&error];
181
178
  if (error == NULL) {
182
179
  pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:result];
183
180
  }
@@ -309,7 +306,7 @@ static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
309
306
  return YES;
310
307
  }
311
308
 
312
- - (NSArray *)executeQuery:(NSString *)sqlStatement sqlDb:(sqlite3 *)sql error:(NSError **)error {
309
+ - (NSArray *)executeQuery:(NSString *)sqlStatement args:(NSArray *)args sqlDb:(sqlite3 *)sql error:(NSError **)error {
313
310
 
314
311
  sqlite3_stmt *statement;
315
312
  statement = [self prepareStatement:sqlStatement sqlDb:sql error:error];
@@ -317,6 +314,27 @@ static const NSString *DBTypeFrameworkDb = @"FrameworkDb";
317
314
  if (statement == NULL) {
318
315
  return NULL;
319
316
  }
317
+
318
+ if (args && [args isKindOfClass:[NSArray class]] && [args count] > 0) {
319
+ for (int i = 0; i < [args count]; i++) {
320
+ id val = args[i];
321
+ int idx = i + 1;
322
+ if ([val isKindOfClass:[NSString class]]) {
323
+ sqlite3_bind_text(statement, idx, [val UTF8String], -1, SQLITE_TRANSIENT);
324
+ } else if ([val isKindOfClass:[NSNumber class]]) {
325
+ const char *objCType = [val objCType];
326
+ if (strcmp(objCType, @encode(double)) == 0 || strcmp(objCType, @encode(float)) == 0) {
327
+ sqlite3_bind_double(statement, idx, [val doubleValue]);
328
+ } else {
329
+ sqlite3_bind_int64(statement, idx, [val longLongValue]);
330
+ }
331
+ } else if ([val isKindOfClass:[NSNull class]]) {
332
+ sqlite3_bind_null(statement, idx);
333
+ } else {
334
+ sqlite3_bind_text(statement, idx, [[NSString stringWithFormat:@"%@", val] UTF8String], -1, SQLITE_TRANSIENT);
335
+ }
336
+ }
337
+ }
320
338
 
321
339
  NSLog(@"Statement: %@", sqlStatement);
322
340