Remove db-util dependency
[platform/core/telephony/tel-plugin-database.git] / src / database_main.c
1 /*
2  * tel-plugin-database
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <strings.h>
26
27 #include <glib.h>
28 #include <sqlite3.h>
29 #include <unistd.h>
30
31 #include <tcore.h>
32 #include <server.h>
33 #include <plugin.h>
34 #include <storage.h>
35
36 #ifndef PLUGIN_VERSION
37 #define PLUGIN_VERSION 1
38 #endif
39
40 static gboolean __update_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
41 {
42         int rv = 0;
43         sqlite3_stmt *stmt = NULL;
44         char szQuery[1000+1];   /* +1 is for NULL Termination Character '\0' */
45
46         GHashTableIter iter;
47         gpointer key, value;
48
49         dbg("update query");
50
51         memset(szQuery, '\0', 1001);
52         strncpy(szQuery, query, 1000);
53
54         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
55         if (rv != SQLITE_OK) {
56                 err("fail to connect to table (%d)", rv);
57                 return FALSE;
58         }
59
60         if (in_param) {
61                 g_hash_table_iter_init(&iter, in_param);
62                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
63                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
64
65                         if (!value || g_strcmp0((const char *)value, "") == 0) {
66                                 dbg("bind null");
67                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
68                         } else {
69                                 dbg("bind value");
70                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
71                                                 SQLITE_STATIC);
72                         }
73
74                         if (rv != SQLITE_OK) {
75                                 dbg("fail to bind data (%d)", rv);
76                                 break;
77                         }
78                 }
79         }
80
81         if (rv != SQLITE_OK) {
82                 sqlite3_finalize(stmt);
83                 return FALSE;
84         }
85
86         rv = sqlite3_step(stmt);
87         dbg("query executed (%d)", rv);
88         sqlite3_finalize(stmt);
89
90         if (rv != SQLITE_DONE)
91                 return FALSE;
92
93         return TRUE;
94 }
95
96 static int _busy_handler(void *pData, int count)
97 {
98         if (5 - count > 0) {
99                 dbg("Busy Handler Called! : CNT(%d)\n", count + 1);
100                 usleep((count + 1) * 100000);
101                 return 1;
102         } else {
103                 dbg("Busy Handler will be returned SQLITE_BUSY error\n");
104                 return 0;
105         }
106 }
107
108 static void *create_handle(Storage *strg, const char *path)
109 {
110         int rv = 0;
111         sqlite3 *handle = NULL;
112
113         if (path == NULL) {
114                 err("Invalid input param error");
115                 return NULL;
116         }
117
118         rv = sqlite3_open(path, &handle);
119         if (rv != SQLITE_OK) {
120                 err("fail to connect database err(%d), errmsg(%s)", rv, sqlite3_errmsg(handle));
121                 return NULL;
122         }
123
124         rv = sqlite3_busy_handler(handle, _busy_handler, NULL);
125         if (rv != SQLITE_OK) {
126                 err("fail to register busy handler err(%d), errmsg(%s)", rv, sqlite3_errmsg(handle));
127                 return NULL;
128         }
129
130         dbg("connected to %s", path);
131         return handle;
132 }
133
134 static gboolean remove_handle(Storage *strg, void *handle)
135 {
136         int rv = 0;
137
138         if (!handle)
139                 return FALSE;
140
141         rv = sqlite3_close(handle);
142         if (rv != SQLITE_OK) {
143                 err("fail to close database err(%d)", rv);
144                 handle = NULL;
145                 return FALSE;
146         }
147
148         dbg("disconnected from database");
149         return TRUE;
150 }
151
152 static gboolean update_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
153 {
154         gboolean ret = TRUE;
155
156         dbg("update query");
157
158         ret = __update_query_database(strg, handle, query, in_param);
159
160         return ret;
161 }
162
163 static gboolean _read_query_database_internal(Storage *strg, void *handle, const char *query, GHashTable *in_param,
164                 gpointer out_param, int out_param_cnt, gboolean in_order)
165 {
166         int rv = 0, local_index = 0, outter_index = 0;
167         sqlite3_stmt *stmt = NULL;
168         char szQuery[5000+1];   /* +1 is for NULL Termination Character '\0' */
169
170         GHashTableIter iter;
171         gpointer key, value;
172
173         dbg("read query");
174
175         memset(szQuery, '\0', 5001);
176         strncpy(szQuery, query, 5000);
177
178         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
179         if (rv != SQLITE_OK) {
180                 err("fail to connect to table (%d)", rv);
181                 return FALSE;
182         }
183
184         if (in_param) {
185                 g_hash_table_iter_init(&iter, in_param);
186                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
187                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
188
189                         if (!value || g_strcmp0((const char *)value, "") == 0) {
190                                 dbg("bind null");
191                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
192                         } else {
193                                 dbg("bind value");
194                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
195                                                 SQLITE_STATIC);
196                         }
197
198                         if (rv != SQLITE_OK) {
199                                 dbg("fail to bind data (%d)", rv);
200                                 break;
201                         }
202                 }
203         }
204
205         if (rv != SQLITE_OK) {
206                 sqlite3_finalize(stmt);
207                 return FALSE;
208         }
209
210         rv = sqlite3_step(stmt);
211         dbg("read query executed (%d), in_order (%d)", rv, in_order);
212
213         while (rv == SQLITE_ROW) {
214                 GHashTable *out_param_data;
215
216                 out_param_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
217
218                 for (local_index = 0; local_index < out_param_cnt; local_index++) {
219                         char tmp_key[10];
220                         const unsigned char *tmp;
221                         tmp = sqlite3_column_text(stmt, local_index);
222                         snprintf(tmp_key, sizeof(tmp_key), "%d", local_index);
223                         g_hash_table_insert(out_param_data, g_strdup(tmp_key), g_strdup((const char *)tmp));
224                 }
225
226                 if (in_order) {
227                         GSList **temp = out_param;
228                         *temp = g_slist_append(*temp, out_param_data);
229                 } else {
230                         char tmp_key_outter[10];
231                         snprintf(tmp_key_outter, sizeof(tmp_key_outter), "%d", outter_index);
232                         g_hash_table_insert((GHashTable*)out_param, g_strdup(tmp_key_outter), out_param_data);
233                 }
234                 outter_index++;
235                 rv = sqlite3_step(stmt);
236         }
237
238         sqlite3_finalize(stmt);
239         return TRUE;
240 }
241
242 static gboolean read_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param,
243                 GHashTable **out_param, int out_param_cnt)
244 {
245         GHashTable *out_hash_table;
246
247         if (out_param == NULL)
248                 return FALSE;
249
250         out_hash_table = g_hash_table_new_full(g_str_hash, g_str_equal,
251                         g_free, (GDestroyNotify)g_hash_table_destroy);
252
253         if (_read_query_database_internal(strg,
254                         handle, query, in_param, out_hash_table, out_param_cnt, FALSE) == FALSE) {
255                 g_hash_table_destroy(out_hash_table);
256                 return FALSE;
257         }
258
259         *out_param = out_hash_table;
260
261         return TRUE;
262 }
263
264 static gboolean read_query_database_in_order(Storage *strg, void *handle, const char *query, GHashTable *in_param,
265                 GSList **out_param, int out_param_cnt)
266 {
267         if (_read_query_database_internal(strg,
268                         handle, query, in_param, out_param, out_param_cnt, TRUE) == FALSE)
269                 return FALSE;
270
271         return TRUE;
272 }
273
274 static gboolean insert_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
275 {
276         int rv = 0;
277         sqlite3_stmt *stmt = NULL;
278         char szQuery[5000+1];   /* +1 is for NULL Termination Character '\0' */
279
280         GHashTableIter iter;
281         gpointer key, value;
282         dbg("insert query");
283
284         memset(szQuery, '\0', 5001);
285         strncpy(szQuery, query, 5000);
286
287         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
288         if (rv != SQLITE_OK) {
289                 err("fail to connect to table (%d)", rv);
290                 return FALSE;
291         }
292
293         if (in_param) {
294                 g_hash_table_iter_init(&iter, in_param);
295                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
296                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
297
298                         if (!value || g_strcmp0((const char *)value, "") == 0) {
299                                 dbg("bind null");
300                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
301                         } else {
302                                 dbg("bind value");
303                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
304                                                 SQLITE_STATIC);
305                         }
306
307                         if (rv != SQLITE_OK) {
308                                 dbg("fail to bind data (%d)", rv);
309                                 break;
310                         }
311                 }
312         }
313
314         if (rv != SQLITE_OK) {
315                 sqlite3_finalize(stmt);
316                 return FALSE;
317         }
318
319         rv = sqlite3_step(stmt);
320         dbg("insert query executed (%d)", rv);
321         sqlite3_finalize(stmt);
322
323         if (rv != SQLITE_DONE)
324                 return FALSE;
325
326         return TRUE;
327 }
328
329 static gboolean remove_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
330 {
331         gboolean ret = TRUE;
332
333         dbg("remove query");
334
335         ret = __update_query_database(strg, handle, query, in_param);
336
337         return ret;
338 }
339
340 static struct storage_operations ops = {
341         .create_handle = create_handle,
342         .remove_handle = remove_handle,
343         .update_query_database = update_query_database,
344         .read_query_database = read_query_database,
345         .read_query_database_in_order = read_query_database_in_order,
346         .insert_query_database = insert_query_database,
347         .remove_query_database = remove_query_database,
348 };
349
350 static gboolean on_load()
351 {
352         dbg("i'm load!");
353         return TRUE;
354 }
355
356 static gboolean on_init(TcorePlugin *p)
357 {
358         if (!p)
359                 return FALSE;
360
361         tcore_storage_new(p, "database", &ops);
362
363         dbg("finish to initialize database plug-in");
364         return TRUE;
365 }
366
367 static void on_unload(TcorePlugin *p)
368 {
369         Storage *strg;
370
371         if (!p)
372                 return;
373
374         dbg("i'm unload!");
375
376         strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "database");
377         if (!strg)
378                 return;
379
380         tcore_storage_free(strg);
381         return;
382
383 }
384
385 EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
386         .name = "DATABASE",
387         .priority = TCORE_PLUGIN_PRIORITY_HIGH - 1,
388         .version = PLUGIN_VERSION,
389         .load = on_load,
390         .init = on_init,
391         .unload = on_unload
392 };