mirror of
https://github.com/moparisthebest/PhoneGap-SQLitePlugin-Android
synced 2024-11-21 08:25:01 -05:00
Cleanup documentation of nesting, remove old version, etc.
This commit is contained in:
parent
1f628821b1
commit
cf7c28b75f
@ -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
215
README.md
@ -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
|
||||
|
@ -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
|
@ -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);
|
@ -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
|
Loading…
Reference in New Issue
Block a user