Reinstate more optimization, but avoid disagreement with dex by properly disabling...
[zxing.git] / iphone / Classes / Database.m
1 //
2 //  Database.m
3 //  ZXing
4 //
5 //  Created by Christian Brunschen on 29/05/2008.
6 /*
7  * Copyright 2008 ZXing authors
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #import "Database.h"
23 #import "Scan.h"
24
25 @implementation Database
26
27 static sqlite3_stmt *maxIdStatement;
28 static sqlite3_stmt *selectAllStatement;
29 static sqlite3_stmt *insertStatement;
30 static sqlite3_stmt *deleteStatement;
31
32 @synthesize connection;
33 @synthesize nextScanIdent;
34
35 static Database *sharedDatabase = nil;
36
37 + (id)sharedDatabase {
38   if (!sharedDatabase) {
39     sharedDatabase = [[self alloc] init];
40     
41     BOOL success;
42     NSFileManager *fileManager = [NSFileManager defaultManager];
43     NSError *error;
44     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
45     NSString *documentsDirectory = [paths objectAtIndex:0];
46     NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"scans.db"];
47     success = [fileManager fileExistsAtPath:writableDBPath];
48     if (!success) {
49       // The writable database does not exist, so copy the default to the appropriate location.
50       NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"scans.db"];
51       success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
52       if (!success) {
53         NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
54       }
55     }
56     
57     sqlite3 *connection;
58     sqlite3_open([writableDBPath UTF8String], &connection);
59     sharedDatabase.connection = connection;
60     
61     static const char *maxIdSql = "SELECT MAX(id) FROM SCAN";
62     sqlite3_prepare_v2(connection, maxIdSql, -1, &maxIdStatement, NULL);
63     
64     static const char *selectAllSql = "SELECT id, text, stamp FROM SCAN ORDER BY id";
65     sqlite3_prepare_v2(connection, selectAllSql, -1, &selectAllStatement, NULL);
66     
67     static const char *insertSql = 
68       "INSERT INTO SCAN (id, text, stamp) VALUES (?, ?, ?)";
69     sqlite3_prepare_v2(connection, insertSql, -1, &insertStatement, NULL);
70     
71     static const char *deleteSql = "DELETE FROM SCAN WHERE id = ?";
72     sqlite3_prepare_v2(connection, deleteSql, -1, &deleteStatement, NULL);
73     
74     if (SQLITE_ROW == sqlite3_step(maxIdStatement)) {
75       int maxId = sqlite3_column_int(maxIdStatement, 0);
76       sharedDatabase.nextScanIdent = maxId + 1;
77       sqlite3_reset(maxIdStatement);
78     } else {
79       NSLog(@"failed to read max ID from database\n");
80     }
81     
82   }
83   return sharedDatabase;
84 }
85
86 - (void)addScanWithText:(NSString *)text {
87   sqlite3_bind_int(insertStatement, 1, nextScanIdent++);
88   sqlite3_bind_text(insertStatement, 2, [text UTF8String], -1, SQLITE_TRANSIENT);
89   sqlite3_bind_double(insertStatement, 3, [[NSDate date] timeIntervalSince1970]);
90   sqlite3_step(insertStatement);
91   sqlite3_reset(insertStatement);
92 }
93
94 - (NSArray *)scans {
95   NSMutableArray *scans = [NSMutableArray array];
96   while (SQLITE_ROW == sqlite3_step(selectAllStatement)) {
97     int ident = sqlite3_column_int(selectAllStatement, 0);
98     NSString *text = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectAllStatement, 1)];
99     NSDate *stamp = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(selectAllStatement, 2)];
100     Scan *scan = [[Scan alloc] initWithIdent:ident text:text stamp:stamp];
101     [scans addObject:scan];
102     [scan release];
103   }
104   sqlite3_reset(selectAllStatement);
105   return scans;
106 }
107
108 - (void)deleteScan:(Scan *)scan {
109   sqlite3_bind_int(deleteStatement, 1, [scan ident]);
110   sqlite3_step(deleteStatement);
111   sqlite3_reset(deleteStatement);
112 }
113
114
115 @end