Add image info.
[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 <sys/stat.h>
24 #include <db-util.h>
25 #include <media-util.h>
26 #include <errno.h>
27 #include "media-svc-env.h"
28 #include "media-svc-debug.h"
29 #include "media-svc-util.h"
30 #include "media-svc-db-utils.h"
31 #include "media-util-err.h"
32 #include "media-util-db.h"
33 #include "media-svc-media.h"
34
35 static int __media_svc_create_update_media_table(sqlite3 *db_handle);
36
37 #define MEDIA_DB_SCHEMA "CREATE TABLE IF NOT EXISTS %s (\
38                                 media_uuid                      TEXT PRIMARY KEY, \
39                                 path                            TEXT NOT NULL UNIQUE, \
40                                 file_name                       TEXT NOT NULL, \
41                                 media_type                      INTEGER,\
42                                 mime_type                       TEXT, \
43                                 size                            INTEGER DEFAULT 0, \
44                                 added_time                      INTEGER DEFAULT 0,\
45                                 modified_time                   INTEGER DEFAULT 0, \
46                                 folder_uuid                     TEXT NOT NULL, \
47                                 thumbnail_path                  TEXT, \
48                                 title                           TEXT, \
49                                 album_id                        INTEGER DEFAULT 0, \
50                                 album                           TEXT, \
51                                 artist                          TEXT, \
52                                 album_artist                    TEXT, \
53                                 genre                           TEXT, \
54                                 composer                        TEXT, \
55                                 year                            TEXT, \
56                                 recorded_date                   TEXT, \
57                                 copyright                       TEXT, \
58                                 track_num                       TEXT, \
59                                 description                     TEXT, \
60                                 bitrate                         INTEGER DEFAULT -1, \
61                                 bitpersample            INTEGER DEFAULT 0, \
62                                 samplerate                      INTEGER DEFAULT -1, \
63                                 channel                         INTEGER DEFAULT -1, \
64                                 duration                        INTEGER DEFAULT -1, \
65                                 longitude                       DOUBLE DEFAULT 0, \
66                                 latitude                        DOUBLE DEFAULT 0, \
67                                 altitude                        DOUBLE DEFAULT 0, \
68                                 exposure_time           TEXT, \
69                                 fnumber                         DOUBLE DEFAULT 0, \
70                                 iso                                     INTEGER DEFAULT -1, \
71                                 model                           TEXT, \
72                                 width                           INTEGER DEFAULT -1, \
73                                 height                          INTEGER DEFAULT -1, \
74                                 datetaken                       TEXT, \
75                                 orientation                     INTEGER DEFAULT -1, \
76                                 burst_id                        TEXT, \
77                                 played_count                    INTEGER DEFAULT 0, \
78                                 last_played_time                INTEGER DEFAULT 0, \
79                                 last_played_position            INTEGER DEFAULT 0, \
80                                 rating                          INTEGER DEFAULT 0, \
81                                 favourite                       INTEGER DEFAULT 0, \
82                                 author                          TEXT, \
83                                 provider                        TEXT, \
84                                 content_name                    TEXT, \
85                                 category                        TEXT, \
86                                 location_tag                    TEXT, \
87                                 age_rating                      TEXT, \
88                                 keyword                         TEXT, \
89                                 is_drm                          INTEGER DEFAULT 0, \
90                                 storage_type                    INTEGER, \
91                                 timeline                        INTEGER DEFAULT 0, \
92                                 weather                         TEXT, \
93                                 sync_status             INTEGER DEFAULT 0, \
94                                 file_name_pinyin        TEXT, \
95                                 title_pinyin    TEXT, \
96                                 album_pinyin    TEXT, \
97                                 artist_pinyin    TEXT, \
98                                 album_artist_pinyin      TEXT, \
99                                 genre_pinyin    TEXT, \
100                                 composer_pinyin   TEXT, \
101                                 copyright_pinyin   TEXT, \
102                                 description_pinyin   TEXT, \
103                                 author_pinyin    TEXT, \
104                                 provider_pinyin   TEXT, \
105                                 content_name_pinyin  TEXT, \
106                                 category_pinyin   TEXT, \
107                                 location_tag_pinyin  TEXT, \
108                                 age_rating_pinyin   TEXT, \
109                                 keyword_pinyin   TEXT, \
110                                 validity                        INTEGER DEFAULT 1, \
111                                 unique(path, file_name) \
112                                 );"
113
114 static int __media_svc_busy_handler(void *pData, int count);
115
116 static int __media_svc_busy_handler(void *pData, int count)
117 {
118         usleep(50000);
119
120         media_svc_debug("media_svc_busy_handler called : %d", count);
121
122         return 100 - count;
123 }
124
125 int _media_svc_connect_db_with_handle(sqlite3 **db_handle)
126 {
127         int ret = MS_MEDIA_ERR_NONE;
128
129         media_svc_debug_func();
130
131         /*Connect DB*/
132         ret = db_util_open(MEDIA_SVC_DB_NAME, db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
133
134         if (SQLITE_OK != ret) {
135
136                 media_svc_error("error when db open");
137                 *db_handle = NULL;
138                 return MS_MEDIA_ERR_DB_INTERNAL;
139         }
140
141         /*Register busy handler*/
142         if (*db_handle) {
143                 ret = sqlite3_busy_handler(*db_handle, __media_svc_busy_handler, NULL);
144
145                 if (SQLITE_OK != ret) {
146
147                         if (*db_handle) {
148                                 media_svc_error("[error when register busy handler] %s\n", sqlite3_errmsg(*db_handle));
149                         }
150
151                         db_util_close(*db_handle);
152                         *db_handle = NULL;
153
154                         return MS_MEDIA_ERR_DB_INTERNAL;
155                 }
156         } else {
157                 *db_handle = NULL;
158                 return MS_MEDIA_ERR_DB_INTERNAL;
159         }
160
161         return MS_MEDIA_ERR_NONE;
162 }
163
164 int _media_svc_disconnect_db_with_handle(sqlite3 *db_handle)
165 {
166         int ret = MS_MEDIA_ERR_NONE;
167
168         media_svc_debug_func();
169
170         ret = db_util_close(db_handle);
171
172         if (SQLITE_OK != ret) {
173                 media_svc_error("Error when db close : %s", sqlite3_errmsg(db_handle));
174                 db_handle = NULL;
175                 return MS_MEDIA_ERR_DB_INTERNAL;
176         }
177
178         return MS_MEDIA_ERR_NONE;
179 }
180
181 int _media_svc_create_media_table(sqlite3 *db_handle, uid_t uid)
182 {
183         int ret = MS_MEDIA_ERR_NONE;
184         char *sql = NULL;
185
186         media_svc_debug_func();
187
188         sql = sqlite3_mprintf(MEDIA_DB_SCHEMA, MEDIA_SVC_DB_TABLE_MEDIA);
189
190         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
191
192         ret = _media_svc_sql_query(db_handle, sql, uid);
193         sqlite3_free(sql);
194         if (ret != SQLITE_OK) {
195                 media_svc_error("It failed to create db table (%d)", ret);
196                 return MS_MEDIA_ERR_DB_INTERNAL;
197         }
198
199         /* Create Index*/
200         sql = sqlite3_mprintf(" CREATE INDEX IF NOT EXISTS media_media_type_idx on %s (media_type); \
201                                                 CREATE INDEX IF NOT EXISTS media_title_idx on %s (title); \
202                                                 CREATE INDEX IF NOT EXISTS media_modified_time_idx on %s (modified_time); \
203                                                 CREATE INDEX IF NOT EXISTS media_provider_idx on %s (provider); \
204                                                 CREATE INDEX IF NOT EXISTS folder_uuid_idx on %s (folder_uuid); \
205                                                 CREATE INDEX IF NOT EXISTS media_album_idx on %s (album); \
206                                                 CREATE INDEX IF NOT EXISTS media_artist_idx on %s (artist); \
207                                                 CREATE INDEX IF NOT EXISTS media_author_idx on %s (author); \
208                                                 CREATE INDEX IF NOT EXISTS media_category_idx on %s (category); \
209                                                 CREATE INDEX IF NOT EXISTS media_composer_idx on %s (composer); \
210                                                 CREATE INDEX IF NOT EXISTS media_content_name_idx on %s (content_name); \
211                                                 CREATE INDEX IF NOT EXISTS media_file_name_idx on %s (file_name); \
212                                                 CREATE INDEX IF NOT EXISTS media_genre_idx on %s (genre); \
213                                                 CREATE INDEX IF NOT EXISTS media_location_tag_idx on %s (location_tag); \
214                                                 CREATE INDEX IF NOT EXISTS media_media_uuid_idx on %s (media_uuid); \
215                                                 CREATE INDEX IF NOT EXISTS media_timeline_idx on %s (timeline); \
216                                                 CREATE INDEX IF NOT EXISTS media_path_idx on %s (path); \
217                                                 ",
218                                                 MEDIA_SVC_DB_TABLE_MEDIA,
219                                                 MEDIA_SVC_DB_TABLE_MEDIA,
220                                                 MEDIA_SVC_DB_TABLE_MEDIA,
221                                                 MEDIA_SVC_DB_TABLE_MEDIA,
222                                                 MEDIA_SVC_DB_TABLE_MEDIA,
223                                                 MEDIA_SVC_DB_TABLE_MEDIA,
224                                                 MEDIA_SVC_DB_TABLE_MEDIA,
225                                                 MEDIA_SVC_DB_TABLE_MEDIA,
226                                                 MEDIA_SVC_DB_TABLE_MEDIA,
227                                                 MEDIA_SVC_DB_TABLE_MEDIA,
228                                                 MEDIA_SVC_DB_TABLE_MEDIA,
229                                                 MEDIA_SVC_DB_TABLE_MEDIA,
230                                                 MEDIA_SVC_DB_TABLE_MEDIA,
231                                                 MEDIA_SVC_DB_TABLE_MEDIA,
232                                                 MEDIA_SVC_DB_TABLE_MEDIA,
233                                                 MEDIA_SVC_DB_TABLE_MEDIA,
234                                                 MEDIA_SVC_DB_TABLE_MEDIA);
235
236         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
237
238         ret = _media_svc_sql_query(db_handle, sql, uid);
239         sqlite3_free(sql);
240         if (ret != SQLITE_OK) {
241                 media_svc_error("It failed to create db table (%d)", ret);
242                 return MS_MEDIA_ERR_DB_INTERNAL;
243         }
244
245         return MS_MEDIA_ERR_NONE;
246 }
247
248 int _media_svc_create_folder_table(sqlite3 *db_handle, uid_t uid)
249 {
250         int ret = MS_MEDIA_ERR_NONE;
251         char *sql = NULL;
252
253         media_svc_debug_func();
254
255         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
256                                 folder_uuid             TEXT PRIMARY KEY, \
257                                 path                            TEXT NOT NULL UNIQUE, \
258                                 name                    TEXT NOT NULL, \
259                                 modified_time           INTEGER DEFAULT 0, \
260                                 name_pinyin             TEXT, \
261                                 storage_type            INTEGER, \
262                                 unique(path, name, storage_type) \
263                                 );",
264                                 MEDIA_SVC_DB_TABLE_FOLDER);
265
266         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
267
268         ret = _media_svc_sql_query(db_handle, sql, uid);
269         sqlite3_free(sql);
270         if (ret != SQLITE_OK) {
271                 media_svc_error("It failed to create db table (%d)", ret);
272                 return MS_MEDIA_ERR_DB_INTERNAL;
273         }
274
275         /* Create Trigger to remove folder which have no content from folder when media remove from media_table*/
276         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS folder_cleanup \
277                                 DELETE ON %s BEGIN DELETE FROM %s \
278                                 WHERE (SELECT count(*) FROM %s WHERE folder_uuid=old.folder_uuid)=1 AND folder_uuid=old.folder_uuid;END;",
279                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_FOLDER, MEDIA_SVC_DB_TABLE_MEDIA);
280
281         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
282
283         ret = _media_svc_sql_query(db_handle, sql, uid);
284         sqlite3_free(sql);
285         if (ret != SQLITE_OK) {
286                 media_svc_error("It failed to create trigger (%d)", ret);
287                 return MS_MEDIA_ERR_DB_INTERNAL;
288         }
289
290         /* Create Index*/
291         sql = sqlite3_mprintf(" CREATE INDEX IF NOT EXISTS folder_folder_uuid_idx on %s (folder_uuid); \
292                                                 ",
293                                                 MEDIA_SVC_DB_TABLE_FOLDER);
294
295         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
296
297         ret = _media_svc_sql_query(db_handle, sql, uid);
298         sqlite3_free(sql);
299         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
300         return MS_MEDIA_ERR_NONE;
301 }
302
303 int _media_svc_create_playlist_table(sqlite3 *db_handle, uid_t uid)
304 {
305         int ret = MS_MEDIA_ERR_NONE;
306         char * sql = NULL;
307
308         media_svc_debug_func();
309
310         /*Create playlist table*/
311         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
312                                 playlist_id             INTEGER PRIMARY KEY AUTOINCREMENT, \
313                                 name                    TEXT NOT NULL UNIQUE,\
314                                 name_pinyin             TEXT, \
315                                 thumbnail_path  TEXT\
316                                 );",
317                                 MEDIA_SVC_DB_TABLE_PLAYLIST);
318
319         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
320
321         ret = _media_svc_sql_query(db_handle, sql, uid);
322         sqlite3_free(sql);
323         if (ret != SQLITE_OK) {
324                 media_svc_error("It failed to create db table (%d)", ret);
325                 return MS_MEDIA_ERR_DB_INTERNAL;
326         }
327
328         /*Create playlist_map table*/
329         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
330                                 _id                             INTEGER PRIMARY KEY AUTOINCREMENT, \
331                                 playlist_id             INTEGER NOT NULL,\
332                                 media_uuid              TEXT NOT NULL,\
333                                 play_order              INTEGER NOT NULL\
334                                 );",
335                                 MEDIA_SVC_DB_TABLE_PLAYLIST_MAP);
336
337         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
338
339         ret = _media_svc_sql_query(db_handle, sql, uid);
340         sqlite3_free(sql);
341         if (ret != SQLITE_OK) {
342                 media_svc_error("It failed to create db table (%d)", ret);
343                 return MS_MEDIA_ERR_DB_INTERNAL;
344         }
345
346         /* Create playlist_view*/
347         sql = sqlite3_mprintf(" \
348                 CREATE VIEW IF NOT EXISTS playlist_view AS \
349                 SELECT p.playlist_id, p.name, p.thumbnail_path AS p_thumbnail_path, media_count, pm._id as pm_id, pm.play_order, m.media_uuid, path, file_name, media_type, mime_type, size, added_time, modified_time, m.thumbnail_path, description, rating, favourite, author, provider, content_name, category, location_tag, age_rating, keyword, is_drm, storage_type, longitude, latitude, altitude, exposure_time, fnumber, iso, model, width, height, datetaken, orientation, title, album, artist, album_artist, genre, composer, year, recorded_date, copyright, track_num, bitrate, duration, played_count, last_played_time, last_played_position, samplerate, channel, weather, burst_id, timeline, sync_status, bitpersample FROM playlist AS p \
350                 INNER JOIN playlist_map AS pm \
351                 INNER JOIN media AS m \
352                 INNER JOIN (SELECT count(playlist_id) as media_count, playlist_id FROM playlist_map group by playlist_id) as cnt_tbl \
353                                 ON (p.playlist_id=pm.playlist_id AND pm.media_uuid = m.media_uuid AND cnt_tbl.playlist_id=pm.playlist_id AND m.validity=1) \
354                 UNION \
355                         SELECT playlist_id, name, thumbnail_path, 0, 0, -1, NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, -1, 0, -1, -1, -1, NULL, 0, -1, NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, -1, -1, NULL, -1, NULL, NULL, -1, 0, 0 FROM playlist \
356                                 WHERE playlist_id NOT IN (select playlist_id from playlist_map) \
357                 UNION \
358                         SELECT playlist_id, name, thumbnail_path, 0, 0, -1, NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, -1, 0, -1, -1, -1, NULL, 0, -1, NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, -1, -1, -1, -1, -1, NULL, -1, NULL, NULL, -1, 0, 0 FROM playlist \
359                                 WHERE playlist_id IN (select pm.playlist_id from playlist_map AS pm INNER JOIN media AS m ON (pm.media_uuid= m.media_uuid) AND m.validity=0); \
360                 ");
361
362         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
363
364         ret = _media_svc_sql_query(db_handle, sql, uid);
365         sqlite3_free(sql);
366         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
367
368         /* Create Trigger to remove media from playlist_map when media remove from media_table*/
369         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS playlist_map_cleanup \
370                                 DELETE ON %s BEGIN DELETE FROM %s WHERE media_uuid=old.media_uuid;END;",
371                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_PLAYLIST_MAP);
372
373         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
374
375         ret = _media_svc_sql_query(db_handle, sql, uid);
376         sqlite3_free(sql);
377         if (ret != SQLITE_OK) {
378                 media_svc_error("It failed to create trigger (%d)", ret);
379                 return MS_MEDIA_ERR_DB_INTERNAL;
380         }
381
382         /* Create Trigger to remove media from playlist_map when playlist removed from playlist table*/
383         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS playlist_map_cleanup_1 \
384                                 DELETE ON %s BEGIN DELETE FROM %s WHERE playlist_id=old.playlist_id;END;",
385                                 MEDIA_SVC_DB_TABLE_PLAYLIST, MEDIA_SVC_DB_TABLE_PLAYLIST_MAP);
386
387         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
388
389         ret = _media_svc_sql_query(db_handle, sql, uid);
390         sqlite3_free(sql);
391         if (ret != SQLITE_OK) {
392                 media_svc_error("It failed to create trigger (%d)", ret);
393                 return MS_MEDIA_ERR_DB_INTERNAL;
394         }
395
396         return MS_MEDIA_ERR_NONE;
397 }
398
399 int _media_svc_create_album_table(sqlite3 *db_handle, uid_t uid)
400 {
401         int ret = MS_MEDIA_ERR_NONE;
402         char * sql = NULL;
403
404         media_svc_debug_func();
405
406         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
407                                 album_id                        INTEGER PRIMARY KEY AUTOINCREMENT, \
408                                 name                    TEXT NOT NULL,\
409                                 artist                  TEXT, \
410                                 album_art               TEXT, \
411                                 unique(name, artist) \
412                                 );",
413                                 MEDIA_SVC_DB_TABLE_ALBUM);
414
415         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
416
417         ret = _media_svc_sql_query(db_handle, sql, uid);
418         sqlite3_free(sql);
419         if (ret != SQLITE_OK) {
420                 media_svc_error("It failed to create db table (%d)", ret);
421                 return MS_MEDIA_ERR_DB_INTERNAL;
422         }
423
424         /* Create Trigger to remove album when media remove from media_table*/
425         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS album_cleanup \
426                                 DELETE ON %s BEGIN DELETE FROM %s \
427                                 WHERE (SELECT count(*) FROM %s WHERE album_id=old.album_id)=1 AND album_id=old.album_id;END;",
428                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_ALBUM, MEDIA_SVC_DB_TABLE_MEDIA);
429
430         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
431
432         ret = _media_svc_sql_query(db_handle, sql, uid);
433         sqlite3_free(sql);
434         if (ret != SQLITE_OK) {
435                 media_svc_error("It failed to create trigger (%d)", ret);
436                 return MS_MEDIA_ERR_DB_INTERNAL;
437         }
438
439         return MS_MEDIA_ERR_NONE;
440 }
441
442 int _media_svc_create_tag_table(sqlite3 *db_handle, uid_t uid)
443 {
444         int ret = MS_MEDIA_ERR_NONE;
445         char * sql = NULL;
446
447         media_svc_debug_func();
448
449         /*Create tag table*/
450         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
451                                 tag_id          INTEGER PRIMARY KEY AUTOINCREMENT, \
452                                 name            TEXT NOT NULL UNIQUE, \
453                                 name_pinyin             TEXT \
454                                 );",
455                                 MEDIA_SVC_DB_TABLE_TAG);
456
457         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
458
459         ret = _media_svc_sql_query(db_handle, sql, uid);
460         sqlite3_free(sql);
461         if (ret != SQLITE_OK) {
462                 media_svc_error("It failed to create db table (%d)", ret);
463                 return MS_MEDIA_ERR_DB_INTERNAL;
464         }
465
466         /*Create tag_map table*/
467         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
468                                 _id                             INTEGER PRIMARY KEY AUTOINCREMENT, \
469                                 tag_id                  INTEGER NOT NULL,\
470                                 media_uuid              TEXT NOT NULL,\
471                                 unique(tag_id, media_uuid) \
472                                 );",
473                                 MEDIA_SVC_DB_TABLE_TAG_MAP);
474
475         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
476
477         ret = _media_svc_sql_query(db_handle, sql, uid);
478         sqlite3_free(sql);
479         if (ret != SQLITE_OK) {
480                 media_svc_error("It failed to create db table (%d)", ret);
481                 return MS_MEDIA_ERR_DB_INTERNAL;
482         }
483
484         /*Create tag_view*/
485         sql = sqlite3_mprintf("\
486                                 CREATE VIEW IF NOT EXISTS tag_view AS \
487                                 SELECT \
488                                         t.tag_id, t.name, media_count, tm._id as tm_id, m.media_uuid, path, file_name, media_type, mime_type, size, added_time, modified_time, thumbnail_path, description, rating, favourite, author, provider, content_name, category, location_tag, age_rating, keyword, is_drm, storage_type, longitude, latitude, altitude, model, width, height, datetaken, orientation, title, album, artist, album_artist, genre, composer, year, recorded_date, copyright, track_num, bitrate, duration, played_count, last_played_time, last_played_position, samplerate, channel, weather, timeline, sync_status, bitpersample FROM tag AS t \
489                                 INNER JOIN tag_map AS tm \
490                                 INNER JOIN media AS m \
491                                 INNER JOIN (SELECT count(tag_id) as media_count, tag_id FROM tag_map group by tag_id) as cnt_tbl \
492                                                  ON (t.tag_id=tm.tag_id AND tm.media_uuid = m.media_uuid AND cnt_tbl.tag_id=tm.tag_id AND m.validity=1) \
493                                 UNION \
494                                 SELECT \
495                                         tag_id, name, 0, 0,  NULL, NULL, -1, -1, -1, -1, -1, NULL, NULL, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, -1,  0, -1, -1, -1, -1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, -1, -1, -1, -1, -1, -1, NULL, -1, NULL, -1, 0, 0 FROM tag \
496                                 WHERE tag_id \
497                                 NOT IN (select tag_id from tag_map); \
498                                 ");
499
500         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
501
502         ret = _media_svc_sql_query(db_handle, sql, uid);
503         sqlite3_free(sql);
504         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
505
506         /* Create Trigger to remove media from tag_map when media remove from media_table*/
507         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS tag_map_cleanup \
508                                 DELETE ON %s BEGIN DELETE FROM %s WHERE media_uuid=old.media_uuid;END;",
509                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_TAG_MAP);
510
511         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
512
513         ret = _media_svc_sql_query(db_handle, sql, uid);
514         sqlite3_free(sql);
515         if (ret != SQLITE_OK) {
516                 media_svc_error("It failed to create trigger (%d)", ret);
517                 return MS_MEDIA_ERR_DB_INTERNAL;
518         }
519
520         /* Create Trigger to remove media from tag_map when tag removed from tag table*/
521         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS tag_map_cleanup_1 \
522                                 DELETE ON %s BEGIN DELETE FROM %s WHERE tag_id=old.tag_id;END;",
523                                 MEDIA_SVC_DB_TABLE_TAG, MEDIA_SVC_DB_TABLE_TAG_MAP);
524
525         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
526
527         ret = _media_svc_sql_query(db_handle, sql, uid);
528         sqlite3_free(sql);
529         if (ret != SQLITE_OK) {
530                 media_svc_error("It failed to create trigger (%d)", ret);
531                 return MS_MEDIA_ERR_DB_INTERNAL;
532         }
533         return MS_MEDIA_ERR_NONE;
534 }
535
536 int _media_svc_create_bookmark_table(sqlite3 *db_handle, uid_t uid)
537 {
538         int ret = MS_MEDIA_ERR_NONE;
539         char * sql = NULL;
540
541         media_svc_debug_func();
542
543         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
544                                 bookmark_id             INTEGER PRIMARY KEY AUTOINCREMENT, \
545                                 media_uuid              TEXT NOT NULL,\
546                                 marked_time             INTEGER DEFAULT 0, \
547                                 thumbnail_path  TEXT, \
548                                 unique(media_uuid, marked_time) \
549                                 );",
550                                 MEDIA_SVC_DB_TABLE_BOOKMARK);
551
552         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
553
554         ret = _media_svc_sql_query(db_handle, sql, uid);
555         sqlite3_free(sql);
556         if (ret != SQLITE_OK) {
557                 media_svc_error("It failed to create db table (%d)", ret);
558                 return MS_MEDIA_ERR_DB_INTERNAL;
559         }
560
561         /* Create Trigger to remove media from tag_map when media remove from media_table*/
562         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS bookmark_cleanup \
563                                 DELETE ON %s BEGIN DELETE FROM %s WHERE media_uuid=old.media_uuid;END;",
564                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_BOOKMARK);
565
566         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
567
568         ret = _media_svc_sql_query(db_handle, sql, uid);
569         sqlite3_free(sql);
570         if (ret != SQLITE_OK) {
571                 media_svc_error("It failed to create trigger (%d)", ret);
572                 return MS_MEDIA_ERR_DB_INTERNAL;
573         }
574
575         return MS_MEDIA_ERR_NONE;
576 }
577
578 int _media_svc_create_custom_table(sqlite3 *db_handle, uid_t uid)
579 {
580         int ret = MS_MEDIA_ERR_NONE;
581         char * sql = NULL;
582
583         media_svc_debug_func();
584
585         sql = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
586                                 _id                             INTEGER PRIMARY KEY AUTOINCREMENT, \
587                                 media_uuid              TEXT, \
588                                 media_type              INTEGER,\
589                                 author                  TEXT, \
590                                 provider                        TEXT, \
591                                 content_name    TEXT, \
592                                 category                        TEXT, \
593                                 location_tag            TEXT, \
594                                 age_rating              TEXT \
595                                 );",
596                                 MEDIA_SVC_DB_TABLE_CUSTOM);
597
598         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
599
600         ret = _media_svc_sql_query(db_handle, sql, uid);
601         sqlite3_free(sql);
602         if (ret != SQLITE_OK) {
603                 media_svc_error("It failed to create db table (%d)", ret);
604                 return MS_MEDIA_ERR_DB_INTERNAL;
605         }
606
607         /* Create Trigger to remove media from tag_map when media remove from media_table*/
608         sql = sqlite3_mprintf("CREATE TRIGGER IF NOT EXISTS custom_cleanup \
609                                 DELETE ON %s BEGIN DELETE FROM %s WHERE media_uuid=old.media_uuid;END;",
610                                 MEDIA_SVC_DB_TABLE_MEDIA, MEDIA_SVC_DB_TABLE_CUSTOM);
611
612         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
613
614         ret = _media_svc_sql_query(db_handle, sql, uid);
615         sqlite3_free(sql);
616         if (ret != SQLITE_OK) {
617                 media_svc_error("It failed to create trigger (%d)", ret);
618                 return MS_MEDIA_ERR_DB_INTERNAL;
619         }
620
621         /* Create Index*/
622         sql = sqlite3_mprintf("CREATE INDEX IF NOT EXISTS custom_provider_idx on %s (provider); \
623                                                 ",
624                                                 MEDIA_SVC_DB_TABLE_CUSTOM);
625
626         media_svc_retv_if(sql == NULL, MS_MEDIA_ERR_OUT_OF_MEMORY);
627
628         ret = _media_svc_sql_query(db_handle, sql, uid);
629         sqlite3_free(sql);
630         if (ret != SQLITE_OK) {
631                 media_svc_error("It failed to create db table (%d)", ret);
632                 return MS_MEDIA_ERR_DB_INTERNAL;
633         }
634
635         return MS_MEDIA_ERR_NONE;
636 }
637
638 int _media_svc_request_update_db(const char *sql_str, uid_t uid)
639 {
640         int ret = MS_MEDIA_ERR_NONE;
641
642         ret = media_db_request_update_db(sql_str, uid);
643
644         return ret;
645 }
646
647 int _media_svc_sql_query(sqlite3 *db_handle, const char *sql_str, uid_t uid)
648 {
649         int ret = MS_MEDIA_ERR_NONE;
650
651         media_svc_debug("[SQL query] : %s", sql_str);
652
653         //DB will be updated by Media Server.
654         ret = _media_svc_request_update_db(sql_str, uid);
655
656         return ret;
657 }
658
659 int _media_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt)
660 {
661         int err = -1;
662
663         media_svc_debug("[SQL query] : %s", sql_str);
664
665         err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
666         sqlite3_free((char *)sql_str);
667
668         if (err != SQLITE_OK) {
669                 media_svc_error ("prepare error %d[%s]", err, sqlite3_errmsg(handle));
670                 return MS_MEDIA_ERR_DB_INTERNAL;
671         }
672
673         err = sqlite3_step(*stmt);
674         if (err != SQLITE_ROW) {
675                 media_svc_error("Item not found. end of row [%s]", sqlite3_errmsg(handle));
676                 SQLITE3_FINALIZE(*stmt);
677                 return MS_MEDIA_ERR_DB_NO_RECORD;
678         }
679
680         return MS_MEDIA_ERR_NONE;
681 }
682
683 int _media_svc_sql_begin_trans(sqlite3 *handle, uid_t uid)
684 {
685         int ret = MS_MEDIA_ERR_NONE;
686
687         media_svc_error("========_media_svc_sql_begin_trans");
688
689         ret = media_db_request_update_db_batch_start("BEGIN IMMEDIATE;", uid);
690
691         return ret;
692 }
693
694 int _media_svc_sql_end_trans(sqlite3 *handle, uid_t uid)
695 {
696         int ret = MS_MEDIA_ERR_NONE;
697
698         media_svc_error("========_media_svc_sql_end_trans");
699
700         ret = media_db_request_update_db_batch_end("COMMIT;", uid);
701
702         return ret;
703 }
704
705 int _media_svc_sql_rollback_trans(sqlite3 *handle, uid_t uid)
706 {
707         media_svc_error("========_media_svc_sql_rollback_trans");
708
709         return _media_svc_request_update_db("ROLLBACK;", uid);
710
711 }
712
713 int _media_svc_sql_query_list(sqlite3 *handle, GList **query_list, uid_t uid)
714 {
715         int ret = MS_MEDIA_ERR_NONE;
716         int idx = 0;
717         int length = g_list_length(*query_list);
718         char *sql = NULL;
719
720         media_svc_debug("query list length : [%d]", length);
721
722         for (idx = 0; idx < length; idx++) {
723                 sql = (char*)g_list_nth_data(*query_list, idx);
724                 if(sql != NULL) {
725                         //ret = _media_svc_sql_query(handle, sql);
726                         ret = media_db_request_update_db_batch(sql, uid);
727                         if (ret != MS_MEDIA_ERR_NONE) {
728                                 media_svc_error("media_db_request_update_db_batch failed : %d", ret);
729                         }
730                         sqlite3_free(sql);
731                         sql = NULL;
732                 }
733         }
734
735         _media_svc_sql_query_release(query_list);
736
737         return MS_MEDIA_ERR_NONE;
738
739 }
740
741 void _media_svc_sql_query_add(GList **query_list, char **query)
742 {
743         *query_list = g_list_append( *query_list, *query);
744 }
745
746 void _media_svc_sql_query_release(GList **query_list)
747 {
748         if (*query_list) {
749                 media_svc_debug("_svc_sql_query_release");
750                 g_list_free(*query_list);
751                 *query_list = NULL;
752         }
753 }