Fix memory leak in storage API
[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 <db-util.h>
29
30 #include <tcore.h>
31 #include <plugin.h>
32 #include <storage.h>
33
34 #ifndef PLUGIN_VERSION
35 #define PLUGIN_VERSION 1
36 #endif
37
38 static void *create_handle(Storage *strg, const char *path)
39 {
40         int rv = 0;
41         sqlite3 *handle = NULL;
42
43         rv = db_util_open(path, &handle, 0);
44         if (rv != SQLITE_OK) {
45                 err("fail to connect database err(%d)", rv);
46                 return NULL;
47         }
48
49         dbg("connected to %s", path);
50         return handle;
51 }
52
53 static gboolean remove_handle(Storage *strg, void *handle)
54 {
55         if (!handle)
56                 return FALSE;
57
58         db_util_close(handle);
59
60         dbg("disconnected from database");
61         return TRUE;
62 }
63
64 static gboolean update_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
65 {
66         int rv = 0;
67         sqlite3_stmt *stmt = NULL;
68         char szQuery[1000+1];   /* +1 is for NULL Termination Character '\0' */
69
70         GHashTableIter iter;
71         gpointer key, value;
72
73         dbg("update query");
74
75         memset(szQuery, '\0', 1001);
76         strncpy(szQuery, query, 1000);
77
78         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
79         if (rv != SQLITE_OK) {
80                 err("fail to connect to table (%d)", rv);
81                 return FALSE;
82         }
83
84         if (in_param) {
85                 g_hash_table_iter_init(&iter, in_param);
86                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
87                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
88
89                         if (!value || g_strcmp0((const char *)value, "") == 0) {
90                                 dbg("bind null");
91                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
92                         } else {
93                                 dbg("bind value");
94                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
95                                                 SQLITE_STATIC);
96                         }
97
98                         if (rv != SQLITE_OK) {
99                                 dbg("fail to bind data (%d)", rv);
100                                 return FALSE;
101                         }
102                 }
103         }
104
105         rv = sqlite3_step(stmt);
106         dbg("update query executed (%d)", rv);
107         sqlite3_finalize(stmt);
108
109         if (rv != SQLITE_DONE)
110                 return FALSE;
111
112         return TRUE;
113 }
114
115 static gboolean _read_query_database_internal(Storage *strg, void *handle, const char *query, GHashTable *in_param,
116                 gpointer out_param, int out_param_cnt, gboolean in_order)
117 {
118         int rv = 0, local_index = 0, outter_index = 0;
119         sqlite3_stmt *stmt = NULL;
120         char szQuery[5000+1];   /* +1 is for NULL Termination Character '\0' */
121
122         GHashTableIter iter;
123         gpointer key, value;
124
125         dbg("read query");
126
127         memset(szQuery, '\0', 5001);
128         strncpy(szQuery, query, 5000);
129
130         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
131         if (rv != SQLITE_OK) {
132                 err("fail to connect to table (%d)", rv);
133                 return FALSE;
134         }
135
136         if (in_param) {
137                 g_hash_table_iter_init(&iter, in_param);
138                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
139                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
140
141                         if (!value || g_strcmp0((const char *)value, "") == 0) {
142                                 dbg("bind null");
143                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
144                         } else {
145                                 dbg("bind value");
146                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
147                                                 SQLITE_STATIC);
148                         }
149
150                         if (rv != SQLITE_OK) {
151                                 dbg("fail to bind data (%d)", rv);
152                                 return FALSE;
153                         }
154                 }
155         }
156
157         rv = sqlite3_step(stmt);
158         dbg("read query executed (%d), in_order (%d)", rv, in_order);
159
160         while (rv == SQLITE_ROW) {
161                 GHashTable *out_param_data;
162
163                 out_param_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
164
165                 for (local_index = 0; local_index < out_param_cnt; local_index++) {
166                         char tmp_key[10];
167                         const unsigned char *tmp;
168                         tmp = sqlite3_column_text(stmt, local_index);
169                         snprintf(tmp_key, sizeof(tmp_key), "%d", local_index);
170                         g_hash_table_insert(out_param_data, g_strdup(tmp_key), g_strdup((const char *)tmp));
171                 }
172
173                 if (in_order) {
174                         GSList **temp = out_param;
175                         *temp = g_slist_append(*temp, out_param_data);
176                 } else {
177                         char tmp_key_outter[10];
178                         snprintf(tmp_key_outter, sizeof(tmp_key_outter), "%d", outter_index);
179                         g_hash_table_insert((GHashTable*)out_param, g_strdup(tmp_key_outter), out_param_data);
180                 }
181                 outter_index++;
182                 rv = sqlite3_step(stmt);
183         }
184
185         sqlite3_finalize(stmt);
186         return TRUE;
187 }
188
189 static gboolean read_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param,
190                 GHashTable **out_param, int out_param_cnt)
191 {
192         GHashTable *out_hash_table;
193
194         if (out_param == NULL)
195                 return FALSE;
196
197         out_hash_table = g_hash_table_new_full(g_str_hash, g_str_equal,
198                         g_free, (GDestroyNotify)g_hash_table_destroy);
199
200         if (_read_query_database_internal(strg,
201                         handle, query, in_param, out_hash_table, out_param_cnt, FALSE) == FALSE) {
202                 g_hash_table_destroy(out_hash_table);
203                 return FALSE;
204         }
205
206         *out_param = out_hash_table;
207
208         return TRUE;
209 }
210
211 static gboolean read_query_database_in_order(Storage *strg, void *handle, const char *query, GHashTable *in_param,
212                 GSList **out_param, int out_param_cnt)
213 {
214         if (_read_query_database_internal(strg,
215                         handle, query, in_param, out_param, out_param_cnt, TRUE) == FALSE)
216                 return FALSE;
217
218         return TRUE;
219 }
220
221 static gboolean insert_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
222 {
223         int rv = 0;
224         sqlite3_stmt *stmt = NULL;
225         char szQuery[5000+1];   /* +1 is for NULL Termination Character '\0' */
226
227         GHashTableIter iter;
228         gpointer key, value;
229         dbg("insert query");
230
231         memset(szQuery, '\0', 5001);
232         strncpy(szQuery, query, 5000);
233
234         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
235         if (rv != SQLITE_OK) {
236                 err("fail to connect to table (%d)", rv);
237                 return FALSE;
238         }
239
240         if (in_param) {
241                 g_hash_table_iter_init(&iter, in_param);
242                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
243                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
244
245                         if (!value || g_strcmp0((const char *)value, "") == 0) {
246                                 dbg("bind null");
247                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
248                         } else {
249                                 dbg("bind value");
250                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
251                                                 SQLITE_STATIC);
252                         }
253
254                         if (rv != SQLITE_OK) {
255                                 dbg("fail to bind data (%d)", rv);
256                                 return FALSE;
257                         }
258                 }
259         }
260
261         rv = sqlite3_step(stmt);
262         dbg("insert query executed (%d)", rv);
263         sqlite3_finalize(stmt);
264
265         if (rv != SQLITE_DONE)
266                 return FALSE;
267
268         return TRUE;
269 }
270
271 static gboolean remove_query_database(Storage *strg, void *handle, const char *query, GHashTable *in_param)
272 {
273         int rv = 0;
274         sqlite3_stmt *stmt = NULL;
275         char szQuery[1000+1];   /* +1 is for NULL Termination Character '\0' */
276
277         GHashTableIter iter;
278         gpointer key, value;
279         dbg("remove query");
280
281         memset(szQuery, '\0', 1001);
282         strncpy(szQuery, query, 1000);
283
284         rv = sqlite3_prepare_v2(handle, szQuery, strlen(szQuery), &stmt, NULL);
285         if (rv != SQLITE_OK) {
286                 err("fail to connect to table (%d)", rv);
287                 return FALSE;
288         }
289
290         if (in_param) {
291                 g_hash_table_iter_init(&iter, in_param);
292                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
293                         dbg("key(%s), value(%s)", (const char *)key, (const char *)value);
294
295                         if (!value || g_strcmp0((const char *)value, "") == 0) {
296                                 dbg("bind null");
297                                 rv = sqlite3_bind_null(stmt, atoi((const char *)key));
298                         } else {
299                                 dbg("bind value");
300                                 rv = sqlite3_bind_text(stmt, atoi((const char *)key), (const char *)value, strlen((const char *)value),
301                                                 SQLITE_STATIC);
302                         }
303
304                         if (rv != SQLITE_OK) {
305                                 dbg("fail to bind data (%d)", rv);
306                                 return FALSE;
307                         }
308                 }
309         }
310
311         rv = sqlite3_step(stmt);
312         dbg("remove query executed (%d)", rv);
313         sqlite3_finalize(stmt);
314
315         if (rv != SQLITE_DONE)
316                 return FALSE;
317
318         return TRUE;
319 }
320
321 static struct storage_operations ops = {
322         .create_handle = create_handle,
323         .remove_handle = remove_handle,
324         .update_query_database = update_query_database,
325         .read_query_database = read_query_database,
326         .read_query_database_in_order = read_query_database_in_order,
327         .insert_query_database = insert_query_database,
328         .remove_query_database = remove_query_database,
329 };
330
331 static gboolean on_load()
332 {
333         dbg("i'm load!");
334         return TRUE;
335 }
336
337 static gboolean on_init(TcorePlugin *p)
338 {
339         if (!p)
340                 return FALSE;
341
342         tcore_storage_new(p, "database", &ops);
343
344         dbg("finish to initialize database plug-in");
345         return TRUE;
346 }
347
348 static void on_unload(TcorePlugin *p)
349 {
350         dbg("i'm unload!");
351         return;
352 }
353
354 EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
355         .name = "DATABASE",
356         .priority = TCORE_PLUGIN_PRIORITY_HIGH - 1,
357         .version = PLUGIN_VERSION,
358         .load = on_load,
359         .init = on_init,
360         .unload = on_unload
361 };