Added dataNoCopyForColumn: and dataNoCopyForColumnIndex: to FMResultSet.
[fmdb.git] / src / fmdb.m
blobf628223f11609275f0b573100a73bdfde787d1b1
1 #import <Foundation/Foundation.h>
2 #import "FMDatabase.h"
3 #import "FMDatabaseAdditions.h"
5 int main (int argc, const char * argv[]) {
6     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
7     
8     // delete the old db.
9     NSFileManager *fileManager = [NSFileManager defaultManager];
10     [fileManager removeFileAtPath:@"/tmp/tmp.db" handler:nil];
11     
12     FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
13     if (![db open]) {
14         NSLog(@"Could not open db.");
15         [pool release];
16         return 0;
17     }
18     
19     // kind of experimentalish.
20     [db setShouldCacheStatements:YES];
21     
22     // create a bad statement, just to test the error code.
23     [db executeUpdate:@"blah blah blah"];
24     if ([db hadError]) {
25         NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
26     }
27     
28     // but of course, I don't bother checking the error codes below.
29     // Bad programmer, no cookie.
30     
31     [db executeUpdate:@"create table test (a text, b text, c integer, d double, e double)"];
32     
33     
34     [db beginTransaction];
35     int i = 0;
36     while (i++ < 20) {
37         [db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
38             @"hi'", // look!  I put in a ', and I'm not escaping it!
39             [NSString stringWithFormat:@"number %d", i],
40             [NSNumber numberWithInt:i],
41             [NSDate date],
42             [NSNumber numberWithFloat:2.2f]];
43     }
44     [db commit];
45     
46     
47     
48     // do it again, just because
49     [db beginTransaction];
50     i = 0;
51     while (i++ < 20) {
52         [db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
53          @"hi again'", // look!  I put in a ', and I'm not escaping it!
54          [NSString stringWithFormat:@"number %d", i],
55          [NSNumber numberWithInt:i],
56          [NSDate date],
57          [NSNumber numberWithFloat:2.2f]];
58     }
59     [db commit];
60     
61     
62     
63     
64     
65     FMResultSet *rs = [db executeQuery:@"select rowid,* from test where a = ?", @"hi'"];
66     while ([rs next]) {
67         // just print out what we've got in a number of formats.
68         NSLog(@"%d %@ %@ %@ %@ %f %f",
69               [rs intForColumn:@"c"],
70               [rs stringForColumn:@"b"],
71               [rs stringForColumn:@"a"],
72               [rs stringForColumn:@"rowid"],
73               [rs dateForColumn:@"d"],
74               [rs doubleForColumn:@"d"],
75               [rs doubleForColumn:@"e"]);
76     }
77     // close the result set.
78     // it'll also close when it's dealloc'd, but we're closing the database before
79     // the autorelease pool closes, so sqlite will complain about it.
80     [rs close];  
81     
82     // ----------------------------------------------------------------------------------------
83     // blob support.
84     [db executeUpdate:@"create table blobTable (a text, b blob)"];
85     
86     // let's read in an image from safari's app bundle.
87     NSData *d = [NSData dataWithContentsOfFile:@"/Applications/Safari.app/Contents/Resources/compass.icns"];
88     if (d) {
89         [db executeUpdate:@"insert into blobTable (a, b) values (?,?)", @"safari's compass", d];
90         
91         rs = [db executeQuery:@"select b from blobTable where a = ?", @"safari's compass"];
92         if ([rs next]) {
93             d = [rs dataForColumn:@"b"];
94             [d writeToFile:@"/tmp/compass.icns" atomically:NO];
95             
96             // let's look at our fancy image that we just wrote out..
97             system("/usr/bin/open /tmp/compass.icns");
98             
99             // ye shall read the header for this function, or suffer the consequences.
100             d = [rs dataNoCopyForColumn:@"b"];
101             [d writeToFile:@"/tmp/compass_data_no_copy.icns" atomically:NO];
102             system("/usr/bin/open /tmp/compass_data_no_copy.icns");
103         }
104         else {
105             NSLog(@"Could not select image.");
106         }
107         
108         [rs close];
109         
110     }
111     else {
112         NSLog(@"Can't find compass image..");
113     }
114     
115     
116     // test out the convenience methods in +Additions
117     [db executeUpdate:@"create table t1 (a integer)"];
118     [db executeUpdate:@"insert into t1 values (?)", [NSNumber numberWithInt:5]];
119     int a = [db intForQuery:@"select a from t1 where a = ?", [NSNumber numberWithInt:5]];
120     if (a != 5) {
121         NSLog(@"intForQuery didn't work (a != 5)");
122     }
123     
124     // test the busy rety timeout schtuff.
125     
126     [db setBusyRetryTimeout:50000];
127     
128     FMDatabase *newDb = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
129     [newDb open];
130     
131     rs = [newDb executeQuery:@"select rowid,* from test where a = ?", @"hi'"];
132     [rs next]; // just grab one... which will keep the db locked.
133     
134     NSLog(@"Testing the busy timeout");
135     
136     BOOL success = [db executeUpdate:@"insert into t1 values (5)"];
137     
138     if (success) {
139         NSLog(@"Whoa- the database didn't stay locked!");
140         return 7;
141     }
142     else {
143         NSLog(@"Hurray, our timeout worked");
144     }
145     
146     [rs close];
147     [newDb close];
148     
149     success = [db executeUpdate:@"insert into t1 values (5)"];
150     if (!success) {
151         NSLog(@"Whoa- the database shouldn't be locked!");
152         return 8;
153     }
154     else {
155         NSLog(@"Hurray, we can insert again!");
156     }
157     
158     
159     
160     // test some nullness.
161     [db executeUpdate:@"create table t2 (a integer, b integer)"];
162     
163     if (![db executeUpdate:@"insert into t2 values (?, ?)", nil, [NSNumber numberWithInt:5]]) {
164         NSLog(@"UH OH, can't insert a nil value for some reason...");
165     }
166     
167     
168     
169     
170     rs = [db executeQuery:@"select * from t2"];
171     while ([rs next]) {
172         NSString *a = [rs stringForColumnIndex:0];
173         NSString *b = [rs stringForColumnIndex:1];
174         
175         if (a != nil) {
176             NSLog(@"%s:%d", __FUNCTION__, __LINE__);
177             NSLog(@"OH OH, PROBLEMO!");
178             return 10;
179         }
180         else {
181             NSLog(@"YAY, NULL VALUES");
182         }
183         
184         if (![b isEqualToString:@"5"]) {
185             NSLog(@"%s:%d", __FUNCTION__, __LINE__);
186             NSLog(@"OH OH, PROBLEMO!");
187             return 10;
188         }
189     }
190     
191     
192     
193     
194     
195     
196     
197     
198     
199     
200     // test some inner loop funkness.
201     [db executeUpdate:@"create table t3 (a somevalue)"];
202     
203     
204     // do it again, just because
205     [db beginTransaction];
206     i = 0;
207     while (i++ < 20) {
208         [db executeUpdate:@"insert into t3 (a) values (?)" , [NSNumber numberWithInt:i]];
209     }
210     [db commit];
211     
212     
213     
214     
215     rs = [db executeQuery:@"select * from t3"];
216     while ([rs next]) {
217         int foo = [rs intForColumnIndex:0];
218         
219         int newVal = foo + 100;
220         
221         [db executeUpdate:@"update t3 set a = ? where a = ?" , [NSNumber numberWithInt:newVal], [NSNumber numberWithInt:foo]];
222         
223         
224         FMResultSet *rs2 = [db executeQuery:@"select a from t3 where a = ?", [NSNumber numberWithInt:newVal]];
225         [rs2 next];
226         
227         if ([rs2 intForColumnIndex:0] != newVal) {
228             NSLog(@"Oh crap, our update didn't work out!");
229             return 9;
230         }
231         
232         [rs2 close];
233     }
234     
235     
236     // NSNull tests
237     [db executeUpdate:@"create table nulltest (a text, b text)"];
238     
239     [db executeUpdate:@"insert into nulltest (a, b) values (?, ?)" , [NSNull null], @"a"];
240     [db executeUpdate:@"insert into nulltest (a, b) values (?, ?)" , nil, @"b"];
241     
242     rs = [db executeQuery:@"select * from nulltest"];
243     
244     while ([rs next]) {
245         
246         NSString *a = [rs stringForColumnIndex:0];
247         NSString *b = [rs stringForColumnIndex:1];
248         
249         if (!b) {
250             NSLog(@"Oh crap, the nil / null inserts didn't work!");
251             return 10;
252         }
253         
254         if (a) {
255             NSLog(@"Oh crap, the nil / null inserts didn't work (son of error message)!");
256             return 11;
257         }
258         else {
259             NSLog(@"HURRAH FOR NSNULL (and nil)!");
260         }
261     }
262     
263     // print out some stats if we are using cached statements.
264     if ([db shouldCacheStatements]) {
265         
266         NSEnumerator *e = [[db cachedStatements] objectEnumerator];;
267         FMStatement *statement;
268         
269         while ((statement = [e nextObject])) {
270                 NSLog(@"%@", statement);
271         }
272     }
273     
274     
275     
276     NSLog(@"That was version %@ of sqlite", [FMDatabase sqliteLibVersion]);
277     
278     
279     [db close];
280     
281     [pool release];
282     return 0;