mirror of
https://github.com/moparisthebest/PhoneGap-SQLitePlugin-Android
synced 2024-11-13 12:35:09 -05:00
Original DroidGap version in Simple-DroidGap-test to work on issue #18
This commit is contained in:
parent
406017ce80
commit
67cd416c70
342
Simple-DroidGap-test/assets/www/SQLitePlugin.js
Normal file
342
Simple-DroidGap-test/assets/www/SQLitePlugin.js
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is purely for the Android 1.5/1.6 HTML 5 Storage
|
||||
* I was hoping that Android 2.0 would deprecate this, but given the fact that
|
||||
* most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required
|
||||
*/
|
||||
|
||||
|
||||
// XXX TODO: use function() { ... } () to encapsulate these declarations (except for Java callback)
|
||||
|
||||
/**
|
||||
* SQL result set object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Rows = function() {
|
||||
this.resultSet = []; // results array
|
||||
this.length = 0; // number of rows
|
||||
};
|
||||
|
||||
/**
|
||||
* Get item from SQL result set
|
||||
*
|
||||
* @param row The row number to return
|
||||
* @return The row object
|
||||
*/
|
||||
DDB_Rows.prototype.item = function(row) {
|
||||
return this.resultSet[row];
|
||||
};
|
||||
|
||||
/**
|
||||
* SQL result set that is returned to user.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Result = function() {
|
||||
this.rows = new DDB_Rows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage object that is called by native code when performing queries.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB = function() {
|
||||
this.queryQueue = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query is complete.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB.prototype.completeQuery = function(id, data) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
|
||||
// Save query results
|
||||
var r = new DDB_Result();
|
||||
r.rows.resultSet = data;
|
||||
r.rows.length = data.length;
|
||||
try {
|
||||
if (typeof query.successCallback === 'function') {
|
||||
query.successCallback(query.tx, r);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user success callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryComplete(id);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query fails
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param reason Error message
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB.prototype.fail = function(reason, id) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
tx.queryList = {};
|
||||
|
||||
try {
|
||||
if (typeof query.errorCallback === 'function') {
|
||||
query.errorCallback(query.tx, reason);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user error callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryFailed(id, reason);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mycreateUUID = function() {
|
||||
return myUUIDcreatePart(4) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(6);
|
||||
};
|
||||
|
||||
myUUIDcreatePart = function(length) {
|
||||
var uuidpart = "";
|
||||
var i, uuidchar;
|
||||
for (i=0; i<length; i++) {
|
||||
uuidchar = parseInt((Math.random() * 256),0).toString(16);
|
||||
if (uuidchar.length === 1) {
|
||||
uuidchar = "0" + uuidchar;
|
||||
}
|
||||
uuidpart += uuidchar;
|
||||
}
|
||||
return uuidpart;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SQL query object
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @constructor
|
||||
* @param tx The transaction object that this query belongs to
|
||||
*/
|
||||
var DDB_Query = function(tx) {
|
||||
|
||||
// Set the id of the query
|
||||
this.id = mycreateUUID();
|
||||
|
||||
// Add this query to the queue
|
||||
dddb.queryQueue[this.id] = this;
|
||||
|
||||
// Init result
|
||||
this.resultSet = [];
|
||||
|
||||
// Set transaction that this query belongs to
|
||||
this.tx = tx;
|
||||
|
||||
// Add this query to transaction list
|
||||
this.tx.queryList[this.id] = this;
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Transaction object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Tx = function() {
|
||||
|
||||
// Set the id of the transaction
|
||||
this.id = mycreateUUID();
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
// Query list
|
||||
this.queryList = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as complete.
|
||||
* If all queries are complete, call the user's transaction success callback.
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB_Tx.prototype.queryComplete = function(id) {
|
||||
delete this.queryList[id];
|
||||
|
||||
// If no more outstanding queries, then fire transaction success
|
||||
if (this.successCallback) {
|
||||
var count = 0;
|
||||
var i;
|
||||
for (i in this.queryList) {
|
||||
if (this.queryList.hasOwnProperty(i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count === 0) {
|
||||
try {
|
||||
this.successCallback();
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user success callback: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as failed.
|
||||
*
|
||||
* @param id Query id
|
||||
* @param reason Error message
|
||||
*/
|
||||
DDB_Tx.prototype.queryFailed = function(id, reason) {
|
||||
|
||||
// The sql queries in this transaction have already been run, since
|
||||
// we really don't have a real transaction implemented in native code.
|
||||
// However, the user callbacks for the remaining sql queries in transaction
|
||||
// will not be called.
|
||||
this.queryList = {};
|
||||
|
||||
if (this.errorCallback) {
|
||||
try {
|
||||
this.errorCallback(reason);
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user error callback: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute SQL statement
|
||||
*
|
||||
* @param sql SQL statement to execute
|
||||
* @param params Statement parameters
|
||||
* @param successCallback Success callback
|
||||
* @param errorCallback Error callback
|
||||
*/
|
||||
DDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
|
||||
|
||||
// Init params array
|
||||
if (typeof params === 'undefined') {
|
||||
params = [];
|
||||
}
|
||||
|
||||
// Create query and add to queue
|
||||
var query = new DDB_Query(this);
|
||||
dddb.queryQueue[query.id] = query;
|
||||
|
||||
// Save callbacks
|
||||
query.successCallback = successCallback;
|
||||
query.errorCallback = errorCallback;
|
||||
|
||||
// Call native code
|
||||
PhoneGap.exec(null, null, "SQLitePlugin", "executeSql", [sql, params, query.id]);
|
||||
};
|
||||
|
||||
var DatabaseShell = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
* Does not support rollback in event of failure.
|
||||
*
|
||||
* @param process {Function} The transaction function
|
||||
* @param successCallback {Function}
|
||||
* @param errorCallback {Function}
|
||||
*/
|
||||
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
|
||||
var tx = new DDB_Tx();
|
||||
tx.successCallback = successCallback;
|
||||
tx.errorCallback = errorCallback;
|
||||
try {
|
||||
process(tx);
|
||||
} catch (e) {
|
||||
console.log("Transaction error: "+e);
|
||||
if (tx.errorCallback) {
|
||||
try {
|
||||
tx.errorCallback(e);
|
||||
} catch (ex) {
|
||||
console.log("Transaction error calling user error callback: "+e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open database
|
||||
*
|
||||
* @param name Database name
|
||||
* @param version Database version
|
||||
* @param display_name Database display name
|
||||
* @param size Database size in bytes
|
||||
* @return Database object
|
||||
*/
|
||||
var DDB_openDatabase = function(name, version, display_name, size) {
|
||||
PhoneGap.exec(null, null, "SQLitePlugin", "openDatabase", [name, version, display_name, size]);
|
||||
var db = new DatabaseShell();
|
||||
return db;
|
||||
};
|
||||
|
||||
/**
|
||||
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
|
||||
* TODO: Do similar for sessionStorage.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
window.sqlitePlugin = {
|
||||
openDatabase: function(name, version, desc, size) {
|
||||
window.dddb = new DDB();
|
||||
return DDB_openDatabase(name, version, desc, size);
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap.plugin.sqlitePlugin;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.*;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class implements the HTML5 database support for Android 1.X devices. It
|
||||
* is not used for Android 2.X, since HTML5 database is built in to the browser.
|
||||
*/
|
||||
public class SQLitePlugin extends Plugin {
|
||||
|
||||
// Data Definition Language
|
||||
private static final String ALTER = "alter";
|
||||
private static final String CREATE = "create";
|
||||
private static final String DROP = "drop";
|
||||
private static final String TRUNCATE = "truncate";
|
||||
|
||||
SQLiteDatabase myDb = null; // Database object
|
||||
String path = null; // Database path
|
||||
String dbName = null; // Database name
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SQLitePlugin() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action
|
||||
* The action to execute.
|
||||
* @param args
|
||||
* JSONArry of arguments for the plugin.
|
||||
* @param callbackId
|
||||
* The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
// TODO: Do we want to allow a user to do this, since they could get
|
||||
// to other app databases?
|
||||
if (action.equals("setStorage")) {
|
||||
this.setStorage(args.getString(0));
|
||||
} else if (action.equals("openDatabase")) {
|
||||
this.openDatabase(args.getString(0), args.getString(1),
|
||||
args.getString(2), args.getLong(3));
|
||||
} else if (action.equals("executeSql")) {
|
||||
String[] s = null;
|
||||
if (args.isNull(1)) {
|
||||
s = new String[0];
|
||||
} else {
|
||||
JSONArray a = args.getJSONArray(1);
|
||||
int len = a.length();
|
||||
s = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
s[i] = a.getString(i);
|
||||
}
|
||||
}
|
||||
this.executeSql(args.getString(0), s, args.getString(2));
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies if action to be executed returns a value and should be run
|
||||
* synchronously.
|
||||
*
|
||||
* @param action
|
||||
* The action to execute
|
||||
* @return T=returns value
|
||||
*/
|
||||
public boolean isSynch(String action) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up and close database.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (this.myDb != null) {
|
||||
this.myDb.close();
|
||||
this.myDb = null;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the application package for the database. Each application saves its
|
||||
* database files in a directory with the application package as part of the
|
||||
* file name.
|
||||
*
|
||||
* For example, application "com.phonegap.demo.Demo" would save its database
|
||||
* files in "/data/data/com.phonegap.demo/databases/" directory.
|
||||
*
|
||||
* @param appPackage
|
||||
* The application package.
|
||||
*/
|
||||
public void setStorage(String appPackage) {
|
||||
this.path = "/data/data/" + appPackage + "/databases/";
|
||||
}
|
||||
|
||||
/**
|
||||
* Open database.
|
||||
*
|
||||
* @param db
|
||||
* The name of the database
|
||||
* @param version
|
||||
* The version
|
||||
* @param display_name
|
||||
* The display name
|
||||
* @param size
|
||||
* The size in bytes
|
||||
*/
|
||||
public void openDatabase(String db, String version, String display_name,
|
||||
long size) {
|
||||
|
||||
// If database is open, then close it
|
||||
if (this.myDb != null) {
|
||||
this.myDb.close();
|
||||
}
|
||||
|
||||
// If no database path, generate from application package
|
||||
if (this.path == null) {
|
||||
Package pack = this.ctx.getClass().getPackage();
|
||||
String appPackage = pack.getName();
|
||||
this.setStorage(appPackage);
|
||||
}
|
||||
|
||||
this.dbName = this.path + db + ".db";
|
||||
this.myDb = SQLiteDatabase.openOrCreateDatabase(this.dbName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute SQL statement.
|
||||
*
|
||||
* @param query
|
||||
* The SQL query
|
||||
* @param params
|
||||
* Parameters for the query
|
||||
* @param tx_id
|
||||
* Transaction id
|
||||
*/
|
||||
public void executeSql(String query, String[] params, String tx_id) {
|
||||
try {
|
||||
if (isDDL(query)) {
|
||||
this.myDb.execSQL(query);
|
||||
this.sendJavascript("dddb.completeQuery('" + tx_id + "', '');");
|
||||
}
|
||||
else {
|
||||
Cursor myCursor = this.myDb.rawQuery(query, params);
|
||||
this.processResults(myCursor, tx_id);
|
||||
myCursor.close();
|
||||
}
|
||||
}
|
||||
catch (SQLiteException ex) {
|
||||
ex.printStackTrace();
|
||||
System.out.println("SQLitePlugin.executeSql(): Error=" + ex.getMessage());
|
||||
|
||||
// Send error message back to JavaScript
|
||||
this.sendJavascript("dddb.fail('" + ex.getMessage() + "','" + tx_id + "');");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see the the query is a Data Definintion command
|
||||
*
|
||||
* @param query to be executed
|
||||
* @return true if it is a DDL command, false otherwise
|
||||
*/
|
||||
private boolean isDDL(String query) {
|
||||
String cmd = query.toLowerCase();
|
||||
if (cmd.startsWith(DROP) || cmd.startsWith(CREATE) || cmd.startsWith(ALTER) || cmd.startsWith(TRUNCATE)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process query results.
|
||||
*
|
||||
* @param cur
|
||||
* Cursor into query results
|
||||
* @param tx_id
|
||||
* Transaction id
|
||||
*/
|
||||
public void processResults(Cursor cur, String tx_id) {
|
||||
|
||||
String result = "[]";
|
||||
// If query result has rows
|
||||
|
||||
if (cur.moveToFirst()) {
|
||||
JSONArray fullresult = new JSONArray();
|
||||
String key = "";
|
||||
String value = "";
|
||||
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);
|
||||
value = cur.getString(i);
|
||||
row.put(key, value);
|
||||
}
|
||||
fullresult.put(row);
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} while (cur.moveToNext());
|
||||
|
||||
result = fullresult.toString();
|
||||
}
|
||||
|
||||
// Let JavaScript know that there are no more rows
|
||||
this.sendJavascript("dddb.completeQuery('" + tx_id + "', " + result
|
||||
+ ");");
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user