增加晶全app静态页面
This commit is contained in:
167
node_modules/cordova-sqlite-storage/src/ios/CustomPSPDFThreadSafeMutableDictionary.m
generated
vendored
Normal file
167
node_modules/cordova-sqlite-storage/src/ios/CustomPSPDFThreadSafeMutableDictionary.m
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
//
|
||||
// CustomPSPDFThreadSafeMutableDictionary.m
|
||||
//
|
||||
// renamed from PSPDFThreadSafeMutableDictionary.m
|
||||
//
|
||||
// Copyright (c) 2019-present Christopher J. Brody (aka Chris Brody)
|
||||
//
|
||||
// Copyright (c) 2013 Peter Steinberger, PSPDFKit GmbH. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Dictionary-Subclasss whose primitive operations are thread safe.
|
||||
@interface CustomPSPDFThreadSafeMutableDictionary : NSMutableDictionary
|
||||
@end
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
//
|
||||
// CustomPSPDFThreadSafeMutableDictionary.m
|
||||
//
|
||||
// renamed from PSPDFThreadSafeMutableDictionary.m
|
||||
//
|
||||
// PSPDFKit
|
||||
//
|
||||
// Copyright (c) 2013 PSPDFKit GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
// #import "PSPDFThreadSafeMutableDictionary.h"
|
||||
|
||||
#import <libkern/OSAtomic.h>
|
||||
|
||||
#define LOCKED(...) OSSpinLockLock(&_lock); \
|
||||
__VA_ARGS__; \
|
||||
OSSpinLockUnlock(&_lock);
|
||||
|
||||
@implementation CustomPSPDFThreadSafeMutableDictionary {
|
||||
OSSpinLock _lock;
|
||||
NSMutableDictionary *_dictionary; // Class Cluster!
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (id)init {
|
||||
return [self initWithCapacity:0];
|
||||
}
|
||||
|
||||
- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys {
|
||||
if ((self = [self initWithCapacity:objects.count])) {
|
||||
[objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
_dictionary[keys[idx]] = obj;
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCapacity:(NSUInteger)capacity {
|
||||
if ((self = [super init])) {
|
||||
_dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
|
||||
_lock = OS_SPINLOCK_INIT;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - NSMutableDictionary
|
||||
|
||||
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
|
||||
LOCKED(_dictionary[aKey] = anObject)
|
||||
}
|
||||
|
||||
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary {
|
||||
LOCKED([_dictionary addEntriesFromDictionary:otherDictionary]);
|
||||
}
|
||||
|
||||
- (void)setDictionary:(NSDictionary *)otherDictionary {
|
||||
LOCKED([_dictionary setDictionary:otherDictionary]);
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(id)aKey {
|
||||
LOCKED([_dictionary removeObjectForKey:aKey])
|
||||
}
|
||||
|
||||
- (void)removeAllObjects {
|
||||
LOCKED([_dictionary removeAllObjects]);
|
||||
}
|
||||
|
||||
- (NSUInteger)count {
|
||||
LOCKED(NSUInteger count = _dictionary.count)
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSArray *)allKeys {
|
||||
LOCKED(NSArray *allKeys = _dictionary.allKeys)
|
||||
return allKeys;
|
||||
}
|
||||
|
||||
- (NSArray *)allValues {
|
||||
LOCKED(NSArray *allValues = _dictionary.allValues)
|
||||
return allValues;
|
||||
}
|
||||
|
||||
- (id)objectForKey:(id)aKey {
|
||||
LOCKED(id obj = _dictionary[aKey])
|
||||
return obj;
|
||||
}
|
||||
|
||||
- (NSEnumerator *)keyEnumerator {
|
||||
LOCKED(NSEnumerator *keyEnumerator = [_dictionary keyEnumerator])
|
||||
return keyEnumerator;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return [self mutableCopyWithZone:zone];
|
||||
}
|
||||
|
||||
- (id)mutableCopyWithZone:(NSZone *)zone {
|
||||
LOCKED(id copiedDictionary = [[self.class allocWithZone:zone] initWithDictionary:_dictionary])
|
||||
return copiedDictionary;
|
||||
}
|
||||
|
||||
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
|
||||
objects:(id __unsafe_unretained [])stackbuf
|
||||
count:(NSUInteger)len {
|
||||
LOCKED(NSUInteger count = [[_dictionary copy] countByEnumeratingWithState:state objects:stackbuf count:len]);
|
||||
return count;
|
||||
}
|
||||
|
||||
- (void)performLockedWithDictionary:(void (^)(NSDictionary *dictionary))block {
|
||||
if (block) LOCKED(block(_dictionary));
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (object == self) return YES;
|
||||
|
||||
if ([object isKindOfClass:CustomPSPDFThreadSafeMutableDictionary.class]) {
|
||||
CustomPSPDFThreadSafeMutableDictionary *other = object;
|
||||
__block BOOL isEqual = NO;
|
||||
[other performLockedWithDictionary:^(NSDictionary *dictionary) {
|
||||
[self performLockedWithDictionary:^(NSDictionary *otherDictionary) {
|
||||
isEqual = [dictionary isEqual:otherDictionary];
|
||||
}];
|
||||
}];
|
||||
return isEqual;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
50
node_modules/cordova-sqlite-storage/src/ios/SQLitePlugin.h
generated
vendored
Normal file
50
node_modules/cordova-sqlite-storage/src/ios/SQLitePlugin.h
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
|
||||
* Copyright (C) 2011 Davide Bertola
|
||||
*
|
||||
* This library is available under the terms of the MIT License (2008).
|
||||
* See http://opensource.org/licenses/alphabetical for full text.
|
||||
*/
|
||||
|
||||
#import <Cordova/CDVPlugin.h>
|
||||
|
||||
// Used to remove dependency on sqlite3.h in this header:
|
||||
struct sqlite3;
|
||||
|
||||
enum WebSQLError {
|
||||
UNKNOWN_ERR = 0,
|
||||
DATABASE_ERR = 1,
|
||||
VERSION_ERR = 2,
|
||||
TOO_LARGE_ERR = 3,
|
||||
QUOTA_ERR = 4,
|
||||
SYNTAX_ERR_ = 5,
|
||||
CONSTRAINT_ERR = 6,
|
||||
TIMEOUT_ERR = 7
|
||||
};
|
||||
typedef int WebSQLError;
|
||||
|
||||
@interface SQLitePlugin : CDVPlugin {
|
||||
NSMutableDictionary *openDBs;
|
||||
}
|
||||
|
||||
@property (nonatomic, copy) NSMutableDictionary *openDBs;
|
||||
@property (nonatomic, copy) NSMutableDictionary *appDBPaths;
|
||||
|
||||
// Self-test
|
||||
-(void) echoStringValue: (CDVInvokedUrlCommand*)command;
|
||||
|
||||
// Open / Close / Delete
|
||||
-(void) open: (CDVInvokedUrlCommand*)command;
|
||||
-(void) close: (CDVInvokedUrlCommand*)command;
|
||||
-(void) delete: (CDVInvokedUrlCommand*)command;
|
||||
|
||||
-(void) openNow: (CDVInvokedUrlCommand*)command;
|
||||
-(void) closeNow: (CDVInvokedUrlCommand*)command;
|
||||
-(void) deleteNow: (CDVInvokedUrlCommand*)command;
|
||||
|
||||
// Batch processing interface
|
||||
-(void) backgroundExecuteSqlBatch: (CDVInvokedUrlCommand*)command;
|
||||
|
||||
-(void) executeSqlBatchNow: (CDVInvokedUrlCommand*)command;
|
||||
|
||||
@end /* vim: set expandtab : */
|
567
node_modules/cordova-sqlite-storage/src/ios/SQLitePlugin.m
generated
vendored
Normal file
567
node_modules/cordova-sqlite-storage/src/ios/SQLitePlugin.m
generated
vendored
Normal file
@ -0,0 +1,567 @@
|
||||
/*
|
||||
* Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
|
||||
* Copyright (C) 2011 Davide Bertola
|
||||
*
|
||||
* This library is available under the terms of the MIT License (2008).
|
||||
* See http://opensource.org/licenses/alphabetical for full text.
|
||||
*/
|
||||
|
||||
#import "SQLitePlugin.h"
|
||||
|
||||
#import "sqlite3.h"
|
||||
|
||||
// Defines Macro to only log lines when in DEBUG mode
|
||||
#ifdef DEBUG
|
||||
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
||||
#else
|
||||
# define DLog(...)
|
||||
#endif
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
# error "Missing objc_arc feature"
|
||||
#endif
|
||||
|
||||
// CustomPSPDFThreadSafeMutableDictionary interface copied from
|
||||
// CustomPSPDFThreadSafeMutableDictionary.m:
|
||||
//
|
||||
// Dictionary-Subclasss whose primitive operations are thread safe.
|
||||
@interface CustomPSPDFThreadSafeMutableDictionary : NSMutableDictionary
|
||||
@end
|
||||
|
||||
@implementation SQLitePlugin
|
||||
|
||||
@synthesize openDBs;
|
||||
@synthesize appDBPaths;
|
||||
|
||||
-(void)pluginInitialize
|
||||
{
|
||||
DLog(@"Initializing SQLitePlugin");
|
||||
|
||||
{
|
||||
openDBs = [CustomPSPDFThreadSafeMutableDictionary dictionaryWithCapacity:0];
|
||||
appDBPaths = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
|
||||
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
|
||||
DLog(@"Detected docs path: %@", docs);
|
||||
[appDBPaths setObject: docs forKey:@"docs"];
|
||||
|
||||
NSString *libs = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
|
||||
DLog(@"Detected Library path: %@", libs);
|
||||
[appDBPaths setObject: libs forKey:@"libs"];
|
||||
|
||||
NSString *nosync = [libs stringByAppendingPathComponent:@"LocalDatabase"];
|
||||
NSError *err;
|
||||
|
||||
// GENERAL NOTE: no `nosync` directory path entry to be added
|
||||
// to appDBPaths map in case of any isses creating the
|
||||
// required directory or setting the resource value for
|
||||
// NSURLIsExcludedFromBackupKey
|
||||
//
|
||||
// This is to avoid potential for issue raised here:
|
||||
// https://github.com/xpbrew/cordova-sqlite-storage/issues/907
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath: nosync])
|
||||
{
|
||||
DLog(@"no cloud sync directory already exists at path: %@", nosync);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([[NSFileManager defaultManager] createDirectoryAtPath: nosync withIntermediateDirectories:NO attributes: nil error:&err])
|
||||
{
|
||||
DLog(@"no cloud sync directory created with path: %@", nosync);
|
||||
}
|
||||
else
|
||||
{
|
||||
// STOP HERE & LOG WITH INTERNAL PLUGIN ERROR:
|
||||
NSLog(@"INTERNAL PLUGIN ERROR: could not create no cloud sync directory at path: %@", nosync);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
// Set the resource value for NSURLIsExcludedFromBackupKey
|
||||
NSURL *nosyncURL = [ NSURL fileURLWithPath: nosync];
|
||||
if (![nosyncURL setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &err])
|
||||
{
|
||||
// STOP HERE & LOG WITH INTERNAL PLUGIN ERROR:
|
||||
NSLog(@"INTERNAL PLUGIN ERROR: error setting nobackup flag in LocalDatabase directory: %@", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// now ready to add `nosync` entry to appDBPaths:
|
||||
DLog(@"no cloud sync at path: %@", nosync);
|
||||
[appDBPaths setObject: nosync forKey:@"nosync"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(id) getDBPath:(NSString *)dbFile at:(NSString *)atkey {
|
||||
if (dbFile == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSString *dbdir = [appDBPaths objectForKey:atkey];
|
||||
if (dbdir == NULL) {
|
||||
// INTERNAL PLUGIN ERROR:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSString *dbPath = [dbdir stringByAppendingPathComponent: dbFile];
|
||||
return dbPath;
|
||||
}
|
||||
|
||||
-(void)echoStringValue: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
CDVPluginResult * pluginResult = nil;
|
||||
NSMutableDictionary * options = [command.arguments objectAtIndex:0];
|
||||
|
||||
NSString * string_value = [options objectForKey:@"value"];
|
||||
|
||||
DLog(@"echo string value: %@", string_value);
|
||||
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:string_value];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
}
|
||||
|
||||
-(void)open: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
[self.commandDelegate runInBackground:^{
|
||||
[self openNow: command];
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)openNow: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
CDVPluginResult* pluginResult = nil;
|
||||
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
|
||||
|
||||
NSString *dbfilename = [options objectForKey:@"name"];
|
||||
|
||||
NSString *dblocation = [options objectForKey:@"dblocation"];
|
||||
if (dblocation == NULL) dblocation = @"docs";
|
||||
// DLog(@"using db location: %@", dblocation);
|
||||
|
||||
NSString *dbname = [self getDBPath:dbfilename at:dblocation];
|
||||
|
||||
if (!sqlite3_threadsafe()) {
|
||||
// INTERNAL PLUGIN ERROR:
|
||||
NSLog(@"INTERNAL PLUGIN ERROR: sqlite3_threadsafe() returns false value");
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"INTERNAL PLUGIN ERROR: sqlite3_threadsafe() returns false value"];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
return;
|
||||
} else if (dbname == NULL) {
|
||||
// INTERNAL PLUGIN ERROR - NOT EXPECTED:
|
||||
NSLog(@"INTERNAL PLUGIN ERROR (NOT EXPECTED): open with database name missing");
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"INTERNAL PLUGIN ERROR: open with database name missing"];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
return;
|
||||
} else {
|
||||
NSValue *dbPointer = [openDBs objectForKey:dbfilename];
|
||||
|
||||
if (dbPointer != NULL) {
|
||||
// NO LONGER EXPECTED due to BUG 666 workaround solution:
|
||||
// DLog(@"Reusing existing database connection for db name %@", dbfilename);
|
||||
NSLog(@"INTERNAL PLUGIN ERROR: database already open for db name: %@ (db file name: %@)", dbname, dbfilename);
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"INTERNAL PLUGIN ERROR: database already open"];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
@synchronized(self) {
|
||||
const char *name = [dbname UTF8String];
|
||||
sqlite3 *db;
|
||||
|
||||
DLog(@"open full db path: %@", dbname);
|
||||
|
||||
if (sqlite3_open(name, &db) != SQLITE_OK) {
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unable to open DB"];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
return;
|
||||
} else {
|
||||
sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, NULL);
|
||||
|
||||
// for SQLCipher version:
|
||||
// NSString *dbkey = [options objectForKey:@"key"];
|
||||
// const char *key = NULL;
|
||||
// if (dbkey != NULL) key = [dbkey UTF8String];
|
||||
// if (key != NULL) sqlite3_key(db, key, strlen(key));
|
||||
|
||||
// Attempt to read the SQLite master table [to support SQLCipher version]:
|
||||
if(sqlite3_exec(db, (const char*)"SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
|
||||
dbPointer = [NSValue valueWithPointer:db];
|
||||
[openDBs setObject: dbPointer forKey: dbfilename];
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Database opened"];
|
||||
} else {
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unable to open DB with key"];
|
||||
// XXX TODO: close the db handle & [perhaps] remove from openDBs!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
|
||||
// DLog(@"open cb finished ok");
|
||||
}
|
||||
|
||||
-(void) close: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
[self.commandDelegate runInBackground:^{
|
||||
[self closeNow: command];
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)closeNow: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
CDVPluginResult* pluginResult = nil;
|
||||
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
|
||||
|
||||
NSString *dbFileName = [options objectForKey:@"path"];
|
||||
|
||||
if (dbFileName == NULL) {
|
||||
// Should not happen:
|
||||
DLog(@"No db name specified for close");
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: You must specify database path"];
|
||||
} else {
|
||||
NSValue *val = [openDBs objectForKey:dbFileName];
|
||||
sqlite3 *db = [val pointerValue];
|
||||
|
||||
if (db == NULL) {
|
||||
// Should not happen:
|
||||
DLog(@"close: db name was not open: %@", dbFileName);
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: Specified db was not open"];
|
||||
}
|
||||
else {
|
||||
DLog(@"close db name: %@", dbFileName);
|
||||
sqlite3_close (db);
|
||||
[openDBs removeObjectForKey:dbFileName];
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"DB closed"];
|
||||
}
|
||||
}
|
||||
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
}
|
||||
|
||||
-(void) delete: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
[self.commandDelegate runInBackground:^{
|
||||
[self deleteNow: command];
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)deleteNow: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
CDVPluginResult* pluginResult = nil;
|
||||
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
|
||||
|
||||
NSString *dbFileName = [options objectForKey:@"path"];
|
||||
|
||||
NSString *dblocation = [options objectForKey:@"dblocation"];
|
||||
if (dblocation == NULL) dblocation = @"docs";
|
||||
|
||||
if (dbFileName==NULL) {
|
||||
// Should not happen:
|
||||
DLog(@"No db name specified for delete");
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: You must specify database path"];
|
||||
} else {
|
||||
NSString *dbPath = [self getDBPath:dbFileName at:dblocation];
|
||||
|
||||
if (dbPath == NULL) {
|
||||
// INTERNAL PLUGIN ERROR - NOT EXPECTED:
|
||||
NSLog(@"INTERNAL PLUGIN ERROR (NOT EXPECTED): delete with no valid database path found");
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"INTERNAL PLUGIN ERROR: delete with no valid database path found"];
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([[NSFileManager defaultManager]fileExistsAtPath:dbPath]) {
|
||||
DLog(@"delete full db path: %@", dbPath);
|
||||
[[NSFileManager defaultManager]removeItemAtPath:dbPath error:nil];
|
||||
[openDBs removeObjectForKey:dbFileName];
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"DB deleted"];
|
||||
} else {
|
||||
DLog(@"delete: db was not found: %@", dbPath);
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"The database does not exist on that path"];
|
||||
}
|
||||
}
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
|
||||
-(void) backgroundExecuteSqlBatch: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
[self.commandDelegate runInBackground:^{
|
||||
[self executeSqlBatchNow: command];
|
||||
}];
|
||||
}
|
||||
|
||||
-(void) executeSqlBatchNow: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
|
||||
NSMutableArray *results = [NSMutableArray arrayWithCapacity:0];
|
||||
NSMutableDictionary *dbargs = [options objectForKey:@"dbargs"];
|
||||
NSMutableArray *executes = [options objectForKey:@"executes"];
|
||||
|
||||
CDVPluginResult* pluginResult;
|
||||
|
||||
{
|
||||
for (NSMutableDictionary *dict in executes) {
|
||||
CDVPluginResult *result = [self executeSqlWithDict:dict andArgs:dbargs];
|
||||
if ([result.status intValue] == CDVCommandStatus_ERROR) {
|
||||
/* add error with result.message: */
|
||||
NSMutableDictionary *r = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
[r setObject:@"error" forKey:@"type"];
|
||||
[r setObject:result.message forKey:@"error"];
|
||||
[r setObject:result.message forKey:@"result"];
|
||||
[results addObject: r];
|
||||
} else {
|
||||
/* add result with result.message: */
|
||||
NSMutableDictionary *r = [NSMutableDictionary dictionaryWithCapacity:0];
|
||||
[r setObject:@"success" forKey:@"type"];
|
||||
[r setObject:result.message forKey:@"result"];
|
||||
[results addObject: r];
|
||||
}
|
||||
}
|
||||
|
||||
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:results];
|
||||
}
|
||||
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
-(void) executeSql: (CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
|
||||
NSMutableDictionary *dbargs = [options objectForKey:@"dbargs"];
|
||||
NSMutableDictionary *ex = [options objectForKey:@"ex"];
|
||||
|
||||
CDVPluginResult * pluginResult = [self executeSqlWithDict: ex andArgs: dbargs];
|
||||
|
||||
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
-(CDVPluginResult*) executeSqlWithDict: (NSMutableDictionary*)options andArgs: (NSMutableDictionary*)dbargs
|
||||
{
|
||||
NSString *dbFileName = [dbargs objectForKey:@"dbname"];
|
||||
if (dbFileName == NULL) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: You must specify database path"];
|
||||
}
|
||||
|
||||
NSMutableArray *params = [options objectForKey:@"params"]; // optional
|
||||
|
||||
NSValue *dbPointer = [openDBs objectForKey:dbFileName];
|
||||
if (dbPointer == NULL) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: No such database, you must open it first"];
|
||||
}
|
||||
sqlite3 *db = [dbPointer pointerValue];
|
||||
|
||||
NSString *sql = [options objectForKey:@"sql"];
|
||||
if (sql == NULL) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"INTERNAL PLUGIN ERROR: You must specify a sql query to execute"];
|
||||
}
|
||||
|
||||
const char *sql_stmt = [sql UTF8String];
|
||||
NSDictionary *error = nil;
|
||||
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;
|
||||
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) {
|
||||
error = [SQLitePlugin captureSQLiteErrorFromDb:db];
|
||||
keepGoing = NO;
|
||||
} else if (params != NULL) {
|
||||
for (int b = 0; b < params.count; b++) {
|
||||
result = [self bindStatement:statement withArg:[params objectAtIndex:b] atIndex:(b+1)];
|
||||
if (result != SQLITE_OK) {
|
||||
error = [SQLitePlugin captureSQLiteErrorFromDb:db];
|
||||
keepGoing = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
columnValue = nil;
|
||||
columnName = [NSString stringWithFormat:@"%s", sqlite3_column_name(statement, i)];
|
||||
|
||||
column_type = sqlite3_column_type(statement, i);
|
||||
switch (column_type) {
|
||||
case SQLITE_INTEGER:
|
||||
columnValue = [NSNumber numberWithLongLong: sqlite3_column_int64(statement, i)];
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
columnValue = [NSNumber numberWithDouble: sqlite3_column_double(statement, i)];
|
||||
break;
|
||||
case SQLITE_BLOB:
|
||||
case SQLITE_TEXT:
|
||||
columnValue = [[NSString alloc] initWithBytes:(char *)sqlite3_column_text(statement, i)
|
||||
length:sqlite3_column_bytes(statement, i)
|
||||
encoding:NSUTF8StringEncoding];
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
// just in case (should not happen):
|
||||
default:
|
||||
columnValue = [NSNull null];
|
||||
break;
|
||||
}
|
||||
|
||||
if (columnValue) {
|
||||
[entry setObject:columnValue forKey:columnName];
|
||||
}
|
||||
|
||||
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 (diffRowsAffected > 0 && nowInsertId != 0) {
|
||||
hasInsertId = YES;
|
||||
insertId = [NSNumber numberWithLongLong:sqlite3_last_insert_rowid(db)];
|
||||
}
|
||||
keepGoing = NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = [SQLitePlugin captureSQLiteErrorFromDb:db];
|
||||
keepGoing = NO;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize (statement);
|
||||
|
||||
if (error) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:error];
|
||||
}
|
||||
|
||||
[resultSet setObject:resultRows forKey:@"rows"];
|
||||
[resultSet setObject:rowsAffected forKey:@"rowsAffected"];
|
||||
if (hasInsertId) {
|
||||
[resultSet setObject:insertId forKey:@"insertId"];
|
||||
}
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:resultSet];
|
||||
}
|
||||
|
||||
-(int)bindStatement:(sqlite3_stmt *)statement withArg:(NSObject *)arg atIndex:(int)argIndex
|
||||
{
|
||||
int bindResult = SQLITE_ERROR;
|
||||
|
||||
if ([arg isEqual:[NSNull null]]) {
|
||||
// bind null:
|
||||
bindResult = sqlite3_bind_null(statement, argIndex);
|
||||
} else if ([arg isKindOfClass:[NSNumber class]]) {
|
||||
// bind NSNumber (int64 or double):
|
||||
NSNumber *numberArg = (NSNumber *)arg;
|
||||
const char *numberType = [numberArg objCType];
|
||||
|
||||
// Bind each number as INTEGER (long long int) or REAL (double):
|
||||
if (strcmp(numberType, @encode(int)) == 0 ||
|
||||
strcmp(numberType, @encode(long long int)) == 0) {
|
||||
bindResult = sqlite3_bind_int64(statement, argIndex, [numberArg longLongValue]);
|
||||
} else {
|
||||
bindResult = sqlite3_bind_double(statement, argIndex, [numberArg doubleValue]);
|
||||
}
|
||||
} else {
|
||||
// bind NSString (text):
|
||||
NSString *stringArg;
|
||||
|
||||
if ([arg isKindOfClass:[NSString class]]) {
|
||||
stringArg = (NSString *)arg;
|
||||
} else {
|
||||
stringArg = [arg description]; // convert to text
|
||||
}
|
||||
|
||||
// always bind text string as UTF-8 (sqlite does internal conversion if necessary):
|
||||
NSData *data = [stringArg dataUsingEncoding:NSUTF8StringEncoding];
|
||||
bindResult = sqlite3_bind_text(statement, argIndex, data.bytes, (int)data.length, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
return bindResult;
|
||||
}
|
||||
|
||||
-(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);
|
||||
}
|
||||
}
|
||||
|
||||
+(NSDictionary *)captureSQLiteErrorFromDb:(struct sqlite3 *)db
|
||||
{
|
||||
int code = sqlite3_errcode(db);
|
||||
int webSQLCode = [SQLitePlugin mapSQLiteErrorCode:code];
|
||||
#if INCLUDE_SQLITE_ERROR_INFO
|
||||
int extendedCode = sqlite3_extended_errcode(db);
|
||||
#endif
|
||||
const char *message = sqlite3_errmsg(db);
|
||||
|
||||
NSMutableDictionary *error = [NSMutableDictionary dictionaryWithCapacity:4];
|
||||
|
||||
[error setObject:[NSNumber numberWithInt:webSQLCode] forKey:@"code"];
|
||||
[error setObject:[NSString stringWithUTF8String:message] forKey:@"message"];
|
||||
|
||||
#if INCLUDE_SQLITE_ERROR_INFO
|
||||
[error setObject:[NSNumber numberWithInt:code] forKey:@"sqliteCode"];
|
||||
[error setObject:[NSNumber numberWithInt:extendedCode] forKey:@"sqliteExtendedCode"];
|
||||
[error setObject:[NSString stringWithUTF8String:message] forKey:@"sqliteMessage"];
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
+(int)mapSQLiteErrorCode:(int)code
|
||||
{
|
||||
// map the sqlite error code to
|
||||
// the websql error code
|
||||
switch(code) {
|
||||
case SQLITE_ERROR:
|
||||
return SYNTAX_ERR_;
|
||||
case SQLITE_FULL:
|
||||
return QUOTA_ERR;
|
||||
case SQLITE_CONSTRAINT:
|
||||
return CONSTRAINT_ERR;
|
||||
default:
|
||||
return UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
@end /* vim: set expandtab : */
|
Reference in New Issue
Block a user