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