Add first, elementary support for PRAGMA on Android

This commit is contained in:
Chris Brody 2012-12-03 23:13:34 +01:00
parent 5cd0e5b3f8
commit 938bce69b8
4 changed files with 129 additions and 6 deletions

View File

@ -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) ->

View File

@ -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);

View File

@ -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 + ");");
}
}

View File

@ -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");
});
});