1 #import "ITSQLite3Database.h"
3 int sqlite3_bind_objc_object(sqlite3_stmt *statement, int index, id object) {
6 if ([object isKindOfClass:[NSData class]]) {
7 retval = sqlite3_bind_blob(statement, index, [object bytes], [object length], SQLITE_TRANSIENT);
8 } else if ([object isKindOfClass:[NSDate class]]) {
9 retval = sqlite3_bind_double(statement, index, [object timeIntervalSince1970]);
10 } else if ([object isKindOfClass:[NSNull class]]) {
11 retval = sqlite3_bind_null(statement, index);
12 } else if ([object isKindOfClass:[NSNumber class]]) {
13 if (strcmp([object objCType], @encode(BOOL)) == 0) {
14 retval = sqlite3_bind_int(statement, index, ([object boolValue] ? 1 : 0));
15 } else if (strcmp([object objCType], @encode(int)) == 0) {
16 retval = sqlite3_bind_int64(statement, index, [object longValue]);
17 } else if (strcmp([object objCType], @encode(long)) == 0) {
18 retval = sqlite3_bind_int64(statement, index, [object longValue]);
19 } else if (strcmp([object objCType], @encode(float)) == 0) {
20 retval = sqlite3_bind_double(statement, index, [object floatValue]);
21 } else if (strcmp([object objCType], @encode(double)) == 0) {
22 retval = sqlite3_bind_double(statement, index, [object doubleValue]);
27 retval = sqlite3_bind_text(statement, index, [[object description] UTF8String], -1, SQLITE_TRANSIENT);
33 id sqlite3_column_objc_object(sqlite3_stmt *statement, int columnIndex) {
36 switch (sqlite3_column_type(statement, columnIndex)) {
38 retval = [NSNumber numberWithLongLong:sqlite3_column_int64(statement, columnIndex)];
41 retval = [NSNumber numberWithDouble:sqlite3_column_double(statement, columnIndex)];
44 retval = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, columnIndex)];
47 retval = [NSData dataWithBytes:sqlite3_column_blob(statement, columnIndex) length:sqlite3_column_bytes(statement, columnIndex)];
51 retval = [NSNull null];
58 @interface ITSQLite3Database (Internals)
59 - (BOOL)executeQuery:(NSString *)query va_args:(va_list)args;
60 - (NSDictionary *)fetchRow:(NSString *)query va_args:(va_list)args;
61 - (NSArray *)fetchTable:(NSString *)query va_args:(va_list)args;
64 @implementation ITSQLite3Database
66 - (id)initWithPath:(NSString *)path {
67 if (self = [super init]) {
69 if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
70 ITDebugLog(@"%@ sqlite3_open(\"%@\"): %@", ITDebugErrorPrefixForObject(self), dbPath, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
74 dbLock = [[NSRecursiveLock alloc] init];
81 if (sqlite3_close(db) != SQLITE_OK) {
82 ITDebugLog(@"%@ sqlite3_close(0x%x): %@", ITDebugErrorPrefixForObject(self), db, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
89 return [self beginTransaction];
92 - (BOOL)beginTransaction {
93 return [self executeQuery:@"BEGIN TRANSACTION;"];
97 return [self commitTransaction];
100 - (BOOL)commitTransaction {
101 return [self executeQuery:@"COMMIT TRANSACTION;"];
105 return [self rollbackTransaction];
108 - (BOOL)rollbackTransaction {
109 return [self executeQuery:@"ROLLBACK TRANSACTION;"];
112 - (BOOL)executeQuery:(NSString *)query va_args:(va_list)args {
113 sqlite3_stmt *statement;
115 if (sqlite3_prepare(db, [query UTF8String], -1, &statement, 0) != SQLITE_OK) {
116 ITDebugLog(@"%@ sqlite3_prepare(0x%x, \"%@\", -1, 0x%x, 0): %@", ITDebugErrorPrefixForObject(self), db, query, statement, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
120 int argi, argc = sqlite3_bind_parameter_count(statement);
121 for (argi = 0; argi < argc; argi++) {
122 id arg = va_arg(args, id);
125 [NSException raise:NSInvalidArgumentException format:@"ITSQLite3Database: -executeQuery expected %i arguments, received %i.", argc, argi];
126 sqlite3_finalize(statement);
130 sqlite3_bind_objc_object(statement, argi+1, arg);
133 int stepret = sqlite3_step(statement);
134 int finalizeret = sqlite3_finalize(statement);
135 if (!(stepret == SQLITE_DONE || stepret == SQLITE_ROW)) {
136 ITDebugLog(@"%@ sqlite3_step(0x%x): %@", ITDebugErrorPrefixForObject(self), statement, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
143 - (BOOL)executeQuery:(NSString *)query, ... {
145 va_start(args, query);
148 BOOL result = [self executeQuery:query va_args:args];
155 - (NSDictionary *)fetchRow:(NSString *)query va_args:(va_list)args {
156 NSArray *table = [self fetchTable:query va_args:args];
157 if ([table count] >= 1) {
158 return [table objectAtIndex:0];
163 - (NSDictionary *)fetchRow:(NSString *)query, ... {
165 va_start(args, query);
168 NSDictionary *result = [self fetchRow:query va_args:args];
175 - (NSArray *)fetchTable:(NSString *)query va_args:(va_list)args {
176 sqlite3_stmt *statement;
178 if (sqlite3_prepare(db, [query UTF8String], -1, &statement, 0) != SQLITE_OK) {
179 ITDebugLog(@"%@ sqlite3_prepare(0x%x, \"%@\", -1, 0x%x, 0): %@", ITDebugErrorPrefixForObject(self), db, query, statement, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
183 int argi, argc = sqlite3_bind_parameter_count(statement);
184 for (argi = 0; argi < argc; argi++) {
185 id arg = va_arg(args, id);
188 [NSException raise:NSInvalidArgumentException format:@"ITSQLite3Database: -executeQuery expected %i arguments, received %i.", argc, argi];
189 sqlite3_finalize(statement);
193 sqlite3_bind_objc_object(statement, argi+1, arg);
196 NSMutableArray *rowArray = [[NSMutableArray alloc] init];
199 while ((stepret = sqlite3_step(statement)) == SQLITE_ROW) {
200 NSMutableDictionary *row = [[NSMutableDictionary alloc] init];
201 int coli, cols = sqlite3_column_count(statement);
202 for (coli = 0; coli < cols; coli++) {
203 [row setObject:sqlite3_column_objc_object(statement, coli) forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement, coli)]];
205 [rowArray addObject:[row autorelease]];
208 int finalizeret = sqlite3_finalize(statement);
209 if (stepret != SQLITE_DONE) {
210 ITDebugLog(@"%@ sqlite3_step(0x%x): %@", ITDebugErrorPrefixForObject(self), statement, [NSString stringWithUTF8String:sqlite3_errmsg(db)]);
214 return [rowArray autorelease];
217 - (NSArray *)fetchTable:(NSString *)query, ... {
219 va_start(args, query);
222 NSArray *result = [self fetchTable:query va_args:args];
229 - (id)fetchRowColumn:(NSString *)query, ... {
231 va_start(args, query);
234 NSDictionary *result = [self fetchRow:query va_args:args];
240 if ([[result allKeys] count] >= 1) {
241 return [result objectForKey:[[result allKeys] objectAtIndex:0]];
248 - (NSArray *)fetchTableColumn:(NSString *)query, ... {
250 va_start(args, query);
253 NSArray *result = [self fetchTable:query va_args:args];
259 NSMutableArray *columnArray = [[NSMutableArray alloc] init];
260 NSEnumerator *enumerator = [result objectEnumerator];
262 while (row = (NSDictionary *)[enumerator nextObject]) {
263 [columnArray addObject:[row objectForKey:[[row allKeys] objectAtIndex:0]]];
265 return [columnArray autorelease];