Cleanup documentation of nesting, remove old version, etc.

This commit is contained in:
Chris Brody 2012-04-21 19:30:46 +02:00
parent 1f628821b1
commit cf7c28b75f
5 changed files with 62 additions and 650 deletions

View File

@ -78,7 +78,7 @@
//this.optimization_no_nested_callbacks: default is true.
//if set to true large batches of queries within a transaction will be much faster but
//you will lose the ability to do multi level nesting of executeSQL callbacks
this.optimization_no_nested_callbacks = true;
this.optimization_no_nested_callbacks = false;
console.log("root.SQLitePluginTransaction - this.trans_id:"+this.trans_id);
transaction_queue[this.trans_id] = [];
transaction_callback_queue[this.trans_id] = new Object();

215
README.md
View File

@ -24,7 +24,10 @@ 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 in Javascript:
Sample
------
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.
// Wait for Cordova to load
//
@ -39,62 +42,80 @@ Sample in Javascript:
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) {
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");
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");
});
});
}, function(e) {
console.log("ERROR: " + e.message);
});
});
}
## Sample with transaction-level nesting
**Android version only:** In this case, the same transaction in the first executeSql() callback is being reused to run executeSql() again. This version will only work on the Android version and only if you make the following patch:
diff --git a/Android/assets/www/SQLitePlugin.js b/Android/assets/www/SQLitePlugin.js
index 6349baf..8a3c50f 100755
--- a/Android/assets/www/SQLitePlugin.js
+++ b/Android/assets/www/SQLitePlugin.js
@@ -78,7 +78,7 @@
//this.optimization_no_nested_callbacks: default is true.
//if set to true large batches of queries within a transaction will be much faster but
//you will lose the ability to do multi level nesting of executeSQL callbacks
- this.optimization_no_nested_callbacks = true;
+ this.optimization_no_nested_callbacks = false;
console.log("root.SQLitePluginTransaction - this.trans_id:"+this.trans_id);
transaction_queue[this.trans_id] = [];
transaction_callback_queue[this.trans_id] = new Object();
This case is (currently) not supported by the iOS version
// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova 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)');
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("res.rows.length: " + res.rows.length + " -- should be 1");
return console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
}, function(e) {
return console.log("ERROR: " + e.message);
console.log("ERROR: " + e.message);
});
});
}
This case will also works with Safari (WebKit), assuming you replace window.sqlitePlugin.openDatabase with window.openDatabase.
Installing
==========
**NOTE:** There are now the following trees:
- `iOS` for Cordova 1.5/1.6 iOS
- `iOS-legacy-phonegap` to support new API for PhoneGap 1.4- (cleanups by @marcucio) - **going away**
- `Android`: new version by @marcucio, with improvements for batch transaction processing, testing seems OK
PhoneGap 1.3.0
--------------
**GOING AWAY:**
For installing with PhoneGap 1.3.0:
in iOS-legacy-phonegap/SQLitePlugin.h file change for PhoneGap's JSONKit.h implementation.
#ifdef PHONEGAP_FRAMEWORK
#import <PhoneGap/PGPlugin.h>
#import <PhoneGap/JSONKit.h>
#import <PhoneGap/PhoneGapDelegate.h>
#import <PhoneGap/File.h>
#import<PhoneGap/FileTransfer.h>
#else
#import "PGPlugin.h"
#import "JSON.h"
#import "PhoneGapDelegate.h"
#import "File.h"
#endif
and in iOS-legacy-phonegap/SQLitePlugin.m JSONRepresentation must be changed to JSONString:
@@ -219,7 +219,7 @@
if (hasInsertId) {
[resultSet setObject:insertId forKey:@"insertId"];
}
- [self respond:callback withString:[resultSet JSONRepresentation] withType:@"success"];
+ [self respond:callback withString:[resultSet JSONString] withType:@"success"];
}
}
SQLite library
--------------
@ -128,38 +149,9 @@ Insert this in there:
Extra Usage
===========
Cordova iOS
-----------
## iOS
**NOTE:** These are from old samples, old API which is hereby deprecated **and going away**.
## Coffee Script
db = sqlitePlugin.openDatabase("my_sqlite_database.sqlite3")
db.executeSql('DROP TABLE IF EXISTS test_table')
db.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)')
db.transaction (tx) ->
tx.executeSql "INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], (res) ->
# success callback
console.log "insertId: #{res.insertId} -- probably 1"
console.log "rowsAffected: #{res.rowsAffected} -- should be 1"
# check the count (not a part of the transaction)
db.executeSql "select count(id) as cnt from test_table;", [], (res) ->
console.log "rows.length: #{res.rows.length} -- should be 1"
console.log "rows[0].cnt: #{res.rows[0].cnt} -- should be 1"
, (e) ->
# error callback
console.log "ERROR: #{e.message}"
## Plain Javascript
**NOTE:** This is from an old sample, old API which is hereby deprecated **and going away**.
var db = sqlitePlugin.openDatabase("my_sqlite_database.sqlite3");
@ -178,91 +170,6 @@ Cordova iOS
});
});
## Changes in tx.executeSql() success callback
var db = sqlitePlugin.openDatabase("my_sqlite_database.sqlite3");
db.executeSql('DROP TABLE IF EXISTS test_table');
db.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
db.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function(res) {
console.log("insertId: " + res.insertId + " -- probably 1");
console.log("rowsAffected: " + res.rowsAffected + " -- should be 1");
db.transaction(function(tx) {
return 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.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
});
});
iOS Legacy PhoneGap
-----------------------------
**GOING AWAY:**
## Coffee Script
db = new PGSQLitePlugin("my_sqlite_database.sqlite3")
db.executeSql('DROP TABLE IF EXISTS test_table')
db.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)')
db.transaction (tx) ->
tx.executeSql "INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], (res) ->
# success callback
console.log "insertId: #{res.insertId} -- probably 1"
console.log "rowsAffected: #{res.rowsAffected} -- should be 1"
# check the count (not a part of the transaction)
db.executeSql "select count(id) as cnt from test_table;", (res) ->
console.log "rows.length: #{res.rows.length} -- should be 1"
console.log "rows[0].cnt: #{res.rows[0].cnt} -- should be 1"
, (e) ->
# error callback
console.log "ERROR: #{e.message}"
## Plain Javascript
var db;
db = new PGSQLitePlugin("my_sqlite_database.sqlite3");
db.executeSql('DROP TABLE IF EXISTS test_table');
db.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
db.transaction(function(tx) {
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");
return db.executeSql("select count(id) as cnt from test_table;", [], function(res) {
console.log("rows.length: " + res.rows.length + " -- should be 1");
return console.log("rows[0].cnt: " + res.rows[0].cnt + " -- should be 1");
});
}, function(e) {
return console.log("ERROR: " + e.message);
});
});
## Changes in tx.executeSql() success callback
var db;
db = new PGSQLitePlugin("my_sqlite_database.sqlite3");
db.executeSql('DROP TABLE IF EXISTS test_table');
db.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
db.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function(res) {
console.log("insertId: " + res.insertId + " -- probably 1");
console.log("rowsAffected: " + res.rowsAffected + " -- should be 1");
db.transaction(function(tx) {
return 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");
});
});
});
Lawnchair Adapter Usage
=======================
@ -278,7 +185,7 @@ Included files
Include the following js files in your html:
- lawnchair.js (you provide)
- SQLitePlugin.js [pgsqlite_plugin.js in Legacy-PhoneGap-iPhone]
- SQLitePlugin.js
- Lawnchair-sqlitePlugin.js (must come after SQLitePlugin.js)
Sample

View File

@ -1,45 +0,0 @@
/*
* 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

View File

@ -1,185 +0,0 @@
(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);

View File

@ -1,265 +0,0 @@
/*
* 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