Fix crash issue
[platform/core/multimedia/libmedia-service.git] / src / common / media-svc-db-utils.c
1 /*
2  * libmedia-service
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@samsung.com>, Haejeong Kim <backto.kim@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 <unistd.h>
23 #include <media-util.h>
24 #include <errno.h>
25 #include "media-svc-env.h"
26 #include "media-svc-debug.h"
27 #include "media-svc-util.h"
28 #include "media-svc-db-utils.h"
29 #include "media-util-err.h"
30 #include "media-util-db.h"
31 #include "media-svc-media.h"
32
33 static GHashTable *table;
34 static GSList *column_list[DB_LIST_MAX];
35
36 typedef struct {
37         char *trigger_name;
38         char *view_name;
39         char *event_table;
40         char *action_table;
41 } table_info_s;
42
43 typedef struct {
44         char *name;
45         char *type;
46         char *option;
47         bool is_unique;
48         bool is_trigger;
49         bool is_view;
50 } column_info_s;
51
52 static void __add_table_info(const char *name,
53                                                         const char *trigger_name,
54                                                         const char *event_table,
55                                                         const char *action_table,
56                                                         const char *view_name)
57 {
58         table_info_s *tbl = NULL;
59
60         if (!STRING_VALID(name))
61                 return;
62
63         if (STRING_VALID(trigger_name)) {
64                 if(!STRING_VALID(event_table) || !STRING_VALID(action_table))
65                         return;
66         }
67
68         tbl = g_new0(table_info_s, 1);
69
70         if (STRING_VALID(trigger_name)) {
71                 tbl->trigger_name = g_strdup(trigger_name);
72                 tbl->event_table = g_strdup(event_table);
73                 tbl->action_table = g_strdup(action_table);
74         }
75
76         if (STRING_VALID(view_name))
77                 tbl->view_name = g_strdup(view_name);
78
79         g_hash_table_insert(table, (gpointer)name, (gpointer)tbl);
80 }
81
82 static void __add_column_info(GSList **slist,
83                                                                 const char *name,
84                                                                 const char *type,
85                                                                 const char *option,
86                                                                 bool is_unique,
87                                                                 bool is_trigger,
88                                                                 bool is_view)
89 {
90         column_info_s *col = g_new0(column_info_s, 1);
91
92         col->name = g_strdup(name);
93         col->type = g_strdup(type);
94         col->option = g_strdup(option);
95
96         col->is_unique = is_unique;
97         col->is_trigger = is_trigger;
98         col->is_view = is_view;
99
100         *slist = g_slist_append(*slist, col);
101 }
102
103 static int __create_playlist_view(uid_t uid)
104 {
105         int ret = MS_MEDIA_ERR_NONE;
106         GSList *iter = NULL;
107         column_info_s *col_ptr = NULL;
108         char *sql = NULL;
109         GString *table_query = g_string_new(NULL);
110         media_svc_retvm_if(!table_query, MS_MEDIA_ERR_INTERNAL, "g_string_new failed");
111
112         for (iter = column_list[DB_LIST_PLAYLIST]; iter; iter = g_slist_next(iter)) {
113                 col_ptr = iter->data;
114
115                 if (!col_ptr)
116                         continue;
117
118                 if (col_ptr->is_view) {
119                         if (table_query->len != 0) {
120                                 if (strncmp(col_ptr->name, DB_COLUMN_THUMBNAIL, strlen(DB_COLUMN_THUMBNAIL)) == 0)
121                                         g_string_append_printf(table_query, ", playlist.%s AS p_thumbnail_path", col_ptr->name);
122                                 else
123                                         g_string_append_printf(table_query, ", playlist.%s", col_ptr->name);
124                         } else {
125                                 g_string_append_printf(table_query, "playlist.%s", col_ptr->name);
126                         }
127                 }
128         }
129
130         for (iter = column_list[DB_LIST_PLAYLIST_MAP]; iter; iter = g_slist_next(iter)) {
131                 col_ptr = iter->data;
132
133                 if (!col_ptr)
134                         continue;
135
136                 if (col_ptr->is_view) {
137                         if (strncmp(col_ptr->name, DB_COLUMN_MAP_ID, strlen(DB_COLUMN_MAP_ID)) == 0)
138                                 g_string_append_printf(table_query, ", playlist_media_count IS NOT NULL AS playlist_media_count, playlist_map.%s AS pm_id", col_ptr->name);
139                         else
140                                 g_string_append_printf(table_query, ", playlist_map.%s", col_ptr->name);
141                 }
142         }
143
144         for (iter = column_list[DB_LIST_MEDIA]; iter; iter = g_slist_next(iter)) {
145                 col_ptr = iter->data;
146
147                 if (!col_ptr)
148                         continue;
149
150                 if (col_ptr->is_view)
151                         g_string_append_printf(table_query, ", media.%s", col_ptr->name);
152         }
153
154         sql = sqlite3_mprintf(DB_QUERY_VIEW_PLAYLIST, DB_VIEW_PLAYLIST, table_query->str);
155         g_string_free(table_query, TRUE);
156         ret = _media_svc_sql_query(sql, uid);
157         SQLITE3_SAFE_FREE(sql);
158
159         return ret;
160 }
161
162 static int __create_tag_view(uid_t uid)
163 {
164         int ret = MS_MEDIA_ERR_NONE;
165         GSList *iter = NULL;
166         column_info_s *col_ptr = NULL;
167         char *sql = NULL;
168         GString *table_query = g_string_new(NULL);
169         media_svc_retvm_if(!table_query, MS_MEDIA_ERR_INTERNAL, "g_string_new failed");
170
171         for (iter = column_list[DB_LIST_TAG]; iter; iter = g_slist_next(iter)) {
172                 col_ptr = iter->data;
173
174                 if (!col_ptr)
175                         continue;
176
177                 if (col_ptr->is_view) {
178                         if (table_query->len != 0)
179                                 g_string_append_printf(table_query, ", tag.%s", col_ptr->name);
180                         else
181                                 g_string_append_printf(table_query, "tag.%s", col_ptr->name);
182                 }
183         }
184
185         for (iter = column_list[DB_LIST_TAG_MAP]; iter; iter = g_slist_next(iter)) {
186                 col_ptr = iter->data;
187
188                 if (!col_ptr)
189                         continue;
190
191                 if (col_ptr->is_view) {
192                         if (strncmp(col_ptr->name, DB_COLUMN_MAP_ID, strlen(DB_COLUMN_MAP_ID)) == 0)
193                                 g_string_append_printf(table_query, ", tag_media_count IS NOT NULL AS tag_media_count, tag_map.%s AS tm_id", col_ptr->name);
194                         else
195                                 g_string_append_printf(table_query, ", tag_map.%s", col_ptr->name);
196                 }
197         }
198
199         for (iter = column_list[DB_LIST_MEDIA]; iter; iter = g_slist_next(iter)) {
200                 col_ptr = iter->data;
201
202                 if (!col_ptr)
203                         continue;
204
205                 if (col_ptr->is_view)
206                         g_string_append_printf(table_query, ", media.%s", col_ptr->name);
207         }
208
209         sql = sqlite3_mprintf(DB_QUERY_VIEW_TAG, DB_VIEW_TAG, table_query->str);
210         g_string_free(table_query, TRUE);
211         ret = _media_svc_sql_query(sql, uid);
212         SQLITE3_SAFE_FREE(sql);
213
214         return ret;
215 }
216
217 int _media_svc_make_table_query(const char *table_name, media_svc_table_slist_e list, uid_t uid)
218 {
219         int ret = MS_MEDIA_ERR_NONE;
220         GSList *iter = NULL;
221         table_info_s *tb = NULL;
222         column_info_s *col_ptr = NULL;
223         char *sql = NULL;
224         GString *table_query = g_string_new(NULL);
225         GString *trigger_query = g_string_new(NULL);
226         GString *unique_query = g_string_new(NULL);
227
228         if (!table_query || !trigger_query || !unique_query) {
229                 media_svc_error("g_string_new failed");
230                 ret = MS_MEDIA_ERR_INTERNAL;
231                 goto ERROR;
232         }
233
234         tb = g_hash_table_lookup(table, table_name);
235         if (tb == NULL) {
236                 media_svc_debug("lookup fail.. table name [%s] ", table_name);
237                 ret = MS_MEDIA_ERR_INTERNAL;
238                 goto ERROR;
239         }
240
241         for (iter = column_list[list]; iter; iter = g_slist_next(iter)) {
242                 col_ptr = iter->data;
243                 if (!col_ptr)
244                         continue;
245
246                 /*create table */
247                 if (col_ptr->option) {
248                         if (table_query->len != 0)
249                                 g_string_append_printf(table_query, ", %s %s %s", col_ptr->name, col_ptr->type, col_ptr->option);
250                         else
251                                 g_string_append_printf(table_query, "%s %s %s", col_ptr->name, col_ptr->type, col_ptr->option);
252                 } else {
253                         if (table_query->len != 0)
254                                 g_string_append_printf(table_query, ", %s %s", col_ptr->name, col_ptr->type);
255                         else
256                                 g_string_append_printf(table_query, "%s %s", col_ptr->name, col_ptr->type);
257                 }
258
259                 /*unique */
260                 if (col_ptr->is_unique) {
261                         if (unique_query->len != 0)
262                                 g_string_append_printf(unique_query, ", %s", col_ptr->name);
263                         else
264                                 g_string_append_printf(unique_query, "%s", col_ptr->name);
265                 }
266
267                 /*create trigger */
268                 if (col_ptr->is_trigger) {
269                         if (STRING_VALID(tb->trigger_name)) {
270                                 if (strncmp(table_name, DB_TABLE_ALBUM, strlen(DB_TABLE_ALBUM)) == 0) {
271                                         g_string_append_printf(trigger_query, DB_QUERY_TRIGGER_WITH_COUNT,
272                                                                                         tb->trigger_name, tb->event_table, tb->action_table, tb->event_table,
273                                                                                         col_ptr->name, col_ptr->name, col_ptr->name, col_ptr->name);
274                                 } else {
275                                         g_string_append_printf(trigger_query, DB_QUERY_TRIGGER,
276                                                                                         tb->trigger_name, tb->event_table, tb->action_table,
277                                                                                         col_ptr->name, col_ptr->name);
278                                 }
279                         } else {
280                                 media_svc_error("invalid trigger name");
281                         }
282                 }
283         }
284
285         /*send queries */
286         if (unique_query->len > 0)
287                 sql = sqlite3_mprintf(DB_QUERY_TABLE_WITH_UNIQUE, table_name, table_query->str, unique_query->str);
288         else
289                 sql = sqlite3_mprintf(DB_QUERY_TABLE, table_name, table_query->str);
290
291         ret = _media_svc_sql_query(sql, uid);
292         SQLITE3_SAFE_FREE(sql);
293         if (ret != MS_MEDIA_ERR_NONE)
294                 goto ERROR;
295
296         if (trigger_query->len > 0) {
297                 ret = _media_svc_sql_query(trigger_query->str, uid);
298                 if (ret != MS_MEDIA_ERR_NONE)
299                         goto ERROR;
300         }
301
302         /*create view */
303         if (strncmp(table_name, DB_TABLE_PLAYLIST, strlen(DB_TABLE_PLAYLIST)) == 0)
304                 ret = __create_playlist_view(uid);
305         else if (strncmp(table_name, DB_TABLE_TAG, strlen(DB_TABLE_TAG)) == 0)
306                 ret = __create_tag_view(uid);
307
308 ERROR:
309         if (trigger_query)
310                 g_string_free(trigger_query, TRUE);
311         if (unique_query)
312                 g_string_free(unique_query, TRUE);
313         if (table_query)
314                 g_string_free(table_query, TRUE);
315
316         return ret;
317 }
318
319 static void __media_svc_table_free(gpointer data)
320 {
321         table_info_s *tb = (table_info_s *) data;
322
323         g_free(tb->trigger_name);
324         g_free(tb->view_name);
325         g_free(tb->event_table);
326         g_free(tb->action_table);
327         g_free(tb);
328 }
329
330 static void __media_svc_column_free(gpointer data)
331 {
332         column_info_s *col = (column_info_s *) data;
333
334         g_free(col->name);
335         g_free(col->type);
336         g_free(col->option);
337         g_free(col);
338 }
339
340 int _media_svc_init_table_query(void)
341 {
342         int ret = MS_MEDIA_ERR_NONE;
343
344         /*variable initialize.. */
345         table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __media_svc_table_free);
346
347         /*table specification.. (table_name, trigger name, event table, action table, view name) */
348         __add_table_info(DB_TABLE_MEDIA, NULL, NULL, NULL, NULL);
349         __add_table_info(DB_TABLE_FOLDER, NULL, NULL, NULL, NULL);
350         __add_table_info(DB_TABLE_PLAYLIST_MAP, DB_TRIGGER_PLAYLIST_MAP, DB_TABLE_MEDIA, DB_TABLE_PLAYLIST_MAP, NULL);
351         __add_table_info(DB_TABLE_PLAYLIST, DB_TRIGGER_PLAYLIST_MAP1, DB_TABLE_PLAYLIST, DB_TABLE_PLAYLIST_MAP, DB_VIEW_PLAYLIST);
352         __add_table_info(DB_TABLE_ALBUM, DB_TRIGGER_ALBUM, DB_TABLE_MEDIA, DB_TABLE_ALBUM, NULL);
353         __add_table_info(DB_TABLE_TAG_MAP, DB_TRIGGER_TAG_MAP, DB_TABLE_MEDIA, DB_TABLE_TAG_MAP, NULL);
354         __add_table_info(DB_TABLE_TAG, DB_TRIGGER_TAG_MAP1, DB_TABLE_TAG, DB_TABLE_TAG_MAP, DB_VIEW_TAG);
355         __add_table_info(DB_TABLE_BOOKMARK, DB_TRIGGER_BOOKMARK, DB_TABLE_MEDIA, DB_TABLE_BOOKMARK, NULL);
356         __add_table_info(DB_TABLE_STORAGE, NULL, NULL, NULL, NULL);
357         __add_table_info(DB_TABLE_FACE_SCAN_LIST, DB_TRIGGER_FACE_SCAN_LIST, DB_TABLE_MEDIA, DB_TABLE_FACE_SCAN_LIST, NULL);
358         __add_table_info(DB_TABLE_FACE, DB_TRIGGER_FACE, DB_TABLE_FACE_SCAN_LIST, DB_TABLE_FACE, NULL);
359
360         /*insert column info.. */
361         /*media*/
362         __add_column_info(&column_list[DB_LIST_MEDIA], "media_id", DB_TYPE_TEXT, "PRIMARY KEY", false, false, true);
363         __add_column_info(&column_list[DB_LIST_MEDIA], "media_path", DB_TYPE_TEXT, "NOT NULL UNIQUE", false, false, true);
364         __add_column_info(&column_list[DB_LIST_MEDIA], "media_display_name", DB_TYPE_TEXT, "NOT NULL", false, false, true);
365         __add_column_info(&column_list[DB_LIST_MEDIA], "media_type", DB_TYPE_INT, NULL, false, false, true);
366         __add_column_info(&column_list[DB_LIST_MEDIA], "media_mime_type", DB_TYPE_TEXT, NULL, false, false, true);
367         __add_column_info(&column_list[DB_LIST_MEDIA], "media_size", DB_TYPE_INT, "DEFAULT 0", false, false, true);
368         __add_column_info(&column_list[DB_LIST_MEDIA], "media_added_time", DB_TYPE_INT, "DEFAULT 0", false, false, true);
369         __add_column_info(&column_list[DB_LIST_MEDIA], "media_modified_time", DB_TYPE_INT, "DEFAULT 0", false, false, true);
370         __add_column_info(&column_list[DB_LIST_MEDIA], "folder_id", DB_TYPE_TEXT, "NOT NULL", false, false, false);
371         __add_column_info(&column_list[DB_LIST_MEDIA], "media_thumbnail_path", DB_TYPE_TEXT, NULL, false, false, true);
372         __add_column_info(&column_list[DB_LIST_MEDIA], "media_title", DB_TYPE_TEXT, NULL, false, false, true);
373         __add_column_info(&column_list[DB_LIST_MEDIA], "album_id", DB_TYPE_INT, "DEFAULT 0", false, false, false);
374         __add_column_info(&column_list[DB_LIST_MEDIA], "media_album", DB_TYPE_TEXT, NULL, false, false, true);
375         __add_column_info(&column_list[DB_LIST_MEDIA], "media_artist", DB_TYPE_TEXT, NULL, false, false, true);
376         __add_column_info(&column_list[DB_LIST_MEDIA], "media_album_artist", DB_TYPE_TEXT, NULL, false, false, true);
377         __add_column_info(&column_list[DB_LIST_MEDIA], "media_genre", DB_TYPE_TEXT, NULL, false, false, true);
378         __add_column_info(&column_list[DB_LIST_MEDIA], "media_composer", DB_TYPE_TEXT, NULL, false, false, true);
379         __add_column_info(&column_list[DB_LIST_MEDIA], "media_year", DB_TYPE_TEXT, NULL, false, false, true);
380         __add_column_info(&column_list[DB_LIST_MEDIA], "media_recorded_date", DB_TYPE_TEXT, NULL, false, false, true);
381         __add_column_info(&column_list[DB_LIST_MEDIA], "media_copyright", DB_TYPE_TEXT, NULL, false, false, true);
382         __add_column_info(&column_list[DB_LIST_MEDIA], "media_track_num", DB_TYPE_TEXT, NULL, false, false, true);
383         __add_column_info(&column_list[DB_LIST_MEDIA], "media_description", DB_TYPE_TEXT, NULL, false, false, true);
384         __add_column_info(&column_list[DB_LIST_MEDIA], "media_bitrate", DB_TYPE_INT, "DEFAULT -1", false, false, true);
385         __add_column_info(&column_list[DB_LIST_MEDIA], "media_bitpersample", DB_TYPE_INT, "DEFAULT 0", false, false, true);
386         __add_column_info(&column_list[DB_LIST_MEDIA], "media_samplerate", DB_TYPE_INT, "DEFAULT -1", false, false, true);
387         __add_column_info(&column_list[DB_LIST_MEDIA], "media_channel", DB_TYPE_INT, "DEFAULT -1", false, false, true);
388         __add_column_info(&column_list[DB_LIST_MEDIA], "media_duration", DB_TYPE_INT, "DEFAULT -1", false, false, true);
389         __add_column_info(&column_list[DB_LIST_MEDIA], "media_longitude", DB_TYPE_DOUBLE, "DEFAULT 0", false, false, true);
390         __add_column_info(&column_list[DB_LIST_MEDIA], "media_latitude", DB_TYPE_DOUBLE, "DEFAULT 0", false, false, true);
391         __add_column_info(&column_list[DB_LIST_MEDIA], "media_altitude", DB_TYPE_DOUBLE, "DEFAULT 0", false, false, true);
392         __add_column_info(&column_list[DB_LIST_MEDIA], "exposure_time", DB_TYPE_TEXT, NULL, false, false, true);
393         __add_column_info(&column_list[DB_LIST_MEDIA], "fnumber", DB_TYPE_DOUBLE, "DEFAULT 0", false, false, true);
394         __add_column_info(&column_list[DB_LIST_MEDIA], "iso", DB_TYPE_INT, "DEFAULT -1", false, false, true);
395         __add_column_info(&column_list[DB_LIST_MEDIA], "model", DB_TYPE_TEXT, NULL, false, false, true);
396         __add_column_info(&column_list[DB_LIST_MEDIA], "media_width", DB_TYPE_INT, "DEFAULT -1", false, false, true);
397         __add_column_info(&column_list[DB_LIST_MEDIA], "media_height", DB_TYPE_INT, "DEFAULT -1", false, false, true);
398         __add_column_info(&column_list[DB_LIST_MEDIA], "media_datetaken", DB_TYPE_TEXT, NULL, false, false, true);
399         __add_column_info(&column_list[DB_LIST_MEDIA], "media_orientation", DB_TYPE_INT, "DEFAULT -1", false, false, true);
400         __add_column_info(&column_list[DB_LIST_MEDIA], "media_rating", DB_TYPE_INT, "DEFAULT 0", false, false, true);
401         __add_column_info(&column_list[DB_LIST_MEDIA], "media_favourite", DB_TYPE_INT, "DEFAULT 0", false, false, true);
402         __add_column_info(&column_list[DB_LIST_MEDIA], "media_is_drm", DB_TYPE_INT, "DEFAULT 0", false, false, true);
403         __add_column_info(&column_list[DB_LIST_MEDIA], "media_storage_type", DB_TYPE_INT, NULL, false, false, true);
404         __add_column_info(&column_list[DB_LIST_MEDIA], "media_timeline", DB_TYPE_INT, "DEFAULT 0", false, false, true);
405         __add_column_info(&column_list[DB_LIST_MEDIA], "media_file_name_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
406         __add_column_info(&column_list[DB_LIST_MEDIA], "media_title_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
407         __add_column_info(&column_list[DB_LIST_MEDIA], "media_album_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
408         __add_column_info(&column_list[DB_LIST_MEDIA], "media_artist_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
409         __add_column_info(&column_list[DB_LIST_MEDIA], "media_album_artist_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
410         __add_column_info(&column_list[DB_LIST_MEDIA], "media_genre_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
411         __add_column_info(&column_list[DB_LIST_MEDIA], "media_composer_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
412         __add_column_info(&column_list[DB_LIST_MEDIA], "media_copyright_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
413         __add_column_info(&column_list[DB_LIST_MEDIA], "media_description_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
414         __add_column_info(&column_list[DB_LIST_MEDIA], "storage_uuid", DB_TYPE_TEXT, NULL, false, false, true);
415         __add_column_info(&column_list[DB_LIST_MEDIA], "validity", DB_TYPE_INT, "DEFAULT 1", false, false, false);
416         __add_column_info(&column_list[DB_LIST_MEDIA], "media_360", DB_TYPE_INT, "DEFAULT 0", false, false, true);
417
418         /*folder*/
419         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_id", DB_TYPE_TEXT, "PRIMARY KEY", false, false, false);
420         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_path", DB_TYPE_TEXT, "NOT NULL", true, false, false);
421         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_name", DB_TYPE_TEXT, "NOT NULL", false, false, false);
422         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_modified_time", DB_TYPE_INT, "DEFAULT 0", false, false, false);
423         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_name_pinyin", DB_TYPE_TEXT, NULL, false, false, false);
424         __add_column_info(&column_list[DB_LIST_FOLDER], "folder_storage_type", DB_TYPE_INT, NULL, false, false, false);
425         __add_column_info(&column_list[DB_LIST_FOLDER], "storage_uuid", DB_TYPE_TEXT, NULL, true, false, false);
426         __add_column_info(&column_list[DB_LIST_FOLDER], "validity", DB_TYPE_INT, "DEFAULT 1", false, false, false);
427
428         /*playlist_map*/
429         __add_column_info(&column_list[DB_LIST_PLAYLIST_MAP], "_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, false, true);
430         __add_column_info(&column_list[DB_LIST_PLAYLIST_MAP], "playlist_id", DB_TYPE_INT, "NOT NULL", false, false, false);
431         __add_column_info(&column_list[DB_LIST_PLAYLIST_MAP], "media_id", DB_TYPE_TEXT, "NOT NULL", false, true, false);
432         __add_column_info(&column_list[DB_LIST_PLAYLIST_MAP], "playlist_member_order", DB_TYPE_INT, "NOT NULL", false, false, true);
433
434         /*playlist*/
435         __add_column_info(&column_list[DB_LIST_PLAYLIST], "playlist_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, true, true);
436         __add_column_info(&column_list[DB_LIST_PLAYLIST], "playlist_name", DB_TYPE_TEXT, "NOT NULL UNIQUE", false, false, true);
437         __add_column_info(&column_list[DB_LIST_PLAYLIST], "thumbnail_path", DB_TYPE_TEXT, NULL, false, false, true);
438
439         /*album*/
440         __add_column_info(&column_list[DB_LIST_ALBUM], "album_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, true, false);
441         __add_column_info(&column_list[DB_LIST_ALBUM], "name", DB_TYPE_TEXT, "NOT NULL", false, false, false);
442         __add_column_info(&column_list[DB_LIST_ALBUM], "artist", DB_TYPE_TEXT, NULL, false, false, false);
443         __add_column_info(&column_list[DB_LIST_ALBUM], "album_art", DB_TYPE_TEXT, NULL, false, false, false);
444
445         /*tag_map*/
446         __add_column_info(&column_list[DB_LIST_TAG_MAP], "_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, false, true);
447         __add_column_info(&column_list[DB_LIST_TAG_MAP], "tag_id", DB_TYPE_INT, "NOT NULL", true, false, false);
448         __add_column_info(&column_list[DB_LIST_TAG_MAP], "media_id", DB_TYPE_TEXT, "NOT NULL", true, true, false);
449
450         /*tag*/
451         __add_column_info(&column_list[DB_LIST_TAG], "tag_id ", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, true, true);
452         __add_column_info(&column_list[DB_LIST_TAG], "tag_name", DB_TYPE_TEXT, "NOT NULL UNIQUE", false, false, true);
453
454         /*bookmark*/
455         __add_column_info(&column_list[DB_LIST_BOOKMARK], "bookmark_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, false, false);
456         __add_column_info(&column_list[DB_LIST_BOOKMARK], "media_id", DB_TYPE_TEXT, "NOT NULL", true, true, false);
457         __add_column_info(&column_list[DB_LIST_BOOKMARK], "bookmark_marked_time", DB_TYPE_INT, "DEFAULT 0", true, false, false);
458         __add_column_info(&column_list[DB_LIST_BOOKMARK], "bookmark_thumbnail_path", DB_TYPE_TEXT, NULL, false, false, false);
459         __add_column_info(&column_list[DB_LIST_BOOKMARK], "bookmark_name", DB_TYPE_TEXT, NULL, false, false, false);
460
461         /*storage*/
462         __add_column_info(&column_list[DB_LIST_STORAGE], "storage_id", DB_TYPE_TEXT, "PRIMARY KEY", false, false, false);
463         __add_column_info(&column_list[DB_LIST_STORAGE], "storage_path", DB_TYPE_TEXT, "NOT NULL", false, false, false);
464         __add_column_info(&column_list[DB_LIST_STORAGE], "storage_type", DB_TYPE_INT, "DEFAULT 0", false, false, false);
465         __add_column_info(&column_list[DB_LIST_STORAGE], "validity", DB_TYPE_INT, "DEFAULT 1", false, false, false);
466
467         /*face scan list*/
468         __add_column_info(&column_list[DB_LIST_FACE_SCAN_LIST], "media_id", DB_TYPE_TEXT, "NOT NULL UNIQUE", false, true, false);
469         __add_column_info(&column_list[DB_LIST_FACE_SCAN_LIST], "modified_time", DB_TYPE_INT, "DEFAULT 0", false, false, false);
470
471         /*face*/
472         __add_column_info(&column_list[DB_LIST_FACE], "media_face_id", DB_TYPE_INT, "PRIMARY KEY AUTOINCREMENT", false, false, false);
473         __add_column_info(&column_list[DB_LIST_FACE], "media_id", DB_TYPE_TEXT, "NOT NULL", true, true, false);
474         __add_column_info(&column_list[DB_LIST_FACE], "face_rect_x", DB_TYPE_INT, "DEFAULT 0", true, false, false);
475         __add_column_info(&column_list[DB_LIST_FACE], "face_rect_y", DB_TYPE_INT, "DEFAULT 0", true, false, false);
476         __add_column_info(&column_list[DB_LIST_FACE], "face_rect_w", DB_TYPE_INT, "DEFAULT 0", true, false, false);
477         __add_column_info(&column_list[DB_LIST_FACE], "face_rect_h", DB_TYPE_INT, "DEFAULT 0", true, false, false);
478         __add_column_info(&column_list[DB_LIST_FACE], "face_orientation", DB_TYPE_INT, "DEFAULT 0", false, false, false);
479         __add_column_info(&column_list[DB_LIST_FACE], "media_face_tag", DB_TYPE_TEXT, NULL, false, false, false);
480
481         return ret;
482 }
483
484 void _media_svc_destroy_table_query(void)
485 {
486         int i = 0;
487
488         /* Table Free */
489         g_hash_table_destroy(table);
490         table = NULL;
491
492         /* Column Free */
493         for (i = 0; i < DB_LIST_MAX; i++) {
494                 g_slist_free_full(column_list[i], __media_svc_column_free);
495                 column_list[i] = NULL;
496         }
497 }
498
499 int _media_svc_sql_query(const char *sql_str, uid_t uid)
500 {
501         return media_db_request_update_db(sql_str, uid);
502 }
503
504 #define MAX_RETRY 9
505 #define SLEEP_TIME 1000 * 1000
506 static int __media_svc_query_direct(sqlite3 *handle, const char *query, uid_t uid)
507 {
508         int ret = MS_MEDIA_ERR_NONE;
509         char *zErrMsg = NULL;
510         int retry_count = 0;
511
512 EXEC_RETRY:
513         ret = sqlite3_exec(handle, query, NULL, NULL, &zErrMsg);
514         if (SQLITE_OK != ret) {
515                 media_svc_sec_error("Error[%s],Query[%s]", zErrMsg, query);
516                 SQLITE3_SAFE_FREE(zErrMsg);
517                 if (ret == SQLITE_BUSY) {
518                         ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
519                 } else if (ret == SQLITE_CONSTRAINT) {
520                         ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
521                 } else if (ret == SQLITE_FULL) {
522                         ret = MS_MEDIA_ERR_DB_FULL_FAIL;
523                 } else if (ret == SQLITE_LOCKED) {
524                         if (retry_count < MAX_RETRY) {
525                                 media_svc_error("Locked retry[%d]", retry_count);
526                                 retry_count++;
527                                 usleep(SLEEP_TIME);
528                                 goto EXEC_RETRY;
529                         }
530                         ret = MS_MEDIA_ERR_DB_INTERNAL;
531                 } else {
532                         ret = MS_MEDIA_ERR_DB_INTERNAL;
533                 }
534         }
535
536         return ret;
537 }
538
539 int _media_svc_sql_query_direct(const char *sql_str, uid_t uid)
540 {
541         int ret = MS_MEDIA_ERR_NONE;
542         sqlite3 *handle = NULL;
543
544         ret = media_db_connect(&handle, uid, true);
545         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "DB connection failed");
546         ret = __media_svc_query_direct(handle, sql_str, uid);
547         media_db_disconnect(handle);
548
549         return ret;
550 }
551
552 int _media_svc_check_table_exist(sqlite3 *db_handle, bool *exist)
553 {
554         int ret = MS_MEDIA_ERR_NONE;
555         sqlite3_stmt *sql_stmt = NULL;
556         char *sql = sqlite3_mprintf("SELECT name FROM sqlite_master WHERE type='table' AND name=%Q;", DB_TABLE_MEDIA);
557
558         ret = _media_svc_sql_prepare_to_step_simple(db_handle, sql, &sql_stmt);
559         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "_media_svc_sql_prepare_to_step_simple failed");
560
561         if (sqlite3_step(sql_stmt) != SQLITE_ROW) {
562                 media_svc_debug("Need to create table");
563                 *exist = false;
564         } else {
565                 media_svc_debug("Already exists");
566                 *exist = true;
567         }
568
569         SQLITE3_FINALIZE(sql_stmt);
570
571         return MS_MEDIA_ERR_NONE;
572 }
573
574 int _media_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt **stmt)
575 {
576         int err = -1;
577
578         media_svc_retvm_if(sql_str == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "invalid query");
579
580         if (handle == NULL) {
581                 media_svc_error("handle is NULL");
582                 sqlite3_free((char *)sql_str);
583                 return MS_MEDIA_ERR_INVALID_PARAMETER;
584         }
585
586         media_svc_sec_debug("Query[%s]", sql_str);
587
588         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
589         sqlite3_free((char *)sql_str);
590
591         if (err != SQLITE_OK) {
592                 media_svc_error("prepare error %d[%s]", err, sqlite3_errmsg(handle));
593                 if (err == SQLITE_CORRUPT)
594                         return MS_MEDIA_ERR_DB_CORRUPT;
595
596                 return MS_MEDIA_ERR_DB_INTERNAL;
597         }
598
599         err = sqlite3_step(*stmt);
600         if (err != SQLITE_ROW) {
601                 media_svc_debug("No record");
602                 SQLITE3_FINALIZE(*stmt);
603                 return MS_MEDIA_ERR_DB_NO_RECORD;
604         }
605
606         return MS_MEDIA_ERR_NONE;
607 }
608
609 int _media_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt **stmt)
610 {
611         int err = -1;
612
613         media_svc_retvm_if(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "handle is NULL");
614
615         media_svc_sec_debug("Query[%s]", sql_str);
616
617         if (!STRING_VALID(sql_str)) {
618                 media_svc_error("invalid query");
619                 return MS_MEDIA_ERR_INVALID_PARAMETER;
620         }
621
622         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
623         sqlite3_free((char *)sql_str);
624
625         if (err != SQLITE_OK) {
626                 media_svc_error("prepare error %d[%s]", err, sqlite3_errmsg(handle));
627                 if (err == SQLITE_CORRUPT)
628                         return MS_MEDIA_ERR_DB_CORRUPT;
629
630                 return MS_MEDIA_ERR_DB_INTERNAL;
631         }
632
633         return MS_MEDIA_ERR_NONE;
634 }
635
636 int _media_svc_sql_query_list(GList **query_list, uid_t uid)
637 {
638         int ret = MS_MEDIA_ERR_NONE;
639         int idx = 0;
640         int length = g_list_length(*query_list);
641         char *sql = NULL;
642         char query_bundle[MEDIA_SVC_QUERY_LEN_MAX] = {0, };
643         unsigned int query_len = 0;
644         unsigned int total_len = 0;
645
646         media_svc_debug("query list length : [%d]", length);
647
648         memset(query_bundle, 0, sizeof(query_bundle));
649
650         for (idx = 0; idx < length; idx++) {
651                 sql = (char *)g_list_nth_data(*query_list, idx);
652                 if (STRING_VALID(sql)) {
653                         query_len = strlen(sql);
654
655                         if (query_len >= (sizeof(query_bundle) - 1)) {
656                                 media_svc_error("NEED TO CHECK FILE : A single query size exceeds 8k [%u]", query_len);
657                                 SQLITE3_SAFE_FREE(sql);
658                                 continue;
659                         }
660
661                         if ((total_len + query_len) >= (sizeof(query_bundle) - 1)) {
662                                 ret = media_db_request_update_db(query_bundle, uid);
663                                 if (ret != MS_MEDIA_ERR_NONE)
664                                         media_svc_error("media_db_request_update_db failed : %d", ret);
665
666                                 memset(query_bundle, 0, sizeof(query_bundle));
667                                 total_len = 0;
668                                 /* NEED TO CHECK : If a single query size is over 8K, drop it. */
669                                 /*                              Consider inserting the basic information without metadata */
670                                 /* Refer : SQLITE3 spec In Tizen 3.0 */
671                                 /* Single query limit size = 1 billion bytes(1GiB) */
672                                 /* DB limit size = 1 billion bytes(1GiB) */
673                                 /* column limit = 2000 */
674                         }
675
676                         SAFE_STRLCAT(query_bundle, sql, sizeof(query_bundle));
677                         total_len += query_len;
678
679                         SQLITE3_SAFE_FREE(sql);
680                 }
681         }
682
683         if (total_len > 0) {
684                 ret = media_db_request_update_db(query_bundle, uid);
685                 if (ret != MS_MEDIA_ERR_NONE)
686                         media_svc_error("media_db_request_update_db failed : %d", ret);
687
688                 memset(query_bundle, 0, sizeof(query_bundle));
689                 total_len = 0;
690         }
691
692         _media_svc_sql_query_release(query_list);
693
694         return MS_MEDIA_ERR_NONE;
695 }
696
697 int _media_svc_sql_query_list_direct(GList **query_list, uid_t uid)
698 {
699         int ret = MS_MEDIA_ERR_NONE;
700         int idx = 0;
701         int length = g_list_length(*query_list);
702         char *sql = NULL;
703         char *zErrMsg = NULL;
704         sqlite3 *handle = NULL;
705         bool with_transaction = true;
706
707         media_svc_debug("query list length[%d]", length);
708         if (length == 0)
709                 goto ZERO_LEN;
710
711         ret = media_db_connect(&handle, uid, true);
712         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "DB connection failed");
713
714         ret = sqlite3_exec(handle, "BEGIN;", NULL, NULL, &zErrMsg);
715         if (SQLITE_OK != ret) {
716                 media_svc_sec_error("Transaction failed[%s]. Try an individual insert.", zErrMsg);
717                 SQLITE3_SAFE_FREE(zErrMsg);
718                 with_transaction = false;
719         }
720
721         for (idx = 0; idx < length; idx++) {
722                 sql = (char *)g_list_nth_data(*query_list, idx);
723                 if (STRING_VALID(sql)) {
724                         ret = __media_svc_query_direct(handle, sql, uid);
725                         if (ret != MS_MEDIA_ERR_NONE)
726                                 media_svc_debug("_media_svc_query_direct failed[%s]", sql);
727
728                         SQLITE3_SAFE_FREE(sql);
729                 }
730         }
731
732         if (with_transaction) {
733                 ret = sqlite3_exec(handle, "COMMIT;", NULL, NULL, &zErrMsg);
734                 if (SQLITE_OK != ret) {
735                         media_svc_sec_error("Commit failed[%s]", zErrMsg);
736                         SQLITE3_SAFE_FREE(zErrMsg);
737                         media_db_disconnect(handle);
738                         _media_svc_sql_query_release(query_list);
739                         return MS_MEDIA_ERR_DB_INTERNAL;
740                 }
741         }
742
743         media_db_disconnect(handle);
744
745 ZERO_LEN:
746         _media_svc_sql_query_release(query_list);
747
748         return MS_MEDIA_ERR_NONE;
749 }
750
751 void _media_svc_sql_query_add(GList **query_list, char **query)
752 {
753         *query_list = g_list_append(*query_list, *query);
754 }
755
756 void _media_svc_sql_query_release(GList **query_list)
757 {
758         if (*query_list) {
759                 g_list_free(*query_list);
760                 *query_list = NULL;
761         }
762 }