The source code moved from the SPIN with license changed to Flora 1.1
[apps/native/home/homescreen-efl.git] / src / db / db.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sqlite3.h>
18
19 #include "homescreen-efl.h"
20 #include "conf.h"
21 #include "util.h"
22 #include "db/db.h"
23
24 static struct {
25         sqlite3 *db;
26         Ecore_Timer *close_timer;
27 } db_info = {
28         .db = NULL,
29         .close_timer = NULL,
30 };
31
32 #define CREATE_TABLE_ITEM "CREATE TABLE IF NOT EXISTS item(\
33 id INTEGER PRIMARY KEY NOT NULL,\
34 type INTEGER,\
35 pkg_id TEXT,\
36 first INTEGER,\
37 next INTEGER,\
38 x INTEGER,\
39 y INTEGER,\
40 w INTEGER,\
41 h INTEGER,\
42 content_info TEXT);"
43
44 #define SELECT_ITEM "SELECT * FROM item;"
45 #define INSERT_ITEM "INSERT OR REPLACE INTO item VALUES(?,?,?,?,?,?,?,?,?,?);"
46 #define CLEAR_TABLE "DELETE FROM item;"
47 #define DELETE_ITEM "DELETE FROM item WHERE id = ?;"
48
49 #define DATABASE_CLOSE_TIME 5
50
51 bool _db_is_success(int return_code);
52 bool _db_open(void);
53 void _db_close(void);
54 bool _db_prepare(const char *query, sqlite3_stmt **stmt);
55 bool _db_step(sqlite3_stmt *stmt);
56 bool _db_finalize(sqlite3_stmt *stmt);
57
58 bool db_create_tables(void)
59 {
60         if (!_db_open())
61                 return false;
62
63         sqlite3_exec(db_info.db, CLEAR_TABLE, NULL, NULL, NULL);
64
65         if (sqlite3_exec(db_info.db, CREATE_TABLE_ITEM, NULL, NULL, NULL))
66                 return false;
67
68         db_item_t root = {0, APP_ITEM_ROOT, "", -1, -1, 0, 0, 0, 0};
69         if (!db_update_apps(root, true))
70                 return false;
71
72         _db_close();
73
74         return true;
75 }
76
77 bool db_get_apps(Eina_List **apps)
78 {
79         const char *content_info = NULL;
80         sqlite3_stmt *stmt;
81         if (!_db_open())
82                 return false;
83
84         if (!_db_prepare(SELECT_ITEM, &stmt))
85                 return false;
86
87         while (sqlite3_step(stmt) == SQLITE_ROW) {
88                 db_item_t *item = (db_item_t *) malloc(sizeof(db_item_t));
89                 item->id = sqlite3_column_int(stmt, 0);
90                 item->type = sqlite3_column_int(stmt, 1);
91                 item->appid = strdup((const char *) sqlite3_column_text(
92                         stmt, 2));
93                 item->first_id = sqlite3_column_int(stmt, 3);
94                 item->next_id = sqlite3_column_int(stmt, 4);
95
96                 item->x = sqlite3_column_int(stmt, 5);
97                 item->y = sqlite3_column_int(stmt, 6);
98                 item->w = sqlite3_column_int(stmt, 7);
99                 item->h = sqlite3_column_int(stmt, 8);
100
101
102                 content_info = (const char *)sqlite3_column_text(stmt, 9);
103
104                 if (content_info) {
105                         item->content_info = strdup(content_info);
106                 } else {
107                         item->content_info = NULL;
108                 }
109
110                 *apps = eina_list_append(*apps, item);
111                 dlog_print(DLOG_DEBUG, LOG_TAG, "App: %s [%s]", item->appid, item->content_info );
112         }
113
114         if (!_db_finalize(stmt))
115                 return false;
116
117         _db_close();
118
119         return true;
120 }
121
122 void db_free_apps(Eina_List *apps)
123 {
124         db_item_t *db_item;
125         EINA_LIST_FREE(apps, db_item) {
126                 free(db_item->appid);
127                 free(db_item);
128         }
129 }
130
131 bool db_update_apps(db_item_t item, bool insert)
132 {
133         sqlite3_stmt *stmt;
134
135         if (!_db_open())
136                 return false;
137
138         if (insert) {
139                 if (!_db_prepare(INSERT_ITEM, &stmt)) {
140                         LOGD("_db_prepare() failed");
141                         return false;
142                 }
143
144                 sqlite3_bind_int(stmt, 1, item.id);
145                 sqlite3_bind_int(stmt, 2, item.type);
146                 sqlite3_bind_text(stmt, 3, item.appid, -1, SQLITE_STATIC);
147                 sqlite3_bind_int(stmt, 4, item.first_id);
148                 sqlite3_bind_int(stmt, 5, item.next_id);
149                 sqlite3_bind_int(stmt, 6, item.x);
150                 sqlite3_bind_int(stmt, 7, item.y);
151                 sqlite3_bind_int(stmt, 8, item.w);
152                 sqlite3_bind_int(stmt, 9, item.h);
153                 sqlite3_bind_text(stmt, 10, item.content_info, -1, SQLITE_STATIC);
154         } else {
155                 if (!_db_prepare(DELETE_ITEM, &stmt)) {
156                         LOGD("_db_prepare() failed");
157                         return false;
158                 }
159
160                 sqlite3_bind_int(stmt, 1, item.id);
161         }
162
163
164         if (!_db_step(stmt))
165                 return false;
166
167         if (!_db_finalize(stmt))
168                 return false;
169
170         _db_close();
171
172         return true;
173 }
174
175 bool _db_is_success(int return_code)
176 {
177         switch (return_code) {
178         case SQLITE_OK:
179                 LOGD("RETURN CODE: SQLITE_OK");
180                 break;
181         case SQLITE_ERROR:
182                 LOGD("RETURN CODE: SQLITE_ERROR");
183                 break;
184         case SQLITE_INTERNAL:
185                 LOGD("RETURN CODE: SQLITE_INTERNAL");
186                 break;
187         case SQLITE_PERM:
188                 LOGD("RETURN CODE: SQLITE_PERM");
189                 break;
190         case SQLITE_ABORT:
191                 LOGD("RETURN CODE: SQLITE_ABORT");
192                 break;
193         case SQLITE_BUSY:
194                 LOGD("RETURN CODE: SQLITE_BUSY");
195                 break;
196         case SQLITE_LOCKED:
197                 LOGD("RETURN CODE: SQLITE_LOCKED");
198                 break;
199         case SQLITE_NOMEM:
200                 LOGD("RETURN CODE: SQLITE_NOMEM");
201                 break;
202         case SQLITE_READONLY:
203                 LOGD("RETURN CODE: SQLITE_READONLY");
204                 break;
205         case SQLITE_INTERRUPT:
206                 LOGD("RETURN CODE: SQLITE_INTERRUPT");
207                 break;
208         case SQLITE_IOERR:
209                 LOGD("RETURN CODE: SQLITE_IOERR");
210                 break;
211         case SQLITE_CORRUPT:
212                 LOGD("RETURN CODE: SQLITE_CORRUPT");
213                 break;
214         case SQLITE_NOTFOUND:
215                 LOGD("RETURN CODE: SQLITE_NOTFOUND");
216                 break;
217         case SQLITE_FULL:
218                 LOGD("RETURN CODE: SQLITE_FULL");
219                 break;
220         case SQLITE_CANTOPEN:
221                 LOGD("RETURN CODE: SQLITE_CANTOPEN");
222                 break;
223         case SQLITE_PROTOCOL:
224                 LOGD("RETURN CODE: SQLITE_PROTOCOL");
225                 break;
226         case SQLITE_EMPTY:
227                 LOGD("RETURN CODE: SQLITE_EMPTY");
228                 break;
229         case SQLITE_SCHEMA:
230                 LOGD("RETURN CODE: SQLITE_SCHEMA");
231                 break;
232         case SQLITE_TOOBIG:
233                 LOGD("RETURN CODE: SQLITE_TOOBIG");
234                 break;
235         case SQLITE_CONSTRAINT:
236                 LOGD("RETURN CODE: SQLITE_CONSTRAINT");
237                 break;
238         case SQLITE_MISMATCH:
239                 LOGD("RETURN CODE: SQLITE_MISMATCH");
240                 break;
241         case SQLITE_MISUSE:
242                 LOGD("RETURN CODE: SQLITE_MISUSE");
243                 break;
244         case SQLITE_NOLFS:
245                 LOGD("RETURN CODE: SQLITE_NOLFS");
246                 break;
247         case SQLITE_AUTH:
248                 LOGD("RETURN CODE: SQLITE_AUTH");
249                 break;
250         case SQLITE_FORMAT:
251                 LOGD("RETURN CODE: SQLITE_FORMAT");
252                 break;
253         case SQLITE_RANGE:
254                 LOGD("RETURN CODE: SQLITE_RANGE");
255                 break;
256         case SQLITE_NOTADB:
257                 LOGD("RETURN CODE: SQLITE_NOTADB");
258                 break;
259         case SQLITE_ROW:
260                 LOGD("RETURN CODE: SQLITE_ROW");
261                 break;
262         case SQLITE_DONE:
263                 LOGD("RETURN CODE: SQLITE_DONE");
264                 break;
265         default:
266                 break;
267         }
268
269         return return_code == SQLITE_OK || return_code == SQLITE_DONE;
270 }
271
272 bool _db_open(void)
273 {
274         if (db_info.db)
275                 return true;
276
277         if (!_db_is_success(sqlite3_open(DATABASE_FILE, &db_info.db)))
278                 return false;
279
280         if (sqlite3_exec(db_info.db, "BEGIN IMMEDIATE TRANSACTION", NULL,
281                 NULL, NULL))
282                 return false;
283
284         return true;
285 }
286
287 Eina_Bool _db_close_cb(void *data)
288 {
289         LOGD("DB CLOSE");
290
291         if (db_info.db) {
292                 if (sqlite3_exec(db_info.db, "COMMIT TRANSACTION",
293                         NULL, NULL, NULL))
294                         return ECORE_CALLBACK_DONE;
295
296                 if (_db_is_success(sqlite3_close(db_info.db)))
297                         db_info.db = NULL;
298         }
299         db_info.close_timer = NULL;
300         return ECORE_CALLBACK_DONE;
301 }
302
303 void _db_close(void)
304 {
305         if (!db_info.db)
306                 return;
307
308         if (db_info.close_timer) {
309                 ecore_timer_reset(db_info.close_timer);
310         } else {
311                 db_info.close_timer = ecore_timer_add(DATABASE_CLOSE_TIME,
312                                         _db_close_cb, NULL);
313         }
314 }
315
316 bool _db_prepare(const char *query, sqlite3_stmt **stmt)
317 {
318         return _db_is_success(sqlite3_prepare_v2(db_info.db, query,
319                 strlen(query), stmt, NULL));
320 }
321
322 bool _db_step(sqlite3_stmt *stmt)
323 {
324         return _db_is_success(sqlite3_step(stmt));
325 }
326
327 bool _db_finalize(sqlite3_stmt *stmt)
328 {
329         return _db_is_success(sqlite3_finalize(stmt));
330 }