Last active
September 28, 2017 07:51
-
-
Save cmkilger/3e1a3a8878f75f4a96f2e72cd84a2f95 to your computer and use it in GitHub Desktop.
Objective-C SQLite wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface SQLiteDatabase: NSObject | |
- (nullable instancetype)initWithPath:(nonnull NSString *)path; | |
- (void)executeQuery:(nonnull NSString *)query; | |
- (void)executeQuery:(nonnull NSString *)query callback:(void(^ _Nullable)(NSDictionary<NSString *, id> * _Nonnull, BOOL * _Nonnull))callback; | |
@end | |
@interface SQLiteStatement: NSObject | |
- (nullable instancetype)initWithQueryTemplate:(nonnull NSString *)template inDatabase:(nonnull SQLiteDatabase *)database; | |
- (void)execute; | |
- (void)executeWithParameters:(nullable NSArray *)parameters; | |
- (void)executeWithCallback:(void(^ _Nullable)(NSDictionary<NSString *, id> * _Nonnull, BOOL * _Nonnull))callback; | |
- (void)executeWithParameters:(nullable NSArray *)parameters callback:(void(^ _Nullable)(NSDictionary<NSString *, id> * _Nonnull, BOOL * _Nonnull))callback; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "SQLite.h" | |
#import <sqlite3.h> | |
@interface SQLiteDatabase () | |
@property (assign) sqlite3 *database; | |
@end | |
@interface SQLiteStatement () | |
@property (assign) sqlite3_stmt *statement; | |
@end | |
@implementation SQLiteDatabase | |
- (instancetype)initWithPath:(NSString *)path { | |
self = [super init]; | |
if (self) { | |
if (sqlite3_open([path cStringUsingEncoding:NSUTF8StringEncoding], &_database) != SQLITE_OK) { | |
return nil; | |
} | |
} | |
return self; | |
} | |
- (void)dealloc { | |
if (_database) { | |
sqlite3_close(_database); | |
} | |
} | |
- (void)executeQuery:(NSString *)query { | |
[self executeQuery:query callback:nil]; | |
} | |
- (void)executeQuery:(NSString *)query callback:(void(^)(NSDictionary<NSString *, id> *, BOOL *))callback { | |
[[[SQLiteStatement alloc] initWithQueryTemplate:query inDatabase:self] executeWithCallback:callback]; | |
} | |
@end | |
@implementation SQLiteStatement | |
- (instancetype)initWithQueryTemplate:(NSString *)template inDatabase:(SQLiteDatabase *)database { | |
self = [super init]; | |
if (self) { | |
if (sqlite3_prepare_v2(database.database, [template cStringUsingEncoding:NSUTF8StringEncoding], -1, &_statement, NULL) != SQLITE_OK) { | |
return nil; | |
} | |
} | |
return self; | |
} | |
- (void)dealloc { | |
if (_statement) { | |
sqlite3_finalize(_statement); | |
} | |
} | |
- (void)execute { | |
[self executeWithParameters:nil callback:nil]; | |
} | |
- (void)executeWithParameters:(NSArray *)parameters { | |
[self executeWithParameters:parameters callback:nil]; | |
} | |
- (void)executeWithCallback:(void(^)(NSDictionary<NSString *, id> *, BOOL *))callback { | |
[self executeWithParameters:nil callback:callback]; | |
} | |
- (void)executeWithParameters:(NSArray *)parameters callback:(void(^)(NSDictionary<NSString *, id> *, BOOL *))callback { | |
sqlite3_reset(_statement); | |
for (int i = 0; i < parameters.count; i++) { | |
id parameter = parameters[i]; | |
if ([parameter isKindOfClass:[NSNull class]]) { | |
sqlite3_bind_null(_statement, i+1); | |
} else if ([parameter isKindOfClass:[NSString class]]) { | |
sqlite3_bind_text(_statement, i+1, [parameter cStringUsingEncoding:NSUTF8StringEncoding], -1, SQLITE_STATIC); | |
} else if ([parameter isKindOfClass:[NSData class]]) { | |
sqlite3_bind_blob(_statement, i+1, [parameter bytes], [parameter length], NULL); | |
} else if ([parameter isKindOfClass:[NSNumber class]]) { | |
switch ([parameter objCType][0]) { | |
case 'd': | |
case 'f': | |
sqlite3_bind_double(_statement, i+1, [parameter doubleValue]); | |
break; | |
default: | |
sqlite3_bind_int64(_statement, i+1, [parameter longLongValue]); | |
break; | |
} | |
} | |
} | |
BOOL stop = NO; | |
int columnCount = sqlite3_column_count(_statement); | |
while (!stop && sqlite3_step(_statement) == SQLITE_ROW && callback) { | |
NSMutableDictionary<NSString *, id> *row = [[NSMutableDictionary alloc] init]; | |
for (int i = 0; i < columnCount; i++) { | |
NSString *key = [[NSString alloc] initWithCString:sqlite3_column_name(_statement, i) encoding:NSUTF8StringEncoding]; | |
id value = nil; | |
switch (sqlite3_column_type(_statement, i)) { | |
case SQLITE_NULL: { | |
value = [NSNull null]; | |
} break; | |
case SQLITE_INTEGER: { | |
value = [[NSNumber alloc] initWithLongLong:sqlite3_column_int64(_statement, i)]; | |
} break; | |
case SQLITE_FLOAT: { | |
value = [[NSNumber alloc] initWithDouble:sqlite3_column_double(_statement, i)]; | |
} break; | |
case SQLITE_BLOB: { | |
int length = sqlite3_column_bytes(_statement, i); | |
const void *bytes = sqlite3_column_blob(_statement, i); | |
value = [[NSData alloc] initWithBytes:bytes length:length]; | |
} break; | |
case SQLITE3_TEXT: { | |
int length = sqlite3_column_bytes(_statement, i); | |
const void *bytes = sqlite3_column_blob(_statement, i); | |
value = [[NSString alloc] initWithBytes:bytes length:length encoding:NSUTF8StringEncoding]; | |
} break; | |
} | |
row[key] = value; | |
} | |
callback(row, &stop); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment