1eb3d06f4501bc2f31872eccb8db125b7c02e77f
[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
491         /* Column Free */
492         for (i = 0; i < DB_LIST_MAX; i++)
493                 g_slist_free_full(column_list[i], __media_svc_column_free);
494 }
495
496 int _media_svc_sql_query(const char *sql_str, uid_t uid)
497 {
498         return media_db_request_update_db(sql_str, uid);
499 }
500
501 #define MAX_RETRY 9
502 #define SLEEP_TIME 1000 * 1000
503 static int __media_svc_query_direct(sqlite3 *handle, const char *query, uid_t uid)
504 {
505         int ret = MS_MEDIA_ERR_NONE;
506         char *zErrMsg = NULL;
507         int retry_count = 0;
508
509 EXEC_RETRY:
510         ret = sqlite3_exec(handle, query, NULL, NULL, &zErrMsg);
511         if (SQLITE_OK != ret) {
512                 media_svc_sec_error("Error[%s],Query[%s]", zErrMsg, query);
513                 SQLITE3_SAFE_FREE(zErrMsg);
514                 if (ret == SQLITE_BUSY) {
515                         ret = MS_MEDIA_ERR_DB_BUSY_FAIL;
516                 } else if (ret == SQLITE_CONSTRAINT) {
517                         ret = MS_MEDIA_ERR_DB_CONSTRAINT_FAIL;
518                 } else if (ret == SQLITE_FULL) {
519                         ret = MS_MEDIA_ERR_DB_FULL_FAIL;
520                 } else if (ret == SQLITE_LOCKED) {
521                         if (retry_count < MAX_RETRY) {
522                                 media_svc_error("Locked retry[%d]", retry_count);
523                                 retry_count++;
524                                 usleep(SLEEP_TIME);
525                                 goto EXEC_RETRY;
526                         }
527                         ret = MS_MEDIA_ERR_DB_INTERNAL;
528                 } else {
529                         ret = MS_MEDIA_ERR_DB_INTERNAL;
530                 }
531         }
532
533         return ret;
534 }
535
536 int _media_svc_sql_query_direct(const char *sql_str, uid_t uid)
537 {
538         int ret = MS_MEDIA_ERR_NONE;
539         sqlite3 *handle = NULL;
540
541         ret = media_db_connect(&handle, uid, true);
542         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "DB connection failed");
543         ret = __media_svc_query_direct(handle, sql_str, uid);
544         media_db_disconnect(handle);
545
546         return ret;
547 }
548
549 int _media_svc_check_table_exist(sqlite3 *db_handle, bool *exist)
550 {
551         int ret = MS_MEDIA_ERR_NONE;
552         sqlite3_stmt *sql_stmt = NULL;
553         char *sql = sqlite3_mprintf("SELECT name FROM sqlite_master WHERE type='table' AND name=%Q;", DB_TABLE_MEDIA);
554
555         ret = _media_svc_sql_prepare_to_step_simple(db_handle, sql, &sql_stmt);
556         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "_media_svc_sql_prepare_to_step_simple failed");
557
558         if (sqlite3_step(sql_stmt) != SQLITE_ROW) {
559                 media_svc_debug("Need to create table");
560                 *exist = false;
561         } else {
562                 media_svc_debug("Already exists");
563                 *exist = true;
564         }
565
566         SQLITE3_FINALIZE(sql_stmt);
567
568         return MS_MEDIA_ERR_NONE;
569 }
570
571 int _media_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt **stmt)
572 {
573         int err = -1;
574
575         media_svc_retvm_if(sql_str == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "invalid query");
576
577         if (handle == NULL) {
578                 media_svc_error("handle is NULL");
579                 sqlite3_free((char *)sql_str);
580                 return MS_MEDIA_ERR_INVALID_PARAMETER;
581         }
582
583         media_svc_sec_debug("Query[%s]", sql_str);
584
585         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
586         sqlite3_free((char *)sql_str);
587
588         if (err != SQLITE_OK) {
589                 media_svc_error("prepare error %d[%s]", err, sqlite3_errmsg(handle));
590                 if (err == SQLITE_CORRUPT)
591                         return MS_MEDIA_ERR_DB_CORRUPT;
592
593                 return MS_MEDIA_ERR_DB_INTERNAL;
594         }
595
596         err = sqlite3_step(*stmt);
597         if (err != SQLITE_ROW) {
598                 media_svc_debug("No record");
599                 SQLITE3_FINALIZE(*stmt);
600                 return MS_MEDIA_ERR_DB_NO_RECORD;
601         }
602
603         return MS_MEDIA_ERR_NONE;
604 }
605
606 int _media_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt **stmt)
607 {
608         int err = -1;
609
610         media_svc_retvm_if(handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "handle is NULL");
611
612         media_svc_sec_debug("Query[%s]", sql_str);
613
614         if (!STRING_VALID(sql_str)) {
615                 media_svc_error("invalid query");
616                 return MS_MEDIA_ERR_INVALID_PARAMETER;
617         }
618
619         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
620         sqlite3_free((char *)sql_str);
621
622         if (err != SQLITE_OK) {
623                 media_svc_error("prepare error %d[%s]", err, sqlite3_errmsg(handle));
624                 if (err == SQLITE_CORRUPT)
625                         return MS_MEDIA_ERR_DB_CORRUPT;
626
627                 return MS_MEDIA_ERR_DB_INTERNAL;
628         }
629
630         return MS_MEDIA_ERR_NONE;
631 }
632
633 int _media_svc_sql_query_list(GList **query_list, uid_t uid)
634 {
635         int ret = MS_MEDIA_ERR_NONE;
636         int idx = 0;
637         int length = g_list_length(*query_list);
638         char *sql = NULL;
639         char query_bundle[MEDIA_SVC_QUERY_LEN_MAX] = {0, };
640         unsigned int query_len = 0;
641         unsigned int total_len = 0;
642
643         media_svc_debug("query list length : [%d]", length);
644
645         memset(query_bundle, 0, sizeof(query_bundle));
646
647         for (idx = 0; idx < length; idx++) {
648                 sql = (char *)g_list_nth_data(*query_list, idx);
649                 if (STRING_VALID(sql)) {
650                         query_len = strlen(sql);
651
652                         if (query_len >= (sizeof(query_bundle) - 1)) {
653                                 media_svc_error("NEED TO CHECK FILE : A single query size exceeds 8k [%u]", query_len);
654                                 SQLITE3_SAFE_FREE(sql);
655                                 continue;
656                         }
657
658                         if ((total_len + query_len) >= (sizeof(query_bundle) - 1)) {
659                                 ret = media_db_request_update_db(query_bundle, uid);
660                                 if (ret != MS_MEDIA_ERR_NONE)
661                                         media_svc_error("media_db_request_update_db failed : %d", ret);
662
663                                 memset(query_bundle, 0, sizeof(query_bundle));
664                                 total_len = 0;
665                                 /* NEED TO CHECK : If a single query size is over 8K, drop it. */
666                                 /*                              Consider inserting the basic information without metadata */
667                                 /* Refer : SQLITE3 spec In Tizen 3.0 */
668                                 /* Single query limit size = 1 billion bytes(1GiB) */
669                                 /* DB limit size = 1 billion bytes(1GiB) */
670                                 /* column limit = 2000 */
671                         }
672
673                         SAFE_STRLCAT(query_bundle, sql, sizeof(query_bundle));
674                         total_len += query_len;
675
676                         SQLITE3_SAFE_FREE(sql);
677                 }
678         }
679
680         if (total_len > 0) {
681                 ret = media_db_request_update_db(query_bundle, uid);
682                 if (ret != MS_MEDIA_ERR_NONE)
683                         media_svc_error("media_db_request_update_db failed : %d", ret);
684
685                 memset(query_bundle, 0, sizeof(query_bundle));
686                 total_len = 0;
687         }
688
689         _media_svc_sql_query_release(query_list);
690
691         return MS_MEDIA_ERR_NONE;
692 }
693
694 int _media_svc_sql_query_list_direct(GList **query_list, uid_t uid)
695 {
696         int ret = MS_MEDIA_ERR_NONE;
697         int idx = 0;
698         int length = g_list_length(*query_list);
699         char *sql = NULL;
700         char *zErrMsg = NULL;
701         sqlite3 *handle = NULL;
702         bool with_transaction = true;
703
704         media_svc_debug("query list length[%d]", length);
705         if (length == 0)
706                 goto ZERO_LEN;
707
708         ret = media_db_connect(&handle, uid, true);
709         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "DB connection failed");
710
711         ret = sqlite3_exec(handle, "BEGIN;", NULL, NULL, &zErrMsg);
712         if (SQLITE_OK != ret) {
713                 media_svc_sec_error("Transaction failed[%s]. Try an individual insert.", zErrMsg);
714                 SQLITE3_SAFE_FREE(zErrMsg);
715                 with_transaction = false;
716         }
717
718         for (idx = 0; idx < length; idx++) {
719                 sql = (char *)g_list_nth_data(*query_list, idx);
720                 if (STRING_VALID(sql)) {
721                         ret = __media_svc_query_direct(handle, sql, uid);
722                         if (ret != MS_MEDIA_ERR_NONE)
723                                 media_svc_debug("_media_svc_query_direct failed[%s]", sql);
724
725                         SQLITE3_SAFE_FREE(sql);
726                 }
727         }
728
729         if (with_transaction) {
730                 ret = sqlite3_exec(handle, "COMMIT;", NULL, NULL, &zErrMsg);
731                 if (SQLITE_OK != ret) {
732                         media_svc_sec_error("Commit failed[%s]", zErrMsg);
733                         SQLITE3_SAFE_FREE(zErrMsg);
734                         media_db_disconnect(handle);
735                         _media_svc_sql_query_release(query_list);
736                         return MS_MEDIA_ERR_DB_INTERNAL;
737                 }
738         }
739
740         media_db_disconnect(handle);
741
742 ZERO_LEN:
743         _media_svc_sql_query_release(query_list);
744
745         return MS_MEDIA_ERR_NONE;
746 }
747
748 void _media_svc_sql_query_add(GList **query_list, char **query)
749 {
750         *query_list = g_list_append(*query_list, *query);
751 }
752
753 void _media_svc_sql_query_release(GList **query_list)
754 {
755         if (*query_list) {
756                 g_list_free(*query_list);
757                 *query_list = NULL;
758         }
759 }