mirror of
https://github.com/moparisthebest/PhoneGap-SQLitePlugin-Android
synced 2024-11-13 12:35:09 -05:00
Cleanup project: remove old DroidGap, PGSQLite versions, iOS from @marcucio is PG1.4- (had no batching improvements)
This commit is contained in:
parent
fd3eaad9c2
commit
be092c1d3f
@ -1,342 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
};
|
||||
|
@ -1,111 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=320; user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>PhoneGap</title>
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8">
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="SQLitePlugin.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" >
|
||||
|
||||
function init1test() {
|
||||
//alert("alert 0");
|
||||
}
|
||||
|
||||
// Wait for PhoneGap to load
|
||||
//
|
||||
document.addEventListener("deviceready", onDeviceReady, false);
|
||||
|
||||
// PhoneGap is ready
|
||||
//
|
||||
function onDeviceReady() {
|
||||
var db = window.sqlitePlugin.openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
|
||||
|
||||
db.transaction(function(tx) {
|
||||
|
||||
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)');
|
||||
|
||||
|
||||
return 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");
|
||||
|
||||
tx.executeSql("select count(id) as cnt from test_table;", [], function(tx, res) {
|
||||
console.log("rows.length: " + res.rows.length + " -- should be 1");
|
||||
return console.log("rows[0].cnt: " + res.rows.item(0).cnt + " -- should be 1");
|
||||
});
|
||||
|
||||
}, function(e) {
|
||||
return console.log("ERROR: " + e.message);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Populate the database
|
||||
//
|
||||
function populateDB(tx) {
|
||||
alert("a 3");
|
||||
tx.executeSql('DROP TABLE IF EXISTS DEMO');
|
||||
alert("a 4");
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
|
||||
alert("a 5");
|
||||
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');
|
||||
alert("a 6");
|
||||
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');
|
||||
alert("a 7");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Transaction error callback
|
||||
//
|
||||
function errorCB(tx, err) {
|
||||
alert("Error processing SQL: "+err);
|
||||
}
|
||||
|
||||
// Transaction success callback
|
||||
//
|
||||
function successCB() {
|
||||
alert("success!");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body onload="init1test();" id="stage" class="theme">
|
||||
<h1>Welcome to PhoneGap!</h1>
|
||||
<h2>this file is located at assets/www/index.html</h2>
|
||||
<div id="info">
|
||||
<h4>Platform: <span id="platform"> </span>, Version: <span id="version"> </span></h4>
|
||||
<h4>UUID: <span id="uuid"> </span>, Name: <span id="name"> </span></h4>
|
||||
<h4>Width: <span id="width"> </span>, Height: <span id="height">
|
||||
</span>, Color Depth: <span id="colorDepth"></span></h4>
|
||||
</div>
|
||||
<dl id="accel-data">
|
||||
<dt>X:</dt><dd id="x"> </dd>
|
||||
<dt>Y:</dt><dd id="y"> </dd>
|
||||
<dt>Z:</dt><dd id="z"> </dd>
|
||||
</dl>
|
||||
<a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
|
||||
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
|
||||
<a href="tel:411" class="btn large">Call 411</a>
|
||||
<a href="#" class="btn large" onclick="beep();">Beep</a>
|
||||
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
|
||||
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
|
||||
<a href="#" class="btn large" onclick="get_contacts();">Get Phone's Contacts</a>
|
||||
<a href="#" class="btn large" onclick="check_network();">Check Network</a>
|
||||
<div id="viewport" class="viewport" style="display: none;">
|
||||
<img style="width:60px;height:60px" id="test_img" src="" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,248 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
+ ");");
|
||||
|
||||
}
|
||||
|
||||
}
|
44
README.md
44
README.md
@ -9,10 +9,10 @@ Created by @Joenoon:
|
||||
|
||||
Adapted to 1.5 by @coomsie
|
||||
|
||||
Major improvements for batch processing by @marcucio
|
||||
|
||||
Android version by @marcucio and @chbrody
|
||||
|
||||
Major improvements for batch processing by @marcucio (Android version)
|
||||
|
||||
API changes by @chbrody
|
||||
|
||||
DISCLAIMER:
|
||||
@ -61,11 +61,9 @@ Installing
|
||||
|
||||
**NOTE:** There are now the following trees:
|
||||
|
||||
- `iOS`: new version by @marcucio, with improvements for batch transaction processing, testing seems OK, **TBD** needs to be ported to Cordova 1.5/1.6
|
||||
- `Cordova-iOS` for Cordova 1.5/1.6 iOS
|
||||
- `Legacy-PhoneGap-iPhone` for PhoneGap (tested 1.3 and earlier).
|
||||
- `iOS-legacy-phonegap` to support new API for PhoneGap 1.4- (cleanups by @marcucio)
|
||||
- `Android`: new version by @marcucio, with improvements for batch transaction processing, testing seems OK
|
||||
- `DroidGap-old`: initial adaptation for Android, expected to go away pretty soon.
|
||||
|
||||
Cordova 1.6 (RC)
|
||||
----------------
|
||||
@ -91,7 +89,7 @@ PhoneGap 1.3.0
|
||||
--------------
|
||||
|
||||
For installing with PhoneGap 1.3.0:
|
||||
in PGSQLitePlugin.h file change for PhoneGaps JSONKit.h implementation.
|
||||
in iOS-legacy-phonegap/SQLitePlugin.h file change for PhoneGap's JSONKit.h implementation.
|
||||
|
||||
#ifdef PHONEGAP_FRAMEWORK
|
||||
#import <PhoneGap/PGPlugin.h>
|
||||
@ -106,10 +104,8 @@ in PGSQLitePlugin.h file change for PhoneGaps JSONKit.h implementation.
|
||||
#import "File.h"
|
||||
#endif
|
||||
|
||||
and in PGSQLitePlugin.m JSONRepresentation must be changed to JSONString:
|
||||
and in iOS-legacy-phonegap/SQLitePlugin.m JSONRepresentation must be changed to JSONString:
|
||||
|
||||
--- a/Plugins/PGSQLitePlugin.m
|
||||
+++ b/Plugins/PGSQLitePlugin.m
|
||||
@@ -219,7 +219,7 @@
|
||||
if (hasInsertId) {
|
||||
[resultSet setObject:insertId forKey:@"insertId"];
|
||||
@ -149,25 +145,13 @@ Insert this in there:
|
||||
<key>SQLitePlugin</key>
|
||||
<string>SQLitePlugin</string>
|
||||
|
||||
**NOTE:** For `Legacy-PhoneGap-iPhone` the plugin name is `PGSQLitePlugin`, no fix is expected in this project.
|
||||
Extra Usage
|
||||
===========
|
||||
|
||||
General Usage
|
||||
=============
|
||||
Cordova iOS
|
||||
-----------
|
||||
|
||||
Android
|
||||
-------
|
||||
|
||||
Tested OK using the Lawnchair test suite. Old DroidGap version is expected to go away very soon, yes I did repeat myself!
|
||||
|
||||
New iOS version
|
||||
---------------
|
||||
|
||||
Tested OK using the sample above and the Lawnchair test suite. Needs to be ported for Cordova 1.5/1.6+. Old version will go away if there are no major issues.
|
||||
|
||||
Cordova iOS (stable version)
|
||||
----------------------------
|
||||
|
||||
**NOTE:** Please use sqlitePlugin.openDatabase() to open a database, the parameters are different from the old SQLitePlugin() constructor which is now gone. This should a closer resemblance to the HTML5/W3 SQL API.
|
||||
**NOTE:** These are from old samples, old API which is hereby deprecated.
|
||||
|
||||
## Coffee Script
|
||||
|
||||
@ -231,7 +215,7 @@ Cordova iOS (stable version)
|
||||
});
|
||||
|
||||
|
||||
Legacy PhoneGap (old version)
|
||||
iOS Legacy PhoneGap
|
||||
-----------------------------
|
||||
|
||||
## Coffee Script
|
||||
@ -333,14 +317,12 @@ Using the `db` option you can create multiple stores in one sqlite file. (There
|
||||
Legacy Lawnchair test
|
||||
---------------------
|
||||
|
||||
In the lawnchair-test subdirectory of Cordova-iOS or Legacy-PhoneGap-iPhone you can copy the contents of the www subdirectory into a Cordova/PhoneGap project and see the behavior of the Lawnchair test suite.
|
||||
In the lawnchair-test subdirectory of Cordova-iOS you can copy the contents of the www subdirectory into a Cordova/PhoneGap project and see the behavior of the Lawnchair test suite.
|
||||
|
||||
Extra notes
|
||||
-----------
|
||||
|
||||
@marcucio has also made some improvements for batching in the iOS version in https://github.com/marcucio/Cordova-Plugins but I do not want to take these until I know it is working OK with multi-level transaction API.
|
||||
|
||||
Old baching notes, will go away:
|
||||
Old baching notes for iOS version:
|
||||
|
||||
### Other notes from @Joenoon:
|
||||
|
||||
|
45
iOS-legacy-phonegap/SQLitePlugin.h
Executable file
45
iOS-legacy-phonegap/SQLitePlugin.h
Executable file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Davide Bertola
|
||||
*
|
||||
* Authors:
|
||||
* Davide Bertola <dade@dadeb.it>
|
||||
* Joe Noon <joenoon@gmail.com>
|
||||
*
|
||||
* This library is available under the terms of the MIT License (2008).
|
||||
* See http://opensource.org/licenses/alphabetical for full text.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "sqlite3.h"
|
||||
|
||||
#ifdef PHONEGAP_FRAMEWORK
|
||||
#import <PhoneGap/PGPlugin.h>
|
||||
#import <PhoneGap/JSON.h>
|
||||
#import <PhoneGap/PhoneGapDelegate.h>
|
||||
#import <PhoneGap/File.h>
|
||||
#else
|
||||
#import "PGPlugin.h"
|
||||
#import "JSON.h"
|
||||
#import "PhoneGapDelegate.h"
|
||||
#import "File.h"
|
||||
#endif
|
||||
|
||||
@interface SQLitePlugin : PGPlugin {
|
||||
NSMutableDictionary *openDBs;
|
||||
}
|
||||
|
||||
@property (nonatomic, copy) NSMutableDictionary *openDBs;
|
||||
@property (nonatomic, retain) NSString *appDocsPath;
|
||||
|
||||
-(void) open:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) backgroundExecuteSqlBatch:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) backgroundExecuteSql:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) executeSqlBatch:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) executeSql:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) _executeSqlBatch:(NSMutableDictionary*)options;
|
||||
-(void) _executeSql:(NSMutableDictionary*)options;
|
||||
-(void) close: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
|
||||
-(void) respond: (id)cb withString:(NSString *)str withType:(NSString *)type;
|
||||
-(id) getDBPath:(id)dbFile;
|
||||
|
||||
@end
|
185
iOS-legacy-phonegap/SQLitePlugin.js
Executable file
185
iOS-legacy-phonegap/SQLitePlugin.js
Executable file
@ -0,0 +1,185 @@
|
||||
(function() {
|
||||
var callbacks, cbref, counter, getOptions, root;
|
||||
|
||||
root = this;
|
||||
|
||||
callbacks = {};
|
||||
|
||||
counter = 0;
|
||||
|
||||
cbref = function(hash) {
|
||||
var f;
|
||||
f = "cb" + (counter += 1);
|
||||
callbacks[f] = hash;
|
||||
return f;
|
||||
};
|
||||
|
||||
getOptions = function(opts, success, error) {
|
||||
var cb, has_cbs;
|
||||
cb = {};
|
||||
has_cbs = false;
|
||||
if (typeof success === "function") {
|
||||
has_cbs = true;
|
||||
cb.success = success;
|
||||
}
|
||||
if (typeof error === "function") {
|
||||
has_cbs = true;
|
||||
cb.error = error;
|
||||
}
|
||||
if (has_cbs) opts.callback = cbref(cb);
|
||||
return opts;
|
||||
};
|
||||
|
||||
root.SQLitePlugin = (function() {
|
||||
|
||||
SQLitePlugin.prototype.openDBs = {};
|
||||
|
||||
function SQLitePlugin(dbPath, openSuccess, openError) {
|
||||
this.dbPath = dbPath;
|
||||
this.openSuccess = openSuccess;
|
||||
this.openError = openError;
|
||||
if (!dbPath) {
|
||||
throw new Error("Cannot create a SQLitePlugin instance without a dbPath");
|
||||
}
|
||||
this.openSuccess || (this.openSuccess = function() {
|
||||
console.log("DB opened: " + dbPath);
|
||||
});
|
||||
this.openError || (this.openError = function(e) {
|
||||
console.log(e.message);
|
||||
});
|
||||
this.open(this.openSuccess, this.openError);
|
||||
}
|
||||
|
||||
SQLitePlugin.handleCallback = function(ref, type, obj) {
|
||||
var _ref;
|
||||
if ((_ref = callbacks[ref]) != null) {
|
||||
if (typeof _ref[type] === "function") _ref[type](obj);
|
||||
}
|
||||
callbacks[ref] = null;
|
||||
delete callbacks[ref];
|
||||
};
|
||||
|
||||
SQLitePlugin.prototype.executeSql = function(sql, values, success, error) {
|
||||
var opts;
|
||||
if (!sql) throw new Error("Cannot executeSql without a query");
|
||||
opts = getOptions({
|
||||
query: [sql].concat(values || []),
|
||||
path: this.dbPath
|
||||
}, success, error);
|
||||
PhoneGap.exec("SQLitePlugin.backgroundExecuteSql", opts);
|
||||
};
|
||||
|
||||
SQLitePlugin.prototype.transaction = function(fn, error, success) {
|
||||
var t;
|
||||
t = new root.SQLitePluginTransaction(this.dbPath);
|
||||
fn(t);
|
||||
return t.complete(success, error);
|
||||
};
|
||||
|
||||
SQLitePlugin.prototype.open = function(success, error) {
|
||||
var opts;
|
||||
if (!(this.dbPath in this.openDBs)) {
|
||||
this.openDBs[this.dbPath] = true;
|
||||
opts = getOptions({
|
||||
path: this.dbPath
|
||||
}, success, error);
|
||||
PhoneGap.exec("SQLitePlugin.open", opts);
|
||||
}
|
||||
};
|
||||
|
||||
SQLitePlugin.prototype.close = function(success, error) {
|
||||
var opts;
|
||||
if (this.dbPath in this.openDBs) {
|
||||
delete this.openDBs[this.dbPath];
|
||||
opts = getOptions({
|
||||
path: this.dbPath
|
||||
}, success, error);
|
||||
PhoneGap.exec("SQLitePlugin.close", opts);
|
||||
}
|
||||
};
|
||||
|
||||
return SQLitePlugin;
|
||||
|
||||
})();
|
||||
|
||||
root.SQLitePluginTransaction = (function() {
|
||||
|
||||
function SQLitePluginTransaction(dbPath) {
|
||||
this.dbPath = dbPath;
|
||||
this.executes = [];
|
||||
}
|
||||
|
||||
SQLitePluginTransaction.prototype.executeSql = function(sql, values, success, error) {
|
||||
var errorcb, successcb, txself;
|
||||
txself = this;
|
||||
successcb = null;
|
||||
if (success) {
|
||||
successcb = function(execres) {
|
||||
var res, saveres;
|
||||
saveres = execres;
|
||||
res = {
|
||||
rows: {
|
||||
item: function(i) {
|
||||
return saveres.rows[i];
|
||||
},
|
||||
length: saveres.rows.length
|
||||
},
|
||||
rowsAffected: saveres.rowsAffected,
|
||||
insertId: saveres.insertId || null
|
||||
};
|
||||
return success(txself, res);
|
||||
};
|
||||
}
|
||||
errorcb = null;
|
||||
if (error) {
|
||||
errorcb = function(res) {
|
||||
return error(txself, res);
|
||||
};
|
||||
}
|
||||
this.executes.push(getOptions({
|
||||
query: [sql].concat(values || []),
|
||||
path: this.dbPath
|
||||
}, successcb, errorcb));
|
||||
};
|
||||
|
||||
SQLitePluginTransaction.prototype.complete = function(success, error) {
|
||||
var begin_opts, commit_opts, errorcb, executes, opts, successcb, txself;
|
||||
if (this.__completed) throw new Error("Transaction already run");
|
||||
this.__completed = true;
|
||||
txself = this;
|
||||
successcb = function(res) {
|
||||
return success(txself, res);
|
||||
};
|
||||
errorcb = function(res) {
|
||||
return error(txself, res);
|
||||
};
|
||||
begin_opts = getOptions({
|
||||
query: ["BEGIN;"],
|
||||
path: this.dbPath
|
||||
});
|
||||
commit_opts = getOptions({
|
||||
query: ["COMMIT;"],
|
||||
path: this.dbPath
|
||||
}, successcb, errorcb);
|
||||
executes = [begin_opts].concat(this.executes).concat([commit_opts]);
|
||||
opts = {
|
||||
executes: executes
|
||||
};
|
||||
PhoneGap.exec("SQLitePlugin.backgroundExecuteSqlBatch", opts);
|
||||
this.executes = [];
|
||||
};
|
||||
|
||||
return SQLitePluginTransaction;
|
||||
|
||||
})();
|
||||
root.sqlitePlugin = {
|
||||
openDatabase: function(dbPath, version, displayName, estimatedSize, creationCallback, errorCallback) {
|
||||
if (version == null) version = null;
|
||||
if (displayName == null) displayName = null;
|
||||
if (estimatedSize == null) estimatedSize = 0;
|
||||
if (creationCallback == null) creationCallback = null;
|
||||
if (errorCallback == null) errorCallback = null;
|
||||
return new SQLitePlugin(dbPath, creationCallback, errorCallback);
|
||||
}
|
||||
};
|
||||
}).call(this);
|
265
iOS-legacy-phonegap/SQLitePlugin.m
Executable file
265
iOS-legacy-phonegap/SQLitePlugin.m
Executable file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Davide Bertola
|
||||
*
|
||||
* Authors:
|
||||
* Davide Bertola <dade@dadeb.it>
|
||||
* Joe Noon <joenoon@gmail.com>
|
||||
*
|
||||
* This library is available under the terms of the MIT License (2008).
|
||||
* See http://opensource.org/licenses/alphabetical for full text.
|
||||
*/
|
||||
|
||||
|
||||
#import "SQLitePlugin.h"
|
||||
|
||||
@implementation SQLitePlugin
|
||||
|
||||
@synthesize openDBs;
|
||||
@synthesize appDocsPath;
|
||||
|
||||
-(PGPlugin*) initWithWebView:(UIWebView*)theWebView
|
||||
{
|
||||
self = (SQLitePlugin*)[super initWithWebView:theWebView];
|
||||
if (self) {
|
||||
openDBs = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
[openDBs retain];
|
||||
|
||||
PGFile* pgFile = [[self appDelegate] getCommandInstance: @"com.phonegap.file"];
|
||||
NSString *docs = [pgFile appDocsPath];
|
||||
[self setAppDocsPath:docs];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) respond: (id)cb withString:(NSString *)str withType:(NSString *)type {
|
||||
if (cb != NULL) {
|
||||
NSString* jsString = [NSString stringWithFormat:@"SQLitePlugin.handleCallback('%@', '%@', %@);", cb, type, str ];
|
||||
[self writeJavascript:jsString];
|
||||
}
|
||||
}
|
||||
|
||||
-(id) getDBPath:(id)dbFile {
|
||||
if (dbFile == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
NSString *dbPath = [NSString stringWithFormat:@"%@/%@", appDocsPath, dbFile];
|
||||
return dbPath;
|
||||
}
|
||||
|
||||
-(void) open: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
NSString *callback = [options objectForKey:@"callback"];
|
||||
NSString *dbPath = [self getDBPath:[options objectForKey:@"path"]];
|
||||
|
||||
if (dbPath == NULL) {
|
||||
[self respond:callback withString:@"{ message: 'You must specify database path' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3 *db;
|
||||
const char *path = [dbPath UTF8String];
|
||||
|
||||
if (sqlite3_open(path, &db) != SQLITE_OK) {
|
||||
[self respond:callback withString:@"{ message: 'Unable to open DB' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
|
||||
NSValue *dbPointer = [NSValue valueWithPointer:db];
|
||||
[openDBs setObject:dbPointer forKey: dbPath];
|
||||
[self respond:callback withString: @"{ message: 'Database opened' }" withType:@"success"];
|
||||
}
|
||||
|
||||
-(void) backgroundExecuteSqlBatch: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
[self performSelector:@selector(_executeSqlBatch:) withObject:options afterDelay:0.001];
|
||||
}
|
||||
|
||||
-(void) backgroundExecuteSql: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
[self performSelector:@selector(_executeSql:) withObject:options afterDelay:0.001];
|
||||
}
|
||||
|
||||
-(void) _executeSqlBatch:(NSMutableDictionary*)options
|
||||
{
|
||||
[self executeSqlBatch:NULL withDict:options];
|
||||
}
|
||||
|
||||
-(void) _executeSql:(NSMutableDictionary*)options
|
||||
{
|
||||
[self executeSql:NULL withDict:options];
|
||||
}
|
||||
|
||||
-(void) executeSqlBatch: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
NSMutableArray *executes = [options objectForKey:@"executes"];
|
||||
for (NSMutableDictionary *dict in executes) {
|
||||
[self executeSql:NULL withDict:dict];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) executeSql: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
NSString *callback = [options objectForKey:@"callback"];
|
||||
NSString *dbPath = [self getDBPath:[options objectForKey:@"path"]];
|
||||
NSMutableArray *query_parts = [options objectForKey:@"query"];
|
||||
NSString *query = [query_parts objectAtIndex:0];
|
||||
|
||||
if (dbPath == NULL) {
|
||||
[self respond:callback withString:@"{ message: 'You must specify database path' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
if (query == NULL) {
|
||||
[self respond:callback withString:@"{ message: 'You must specify a query to execute' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
|
||||
NSValue *dbPointer = [openDBs objectForKey:dbPath];
|
||||
if (dbPointer == NULL) {
|
||||
[self respond:callback withString:@"{ message: 'No such database, you must open it first' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
sqlite3 *db = [dbPointer pointerValue];
|
||||
|
||||
const char *sql_stmt = [query UTF8String];
|
||||
char *errMsg = NULL;
|
||||
sqlite3_stmt *statement;
|
||||
int result, i, column_type, count;
|
||||
int previousRowsAffected, nowRowsAffected, diffRowsAffected;
|
||||
long long previousInsertId, nowInsertId;
|
||||
BOOL keepGoing = YES;
|
||||
BOOL hasInsertId;
|
||||
NSMutableDictionary *resultSet = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
NSMutableArray *resultRows = [NSMutableArray arrayWithCapacity:0];
|
||||
NSMutableDictionary *entry;
|
||||
NSObject *columnValue;
|
||||
NSString *columnName;
|
||||
NSString *bindval;
|
||||
NSObject *insertId;
|
||||
NSObject *rowsAffected;
|
||||
|
||||
hasInsertId = NO;
|
||||
previousRowsAffected = sqlite3_total_changes(db);
|
||||
previousInsertId = sqlite3_last_insert_rowid(db);
|
||||
|
||||
if (sqlite3_prepare_v2(db, sql_stmt, -1, &statement, NULL) != SQLITE_OK) {
|
||||
errMsg = (char *) sqlite3_errmsg (db);
|
||||
keepGoing = NO;
|
||||
} else {
|
||||
for (int b = 1; b < query_parts.count; b++) {
|
||||
bindval = [NSString stringWithFormat:@"%@", [query_parts objectAtIndex:b]];
|
||||
sqlite3_bind_text(statement, b, [bindval UTF8String], -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
while (keepGoing) {
|
||||
result = sqlite3_step (statement);
|
||||
switch (result) {
|
||||
|
||||
case SQLITE_ROW:
|
||||
i = 0;
|
||||
entry = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
count = sqlite3_column_count(statement);
|
||||
|
||||
while (i < count) {
|
||||
column_type = sqlite3_column_type(statement, i);
|
||||
switch (column_type) {
|
||||
case SQLITE_INTEGER:
|
||||
columnValue = [NSNumber numberWithDouble: sqlite3_column_double(statement, i)];
|
||||
columnName = [NSString stringWithFormat:@"%s", sqlite3_column_name(statement, i)];
|
||||
[entry setObject:columnValue forKey:columnName];
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
columnValue = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, i)];
|
||||
columnName = [NSString stringWithFormat:@"%s", sqlite3_column_name(statement, i)];
|
||||
[entry setObject:columnValue forKey:columnName];
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
columnValue = [NSNumber numberWithFloat: sqlite3_column_double(statement, i)];
|
||||
columnName = [NSString stringWithFormat:@"%s", sqlite3_column_name(statement, i)];
|
||||
[entry setObject:columnValue forKey:columnName];
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
|
||||
}
|
||||
[resultRows addObject:entry];
|
||||
break;
|
||||
|
||||
case SQLITE_DONE:
|
||||
nowRowsAffected = sqlite3_total_changes(db);
|
||||
diffRowsAffected = nowRowsAffected - previousRowsAffected;
|
||||
rowsAffected = [NSNumber numberWithInt:diffRowsAffected];
|
||||
nowInsertId = sqlite3_last_insert_rowid(db);
|
||||
if (previousInsertId != nowInsertId) {
|
||||
hasInsertId = YES;
|
||||
insertId = [NSNumber numberWithLongLong:sqlite3_last_insert_rowid(db)];
|
||||
}
|
||||
keepGoing = NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
errMsg = "SQL statement error";
|
||||
keepGoing = NO;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize (statement);
|
||||
|
||||
if (errMsg != NULL) {
|
||||
[self respond:callback withString:[NSString stringWithFormat:@"{ message: 'SQL statement error : %s' }", errMsg] withType:@"error"];
|
||||
} else {
|
||||
[resultSet setObject:resultRows forKey:@"rows"];
|
||||
[resultSet setObject:rowsAffected forKey:@"rowsAffected"];
|
||||
if (hasInsertId) {
|
||||
[resultSet setObject:insertId forKey:@"insertId"];
|
||||
}
|
||||
[self respond:callback withString:[resultSet JSONRepresentation] withType:@"success"];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) close: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
|
||||
{
|
||||
NSString *callback = [options objectForKey:@"callback"];
|
||||
NSString *dbPath = [self getDBPath:[options objectForKey:@"path"]];
|
||||
if (dbPath == NULL) {
|
||||
[self respond:callback withString:@"{ message: 'You must specify database path' }" withType:@"error"];
|
||||
return;
|
||||
}
|
||||
|
||||
NSValue *val = [openDBs objectForKey:dbPath];
|
||||
sqlite3 *db = [val pointerValue];
|
||||
if (db == NULL) {
|
||||
[self respond:callback withString: @"{ message: 'Specified db was not open' }" withType:@"error"];
|
||||
}
|
||||
sqlite3_close (db);
|
||||
[self respond:callback withString: @"{ message: 'db closed' }" withType:@"success"];
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
int i;
|
||||
NSArray *keys = [openDBs allKeys];
|
||||
NSValue *pointer;
|
||||
NSString *key;
|
||||
sqlite3 *db;
|
||||
|
||||
/* close db the user forgot */
|
||||
for (i=0; i<[keys count]; i++) {
|
||||
key = [keys objectAtIndex:i];
|
||||
pointer = [openDBs objectForKey:key];
|
||||
db = [pointer pointerValue];
|
||||
sqlite3_close (db);
|
||||
}
|
||||
|
||||
[openDBs release];
|
||||
[appDocsPath release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue
Block a user