diff --git a/AIBSQLite.h b/AIBSQLite.h index 50be252..9a3eb0c 100644 --- a/AIBSQLite.h +++ b/AIBSQLite.h @@ -6,7 +6,7 @@ // -#import +#import "./node_modules/react-native/React/Base/RCTBridgeModule.h" @interface AIBSQLite : NSObject diff --git a/AIBSQLite.m b/AIBSQLite.m index a499f76..3aff3f9 100644 --- a/AIBSQLite.m +++ b/AIBSQLite.m @@ -6,11 +6,11 @@ // #import "AIBSQLite.h" -#import "RCTLog.h" -#import "RCTUtils.h" +#import "./node_modules/react-native/React/Base/RCTLog.h" +#import "./node_modules/react-native/React/Base/RCTUtils.h" #import -#import "RCTBridge.h" -#import "RCTEventDispatcher.h" +#import "./node_modules/react-native/React/Base/RCTBridge.h" +#import "./node_modules/react-native/React/Base/RCTEventDispatcher.h" #import @@ -159,50 +159,101 @@ - (id) init }); } +RCT_EXPORT_METHOD(validateStatement: (NSString *)databaseId sql: (NSString *)sql andParams: (NSArray *)params callback: (RCTResponseSenderBlock)callback) +{ + if (!callback) { + RCTLogError(@"Called prepareStatement without a callback."); + } + + dispatch_async(AIBSQLiteQueue(), ^{ + Database *database = [openDatabases valueForKey:databaseId]; + if (database == nil) { + callback(@[@"No open database found", [NSNull null]]); + return; + } + + sqlite3 *db = [database db]; + sqlite3_stmt *stmt; + + int rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL); + if (rc != SQLITE_OK) { + callback(@[[NSString stringWithUTF8String:sqlite3_errmsg(db)]]); + } + + for (int i=0; i < [params count]; i++){ + NSObject *param = [params objectAtIndex: i]; + if ([param isKindOfClass: [NSString class]]) { + NSString *str = (NSString*) param; + int strLength = (int) [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; + sqlite3_bind_text(stmt, i+1, [str UTF8String], strLength, SQLITE_TRANSIENT); + } else if ([param isKindOfClass: [NSNumber class]]) { + sqlite3_bind_double(stmt, i+1, [(NSNumber *)param doubleValue]); + } else if ([param isKindOfClass: [NSNull class]]) { + sqlite3_bind_null(stmt, i+1); + } else { + sqlite3_finalize(stmt); + callback(@[@"Parameters must be either numbers or strings" ]); + return; + } + } + + // Step once to see if we catch any errors + rc = sqlite3_step(stmt); + if (rc != SQLITE_OK) { + callback(@[[NSString stringWithUTF8String:sqlite3_errmsg(db)]]); + return; + } + + // We are done validating so close out the statement and return success + sqlite3_finalize(stmt); + callback(@[[NSNull null]]); + }); +} + RCT_EXPORT_METHOD(prepareStatement: (NSString *)databaseId sql: (NSString *)sql andParams: (NSArray *)params callback: (RCTResponseSenderBlock)callback) { - if (!callback) { - RCTLogError(@"Called prepareStatement without a callback."); + if (!callback) { + RCTLogError(@"Called prepareStatement without a callback."); + } + + dispatch_async(AIBSQLiteQueue(), ^{ + Database *database = [openDatabases valueForKey:databaseId]; + if (database == nil) { + callback(@[@"No open database found", [NSNull null]]); + return; } + sqlite3 *db = [database db]; + sqlite3_stmt *stmt; - dispatch_async(AIBSQLiteQueue(), ^{ - Database *database = [openDatabases valueForKey:databaseId]; - if (database == nil) { - callback(@[@"No open database found", [NSNull null]]); - return; - } - sqlite3 *db = [database db]; - sqlite3_stmt *stmt; - - int rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL); - if (rc != SQLITE_OK) { - callback(@[[NSString stringWithUTF8String:sqlite3_errmsg(db)]]); - return; - } - - for (int i=0; i < [params count]; i++){ - NSObject *param = [params objectAtIndex: i]; - if ([param isKindOfClass: [NSString class]]) { - NSString *str = (NSString*) param; - int strLength = (int) [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; - sqlite3_bind_text(stmt, i+1, [str UTF8String], strLength, SQLITE_TRANSIENT); - } else if ([param isKindOfClass: [NSNumber class]]) { - sqlite3_bind_double(stmt, i+1, [(NSNumber *)param doubleValue]); - } else if ([param isKindOfClass: [NSNull class]]) { - sqlite3_bind_null(stmt, i+1); - } else { - sqlite3_finalize(stmt); - callback(@[@"Parameters must be either numbers or strings" ]); - return; - } - } - - NSString *statementId = [[NSNumber numberWithInt: nextId++] stringValue]; - Statement *statement = [[Statement alloc] initWithSqliteStmt: stmt]; - [[database statements] setValue: statement forKey:statementId]; - - callback(@[[NSNull null], statementId]); - }); + int rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL); + if (rc != SQLITE_OK) { + callback(@[[NSString stringWithUTF8String:sqlite3_errmsg(db)]]); + return; + } + + for (int i=0; i < [params count]; i++){ + NSObject *param = [params objectAtIndex: i]; + if ([param isKindOfClass: [NSString class]]) { + NSString *str = (NSString*) param; + int strLength = (int) [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; + sqlite3_bind_text(stmt, i+1, [str UTF8String], strLength, SQLITE_TRANSIENT); + } else if ([param isKindOfClass: [NSNumber class]]) { + sqlite3_bind_double(stmt, i+1, [(NSNumber *)param doubleValue]); + } else if ([param isKindOfClass: [NSNull class]]) { + sqlite3_bind_null(stmt, i+1); + } else { + sqlite3_finalize(stmt); + callback(@[@"Parameters must be either numbers or strings" ]); + return; + } + } + + NSString *statementId = [[NSNumber numberWithInt: nextId++] stringValue]; + Statement *statement = [[Statement alloc] initWithSqliteStmt: stmt]; + [[database statements] setValue: statement forKey:statementId]; + + callback(@[[NSNull null], statementId]); + }); } RCT_EXPORT_METHOD(stepStatement:(NSString *)databaseId statementId: (NSString *) statementId callback:(RCTResponseSenderBlock)callback) diff --git a/sqlite3.ios.js b/sqlite3.ios.js index ba0cbf6..668febe 100644 --- a/sqlite3.ios.js +++ b/sqlite3.ios.js @@ -33,6 +33,22 @@ Database.prototype = { return this._databaseName; }, + validateSQL ( + sql: string, + params: Array, + completeCallback: ((error: ?SQLite3Error) => void) + ): void { + this._addAction(completeCallback, (callback) => { + NativeModules.AIBSQLite.validateStatement(this._databaseId, sql, params, (error) => { + if (error) { + completeCallback(new SQLite3Error(error)); + return; + } + completeCallback(null); + }); + }); + }, + executeSQL ( sql: string, params: Array,