PageRenderTime 154ms CodeModel.GetById 109ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/MapView/Map/FMDB/FMResultSet.m

http://github.com/route-me/route-me
Objective C | 332 lines | 224 code | 98 blank | 10 comment | 47 complexity | dad3fba684cbe9235acf5ba47ade3b6a MD5 | raw file
  1#import "FMResultSet.h"
  2#import "FMDatabase.h"
  3#import "unistd.h"
  4
  5@interface FMResultSet (Private)
  6- (NSMutableDictionary *)columnNameToIndexMap;
  7- (void)setColumnNameToIndexMap:(NSMutableDictionary *)value;
  8@end
  9
 10@implementation FMResultSet
 11
 12+ (id) resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB {
 13    
 14    FMResultSet *rs = [[FMResultSet alloc] init];
 15    
 16    [rs setStatement:statement];
 17    [rs setParentDB:aDB];
 18    
 19    return [rs autorelease];
 20}
 21
 22- (void)dealloc {
 23    [self close];
 24    
 25    [query release];
 26    query = nil;
 27    
 28    [columnNameToIndexMap release];
 29    columnNameToIndexMap = nil;
 30    
 31	[super dealloc];
 32}
 33
 34- (void) close {
 35    
 36    [statement reset];
 37    [statement release];
 38    statement = nil;
 39    
 40    // we don't need this anymore... (i think)
 41    //[parentDB setInUse:NO];
 42    parentDB = nil;
 43}
 44
 45- (void) setupColumnNames {
 46    
 47    if (!columnNameToIndexMap) {
 48        [self setColumnNameToIndexMap:[NSMutableDictionary dictionary]];
 49    }	
 50    
 51    int columnCount = sqlite3_column_count(statement.statement);
 52    
 53    int columnIdx = 0;
 54    for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
 55        [columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx]
 56                                 forKey:[[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)] lowercaseString]];
 57    }
 58    columnNamesSetup = YES;
 59}
 60
 61- (void) kvcMagic:(id)object {
 62    
 63    int columnCount = sqlite3_column_count(statement.statement);
 64    
 65    int columnIdx = 0;
 66    for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
 67        
 68        const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx);
 69        
 70        // check for a null row
 71        if (c) {
 72            NSString *s = [NSString stringWithUTF8String:c];
 73            
 74            [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)]];
 75        }
 76    }
 77}
 78
 79- (BOOL) next {
 80    
 81    int rc;
 82    BOOL retry;
 83    int numberOfRetries = 0;
 84    do {
 85        retry = NO;
 86        
 87        rc = sqlite3_step(statement.statement);
 88        
 89        if (SQLITE_BUSY == rc) {
 90            // this will happen if the db is locked, like if we are doing an update or insert.
 91            // in that case, retry the step... and maybe wait just 10 milliseconds.
 92            retry = YES;
 93            usleep(20);
 94            
 95            if ([parentDB busyRetryTimeout] && (numberOfRetries++ > [parentDB busyRetryTimeout])) {
 96                
 97                NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]);
 98                NSLog(@"Database busy");
 99                break;
100            }
101        }
102        else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
103            // all is well, let's return.
104        }
105        else if (SQLITE_ERROR == rc) {
106            NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
107            break;
108        } 
109        else if (SQLITE_MISUSE == rc) {
110            // uh oh.
111            NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
112            break;
113        }
114        else {
115            // wtf?
116            NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
117            break;
118        }
119        
120    } while (retry);
121    
122    
123    if (rc != SQLITE_ROW) {
124        [self close];
125    }
126    
127    return (rc == SQLITE_ROW);
128}
129
130- (BOOL) hasAnotherRow {
131    return sqlite3_errcode([parentDB sqliteHandle]) == SQLITE_ROW;
132}
133
134- (int) columnIndexForName:(NSString*)columnName {
135    
136    if (!columnNamesSetup) {
137        [self setupColumnNames];
138    }
139    
140    columnName = [columnName lowercaseString];
141    
142    NSNumber *n = [columnNameToIndexMap objectForKey:columnName];
143    
144    if (n) {
145        return [n intValue];
146    }
147    
148    NSLog(@"Warning: I could not find the column named '%@'.", columnName);
149    
150    return -1;
151}
152
153
154
155- (int) intForColumn:(NSString*)columnName {
156    return [self intForColumnIndex:[self columnIndexForName:columnName]];
157}
158
159- (int) intForColumnIndex:(int)columnIdx {
160    return sqlite3_column_int(statement.statement, columnIdx);
161}
162
163- (long) longForColumn:(NSString*)columnName {
164    return [self longForColumnIndex:[self columnIndexForName:columnName]];
165}
166
167- (long) longForColumnIndex:(int)columnIdx {
168    return (long)sqlite3_column_int64(statement.statement, columnIdx);
169}
170
171- (long long int) longLongIntForColumn:(NSString*)columnName {
172    return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
173}
174
175- (long long int) longLongIntForColumnIndex:(int)columnIdx {
176    return sqlite3_column_int64(statement.statement, columnIdx);
177}
178
179- (BOOL) boolForColumn:(NSString*)columnName {
180    return [self boolForColumnIndex:[self columnIndexForName:columnName]];
181}
182
183- (BOOL) boolForColumnIndex:(int)columnIdx {
184    return ([self intForColumnIndex:columnIdx] != 0);
185}
186
187- (double) doubleForColumn:(NSString*)columnName {
188    return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
189}
190
191- (double) doubleForColumnIndex:(int)columnIdx {
192    return sqlite3_column_double(statement.statement, columnIdx);
193}
194
195- (NSString*) stringForColumnIndex:(int)columnIdx {
196    
197    if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
198		return nil;
199	}
200    
201    const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx);
202    
203    if (!c) {
204        // null row.
205        return nil;
206    }
207    
208    return [NSString stringWithUTF8String:c];
209}
210
211- (NSString*) stringForColumn:(NSString*)columnName {
212    return [self stringForColumnIndex:[self columnIndexForName:columnName]];
213}
214
215- (NSDate*) dateForColumn:(NSString*)columnName {
216    return [self dateForColumnIndex:[self columnIndexForName:columnName]];
217}
218
219- (NSDate*) dateForColumnIndex:(int)columnIdx {
220    
221    if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
222		return nil;
223	}
224    
225    return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
226}
227
228
229- (NSData*) dataForColumn:(NSString*)columnName {
230    return [self dataForColumnIndex:[self columnIndexForName:columnName]];
231}
232
233- (NSData*) dataForColumnIndex:(int)columnIdx {
234    
235    if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
236		return nil;
237	}
238    
239    int dataSize = sqlite3_column_bytes(statement.statement, columnIdx);
240    
241    NSMutableData *data = [NSMutableData dataWithLength:dataSize];
242    
243    memcpy([data mutableBytes], sqlite3_column_blob(statement.statement, columnIdx), dataSize);
244    
245    return data;
246}
247
248
249- (NSData*) dataNoCopyForColumn:(NSString*)columnName {
250    return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
251}
252
253- (NSData*) dataNoCopyForColumnIndex:(int)columnIdx {
254    
255    if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
256		return nil;
257	}
258    
259    int dataSize = sqlite3_column_bytes(statement.statement, columnIdx);
260    
261    NSData *data = [NSData dataWithBytesNoCopy:(void *)sqlite3_column_blob(statement.statement, columnIdx) length:dataSize freeWhenDone:NO];
262    
263    return data;
264}
265
266
267- (BOOL) columnIndexIsNull:(int)columnIdx {
268    return sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL;
269}
270
271- (BOOL) columnIsNull:(NSString*)columnName {
272    return [self columnIndexIsNull:[self columnIndexForName:columnName]];
273}
274
275- (const unsigned char *) UTF8StringForColumnIndex:(int)columnIdx {
276    
277    if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
278		return nil;
279	}
280    
281    return sqlite3_column_text(statement.statement, columnIdx);
282}
283
284- (const unsigned char *) UTF8StringForColumnName:(NSString*)columnName {
285	return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
286}
287
288
289// returns autoreleased NSString containing the name of the column in the result set
290- (NSString*) columnNameForIndex:(int)columnIdx {
291	return [NSString stringWithUTF8String: sqlite3_column_name(statement.statement, columnIdx)];
292}
293
294- (void)setParentDB:(FMDatabase *)newDb {
295    parentDB = newDb;
296}
297
298
299- (NSString *)query {
300    return query;
301}
302
303- (void)setQuery:(NSString *)value {
304    [value retain];
305    [query release];
306    query = value;
307}
308
309- (NSMutableDictionary *)columnNameToIndexMap {
310    return columnNameToIndexMap;
311}
312
313- (void)setColumnNameToIndexMap:(NSMutableDictionary *)value {
314    [value retain];
315    [columnNameToIndexMap release];
316    columnNameToIndexMap = value;
317}
318
319- (FMStatement *) statement {
320    return statement;
321}
322
323- (void)setStatement:(FMStatement *)value {
324    if (statement != value) {
325        [statement release];
326        statement = [value retain];
327    }
328}
329
330
331
332@end