diff --git a/Android/assets/www/SQLitePlugin-orig.coffee b/Android/assets/www/SQLitePlugin-orig.coffee index 813ac09..cc7e65f 100644 --- a/Android/assets/www/SQLitePlugin-orig.coffee +++ b/Android/assets/www/SQLitePlugin-orig.coffee @@ -38,6 +38,25 @@ do -> cordova.exec null, null, "SQLitePlugin", "close", [ @dbPath ] + pcb = -> 1 + + SQLitePlugin::executePragmaStatement = (statement, success, error) -> + console.log "SQLitePlugin::executePragmaStatement" + pcb = success + + cordova.exec (-> 1), error, "SQLitePlugin", "executePragmaStatement", [ "A-1", statement ] + return + + SQLitePluginCallback = + p1: (id, result) -> + console.log "PRAGMA CB" + + mycb = pcb + pcb = -> 1 + mycb result + + return + get_unique_id = -> id = new Date().getTime() id2 = new Date().getTime() @@ -185,6 +204,7 @@ do -> # required for callbacks: root.SQLitePluginTransaction = SQLitePluginTransaction + root.SQLitePluginCallback = SQLitePluginCallback root.sqlitePlugin = openDatabase: (dbPath, version, displayName, estimatedSize, creationCallback, errorCallback) -> diff --git a/Android/assets/www/SQLitePlugin.js b/Android/assets/www/SQLitePlugin.js index f9968de..c34e25b 100755 --- a/Android/assets/www/SQLitePlugin.js +++ b/Android/assets/www/SQLitePlugin.js @@ -1,5 +1,5 @@ (function() { - var SQLitePlugin, SQLitePluginTransaction, get_unique_id, root, transaction_callback_queue, transaction_queue; + var SQLitePlugin, SQLitePluginCallback, SQLitePluginTransaction, get_unique_id, pcb, root, transaction_callback_queue, transaction_queue; root = this; SQLitePlugin = function(dbPath, openSuccess, openError) { console.log("SQLitePlugin"); @@ -42,6 +42,27 @@ return cordova.exec(null, null, "SQLitePlugin", "close", [this.dbPath]); } }; + pcb = function() { + return 1; + }; + SQLitePlugin.prototype.executePragmaStatement = function(statement, success, error) { + console.log("SQLitePlugin::executePragmaStatement"); + pcb = success; + cordova.exec((function() { + return 1; + }), error, "SQLitePlugin", "executePragmaStatement", ["A-1", statement]); + }; + SQLitePluginCallback = { + p1: function(id, result) { + var mycb; + console.log("PRAGMA CB"); + mycb = pcb; + pcb = function() { + return 1; + }; + mycb(result); + } + }; get_unique_id = function() { var id, id2; id = new Date().getTime(); @@ -212,6 +233,7 @@ return cordova.exec(null, null, "SQLitePlugin", "executeSqlBatch", transaction_queue[this.trans_id]); }; root.SQLitePluginTransaction = SQLitePluginTransaction; + root.SQLitePluginCallback = SQLitePluginCallback; return root.sqlitePlugin = { openDatabase: function(dbPath, version, displayName, estimatedSize, creationCallback, errorCallback) { return new SQLitePlugin(dbPath, creationCallback, errorCallback); diff --git a/Android/src/com/phonegap/plugin/sqlitePlugin/SQLitePlugin.java b/Android/src/com/phonegap/plugin/sqlitePlugin/SQLitePlugin.java index 882e0e9..621f9ee 100755 --- a/Android/src/com/phonegap/plugin/sqlitePlugin/SQLitePlugin.java +++ b/Android/src/com/phonegap/plugin/sqlitePlugin/SQLitePlugin.java @@ -55,6 +55,13 @@ public class SQLitePlugin extends Plugin { //this.openDatabase(args.getString(0), args.getString(1), // args.getString(2), args.getLong(3)); } + else if (action.equals("executePragmaStatement")) + { + String id = args.getString(0); + String query = args.getString(1); + Cursor myCursor = this.myDb.rawQuery(query, null); + this.processPragmaResults(myCursor, id); + } else if (action.equals("executeSqlBatch")) { String[] queries = null; @@ -230,6 +237,7 @@ public class SQLitePlugin extends Plugin { try { for (int i = 0; i < colCount; ++i) { key = cur.getColumnName(i); + // for old Android SDK remove lines from HERE: if(android.os.Build.VERSION.SDK_INT >= 11) { @@ -271,4 +279,65 @@ public class SQLitePlugin extends Plugin { this.sendJavascript(" SQLitePluginTransaction.queryCompleteCallback('" + tx_id + "','" + query_id + "', " + result + ");"); } + + public void processPragmaResults(Cursor cur, String id) { + + String result = "[]"; + + // If query result has rows + if (cur.moveToFirst()) { + JSONArray fullresult = new JSONArray(); + String key = ""; + int colCount = cur.getColumnCount(); + + // Build up JSON result object for each row + do { + JSONObject row = new JSONObject(); + try { + for (int i = 0; i < colCount; ++i) { + key = cur.getColumnName(i); + + // XXX TBD factor out: + // for old Android SDK remove lines from HERE: + if(android.os.Build.VERSION.SDK_INT >= 11) + { + switch(cur.getType (i)) + { + case Cursor.FIELD_TYPE_NULL: + row.put(key, null); + break; + case Cursor.FIELD_TYPE_INTEGER: + row.put(key, cur.getInt(i)); + break; + case Cursor.FIELD_TYPE_FLOAT: + row.put(key, cur.getFloat(i)); + break; + case Cursor.FIELD_TYPE_STRING: + row.put(key, cur.getString(i)); + break; + case Cursor.FIELD_TYPE_BLOB: + row.put(key, cur.getBlob(i)); + break; + } + } + else // to HERE. + { + row.put(key, cur.getString(i)); + } + } + + fullresult.put(row); + + } catch (JSONException e) { + e.printStackTrace(); + } + + } while (cur.moveToNext()); + + result = fullresult.toString(); + } + + this.sendJavascript(" SQLitePluginCallback.p1('" + id + "', " + result + ");"); + + } } diff --git a/README.md b/README.md index 51dd03f..48eb56d 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,8 @@ Nested transaction callback support by @marcucio ## Announcements - - The Android version will now be maintained here. - - [Android version with rebuilding SQLCipher from source](http://mobileapphelp.blogspot.com/2012/08/rebuilding-sqlitesqlcipher-for-android.html) - - [Android version tested with SQLCipher for database encryption](http://mobileapphelp.blogspot.com/2012/08/trying-sqlcipher-with-cordova.html), working with a few changes to SQLitePlugin.java + - Elementary support for sqlite PRAGMAs has now been added to this version for Android. + - The Android version is now maintained in this location. ## Highlights @@ -18,6 +17,12 @@ Nested transaction callback support by @marcucio - Drop-in replacement for HTML5 SQL API, the only change is window.openDatabase() --> sqlitePlugin.openDatabase() - batch processing optimizations +This sqlitePlugin can also be used with SQLCipher to provide encryption. This was already described on my old blog: + - [Android version with rebuilding SQLCipher from source](http://mobileapphelp.blogspot.com/2012/08/rebuilding-sqlitesqlcipher-for-android.html) + - [Android version tested with SQLCipher for database encryption](http://mobileapphelp.blogspot.com/2012/08/trying-sqlcipher-with-cordova.html), working with a few changes to SQLitePlugin.java + +I have recently discovered [here](https://guardianproject.info/code/sqlcipher/) that a PRAGMA can also be used to set the encryption key. My next step is to post some updated instructions to my [new blog](http://brodyspark.blogspot.com/). + ## Apps using PhoneGap/Cordova sqlitePlugin (Android version) - [Get It Done app](http://getitdoneapp.com/) by [marcucio.com](http://marcucio.com/) @@ -35,8 +40,7 @@ Usage The idea is to emulate the HTML5 SQL API as closely as possible. The only major change is to use window.sqlitePlugin.openDatabase() (or sqlitePlugin.openDatabase()) instead of window.openDatabase(). If you see any other major change please report it, it is probably a bug. -Sample ------- +# Sample with PRAGMA feature This is a pretty strong test: first we create a table and add a single entry, then query the count to check if the item was inserted as expected. Note that a new transaction is created in the middle of the first callback. @@ -53,13 +57,21 @@ This is a pretty strong test: first we create a table and add a single entry, th tx.executeSql('DROP TABLE IF EXISTS test_table'); tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)'); + // demonstrate PRAGMA on Android: + db.executePragmaStatement("pragma table_info (test_table);", function(res) { + alert("PRAGMA res: " + JSON.stringify(res)); + }); + tx.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function(tx, res) { console.log("insertId: " + res.insertId + " -- probably 1"); console.log("rowsAffected: " + res.rowsAffected + " -- should be 1"); + alert("insertId: " + res.insertId + " -- probably 1"); + db.transaction(function(tx) { tx.executeSql("select count(id) as cnt from test_table;", [], function(tx, res) { console.log("res.rows.length: " + res.rows.length + " -- should be 1"); console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1"); + alert("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1"); }); });