[cstdstring] demise Format, replacing with StringUtils::Format
[vuplus_xbmc] / xbmc / utils / DatabaseUtils.cpp
1 /*
2  *      Copyright (C) 2012-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <sstream>
22
23 #include "DatabaseUtils.h"
24 #include "dbwrappers/dataset.h"
25 #include "music/MusicDatabase.h"
26 #include "utils/log.h"
27 #include "utils/Variant.h"
28 #include "utils/StringUtils.h"
29 #include "video/VideoDatabase.h"
30
31 std::string DatabaseUtils::MediaTypeToString(MediaType mediaType)
32 {
33   switch (mediaType)
34   {
35   case MediaTypeMusic:
36     return "music";
37   case MediaTypeArtist:
38     return "artist";
39   case MediaTypeAlbum:
40     return "album";
41   case MediaTypeSong:
42     return "song";
43   case MediaTypeVideo:
44     return "video";
45   case MediaTypeVideoCollection:
46     return "set";
47   case MediaTypeMusicVideo:
48     return "musicvideo";
49   case MediaTypeMovie:
50     return "movie";
51   case MediaTypeTvShow:
52     return "tvshow";
53   case MediaTypeEpisode:
54     return "episode";
55   default:
56     break;
57   }
58
59   return "";
60 }
61
62 MediaType DatabaseUtils::MediaTypeFromString(const std::string &strMediaType)
63 {
64   if (strMediaType.compare("music") == 0)
65     return MediaTypeMusic;
66   else if (strMediaType.compare("artist") == 0 || strMediaType.compare("artists") == 0)
67     return MediaTypeArtist;
68   else if (strMediaType.compare("album") == 0 || strMediaType.compare("albums") == 0)
69     return MediaTypeAlbum;
70   else if (strMediaType.compare("song") == 0 || strMediaType.compare("songs") == 0)
71     return MediaTypeSong;
72   else if (strMediaType.compare("video") == 0 || strMediaType.compare("videos") == 0)
73     return MediaTypeVideo;
74   else if (strMediaType.compare("set") == 0 || strMediaType.compare("sets") == 0)
75     return MediaTypeVideoCollection;
76   else if (strMediaType.compare("musicvideo") == 0 || strMediaType.compare("musicvideos") == 0)
77     return MediaTypeMusicVideo;
78   else if (strMediaType.compare("movie") == 0 || strMediaType.compare("movies") == 0)
79     return MediaTypeMovie;
80   else if (strMediaType.compare("tvshow") == 0 || strMediaType.compare("tvshows") == 0)
81     return MediaTypeTvShow;
82   else if (strMediaType.compare("episode") == 0 || strMediaType.compare("episodes") == 0)
83     return MediaTypeEpisode;
84
85   return MediaTypeNone;
86 }
87
88 MediaType DatabaseUtils::MediaTypeFromVideoContentType(int videoContentType)
89 {
90   VIDEODB_CONTENT_TYPE type = (VIDEODB_CONTENT_TYPE)videoContentType;
91   switch (type)
92   {
93     case VIDEODB_CONTENT_MOVIES:
94       return MediaTypeMovie;
95
96     case VIDEODB_CONTENT_MOVIE_SETS:
97       return MediaTypeVideoCollection;
98
99     case VIDEODB_CONTENT_TVSHOWS:
100       return MediaTypeTvShow;
101
102     case VIDEODB_CONTENT_EPISODES:
103       return MediaTypeEpisode;
104
105     case VIDEODB_CONTENT_MUSICVIDEOS:
106       return MediaTypeMusicVideo;
107
108     default:
109       break;
110   }
111
112   return MediaTypeNone;
113 }
114
115 std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQueryPart queryPart)
116 {
117   if (field == FieldNone || mediaType == MediaTypeNone)
118     return "";
119
120   if (mediaType == MediaTypeAlbum)
121   {
122     if (field == FieldId) return "albumview.idAlbum";
123     else if (field == FieldAlbum) return "albumview.strAlbum";
124     else if (field == FieldArtist || field == FieldAlbumArtist) return "albumview.strArtists";
125     else if (field == FieldGenre) return "albumview.strGenre";
126     else if (field == FieldYear) return "albumview.iYear";
127     else if (field == FieldMoods) return "albumview.strMoods";
128     else if (field == FieldStyles) return "albumview.strStyles";
129     else if (field == FieldThemes) return "albumview.strThemes";
130     else if (field == FieldReview) return "albumview.strReview";
131     else if (field == FieldMusicLabel) return "albumview.strLabel";
132     else if (field == FieldAlbumType) return "albumview.strType";
133     else if (field == FieldRating) return "albumview.iRating";
134     else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "albumview.idalbum";    // only used for order clauses
135     else if (field == FieldPlaycount) return "albumview.iTimesPlayed";
136   }
137   else if (mediaType == MediaTypeSong)
138   {
139     if (field == FieldId) return "songview.idSong";
140     else if (field == FieldTitle) return "songview.strTitle";
141     else if (field == FieldTrackNumber) return "songview.iTrack";
142     else if (field == FieldTime) return "songview.iDuration";
143     else if (field == FieldYear) return "songview.iYear";
144     else if (field == FieldFilename) return "songview.strFilename";
145     else if (field == FieldPlaycount) return "songview.iTimesPlayed";
146     else if (field == FieldStartOffset) return "songview.iStartOffset";
147     else if (field == FieldEndOffset) return "songview.iEndOffset";
148     else if (field == FieldLastPlayed) return "songview.lastPlayed";
149     else if (field == FieldRating) return "songview.rating";
150     else if (field == FieldComment) return "songview.comment";
151     else if (field == FieldAlbum) return "songview.strAlbum";
152     else if (field == FieldPath) return "songview.strPath";
153     else if (field == FieldArtist || field == FieldAlbumArtist) return "songview.strArtists";
154     else if (field == FieldGenre) return "songview.strGenre";
155     else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "songview.idSong";     // only used for order clauses
156   }
157   else if (mediaType == MediaTypeArtist)
158   {
159     if (field == FieldId) return "artistview.idArtist";
160     else if (field == FieldArtist) return "artistview.strArtist";
161     else if (field == FieldGenre) return "artistview.strGenres";
162     else if (field == FieldMoods) return "artistview.strMoods";
163     else if (field == FieldStyles) return "artistview.strStyles";
164     else if (field == FieldInstruments) return "artistview.strInstruments";
165     else if (field == FieldBiography) return "artistview.strBiography";
166     else if (field == FieldBorn) return "artistview.strBorn";
167     else if (field == FieldBandFormed) return "artistview.strFormed";
168     else if (field == FieldDisbanded) return "artistview.strDisbanded";
169     else if (field == FieldDied) return "artistview.strDied";
170   }
171   else if (mediaType == MediaTypeMusicVideo)
172   {
173     CStdString result;
174     if (field == FieldId) return "musicvideoview.idMVideo";
175     else if (field == FieldTitle) result = StringUtils::Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_TITLE);
176     else if (field == FieldTime) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_RUNTIME);
177     else if (field == FieldDirector) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_DIRECTOR);
178     else if (field == FieldStudio) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_STUDIOS);
179     else if (field == FieldYear) result = StringUtils::Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_YEAR);
180     else if (field == FieldPlot) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_PLOT);
181     else if (field == FieldAlbum) result = StringUtils::Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_ALBUM);
182     else if (field == FieldArtist) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_ARTIST);
183     else if (field == FieldGenre) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_GENRE);
184     else if (field == FieldTrackNumber) result = StringUtils::Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_TRACK);
185     else if (field == FieldFilename) return "musicvideoview.strFilename";
186     else if (field == FieldPath) return "musicvideoview.strPath";
187     else if (field == FieldPlaycount) return "musicvideoview.playCount";
188     else if (field == FieldLastPlayed) return "musicvideoview.lastPlayed";
189     else if (field == FieldDateAdded) return "musicvideoview.dateAdded";
190
191     if (!result.empty())
192       return result;
193   }
194   else if (mediaType == MediaTypeMovie)
195   {
196     CStdString result;
197     if (field == FieldId) return "movieview.idMovie";
198     else if (field == FieldTitle)
199     {
200       // We need some extra logic to get the title value if sorttitle isn't set
201       if (queryPart == DatabaseQueryPartOrderBy)
202         result = StringUtils::Format("CASE WHEN length(movieview.c%02d) > 0 THEN movieview.c%02d ELSE movieview.c%02d END", VIDEODB_ID_SORTTITLE, VIDEODB_ID_SORTTITLE, VIDEODB_ID_TITLE);
203       else
204         result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_TITLE);
205     }
206     else if (field == FieldPlot) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_PLOT);
207     else if (field == FieldPlotOutline) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_PLOTOUTLINE);
208     else if (field == FieldTagline) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_TAGLINE);
209     else if (field == FieldVotes) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_VOTES);
210     else if (field == FieldRating)
211     {
212       if (queryPart == DatabaseQueryPartOrderBy)
213         result = StringUtils::Format("CAST(movieview.c%02d as DECIMAL(5,3))", VIDEODB_ID_RATING);
214       else
215         result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_RATING);
216     }
217     else if (field == FieldWriter) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_CREDITS);
218     else if (field == FieldYear) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_YEAR);
219     else if (field == FieldSortTitle) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_SORTTITLE);
220     else if (field == FieldTime) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_RUNTIME);
221     else if (field == FieldMPAA) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_MPAA);
222     else if (field == FieldTop250) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_TOP250);
223     else if (field == FieldSet) return "movieview.strSet";
224     else if (field == FieldGenre) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_GENRE);
225     else if (field == FieldDirector) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_DIRECTOR);
226     else if (field == FieldStudio) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_STUDIOS);
227     else if (field == FieldTrailer) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_TRAILER);
228     else if (field == FieldCountry) result = StringUtils::Format("movieview.c%02d", VIDEODB_ID_COUNTRY);
229     else if (field == FieldFilename) return "movieview.strFilename";
230     else if (field == FieldPath) return "movieview.strPath";
231     else if (field == FieldPlaycount) return "movieview.playCount";
232     else if (field == FieldLastPlayed) return "movieview.lastPlayed";
233     else if (field == FieldDateAdded) return "movieview.dateAdded";
234
235     if (!result.empty())
236       return result;
237   }
238   else if (mediaType == MediaTypeTvShow)
239   {
240     CStdString result;
241     if (field == FieldId) return "tvshowview.idShow";
242     else if (field == FieldTitle)
243     {
244       // We need some extra logic to get the title value if sorttitle isn't set
245       if (queryPart == DatabaseQueryPartOrderBy)
246         result = StringUtils::Format("CASE WHEN length(tvshowview.c%02d) > 0 THEN tvshowview.c%02d ELSE tvshowview.c%02d END", VIDEODB_ID_TV_SORTTITLE, VIDEODB_ID_TV_SORTTITLE, VIDEODB_ID_TV_TITLE);
247       else
248         result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_TITLE);
249     }
250     else if (field == FieldPlot) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_PLOT);
251     else if (field == FieldTvShowStatus) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_STATUS);
252     else if (field == FieldVotes) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_VOTES);
253     else if (field == FieldRating) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_RATING);
254     else if (field == FieldYear) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_PREMIERED);
255     else if (field == FieldGenre) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_GENRE);
256     else if (field == FieldMPAA) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_MPAA);
257     else if (field == FieldStudio) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_STUDIOS);
258     else if (field == FieldSortTitle) result = StringUtils::Format("tvshowview.c%02d", VIDEODB_ID_TV_SORTTITLE);
259     else if (field == FieldPath) return "tvshowview.strPath";
260     else if (field == FieldDateAdded) return "tvshowview.dateAdded";
261     else if (field == FieldLastPlayed) return "tvshowview.lastPlayed";
262     else if (field == FieldSeason) return "tvshowview.totalSeasons";
263     else if (field == FieldNumberOfEpisodes) return "tvshowview.totalCount";
264     else if (field == FieldNumberOfWatchedEpisodes) return "tvshowview.watchedcount";
265
266     if (!result.empty())
267       return result;
268   }
269   else if (mediaType == MediaTypeEpisode)
270   {
271     CStdString result;
272     if (field == FieldId) return "episodeview.idEpisode";
273     else if (field == FieldTitle) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_TITLE);
274     else if (field == FieldPlot) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_PLOT);
275     else if (field == FieldVotes) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_VOTES);
276     else if (field == FieldRating) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_RATING);
277     else if (field == FieldWriter) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_CREDITS);
278     else if (field == FieldAirDate) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_AIRED);
279     else if (field == FieldTime) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_RUNTIME);
280     else if (field == FieldDirector) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_DIRECTOR);
281     else if (field == FieldSeason) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SEASON);
282     else if (field == FieldEpisodeNumber) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_EPISODE);
283     else if (field == FieldUniqueId) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_UNIQUEID);
284     else if (field == FieldEpisodeNumberSpecialSort) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTEPISODE);
285     else if (field == FieldSeasonSpecialSort) result = StringUtils::Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTSEASON);
286     else if (field == FieldFilename) return "episodeview.strFilename";
287     else if (field == FieldPath) return "episodeview.strPath";
288     else if (field == FieldPlaycount) return "episodeview.playCount";
289     else if (field == FieldLastPlayed) return "episodeview.lastPlayed";
290     else if (field == FieldDateAdded) return "episodeview.dateAdded";
291     else if (field == FieldTvShowTitle) return "episodeview.strTitle";
292     else if (field == FieldYear) return "episodeview.premiered";
293     else if (field == FieldMPAA) return "episodeview.mpaa";
294     else if (field == FieldStudio) return "episodeview.strStudio";
295
296     if (!result.empty())
297       return result;
298   }
299
300   if (field == FieldRandom && queryPart == DatabaseQueryPartOrderBy)
301     return "RANDOM()";
302
303   return "";
304 }
305
306 int DatabaseUtils::GetField(Field field, MediaType mediaType)
307 {
308   if (field == FieldNone || mediaType == MediaTypeNone)
309     return -1;
310
311   return GetField(field, mediaType, false);
312 }
313
314 int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType)
315 {
316   if (field == FieldNone || mediaType == MediaTypeNone)
317     return -1;
318
319   return GetField(field, mediaType, true);
320 }
321
322 bool DatabaseUtils::GetSelectFields(const Fields &fields, MediaType mediaType, FieldList &selectFields)
323 {
324   if (mediaType == MediaTypeNone || fields.empty())
325     return false;
326
327   Fields sortFields = fields;
328
329   // add necessary fields to create the label
330   if (mediaType == MediaTypeSong || mediaType == MediaTypeVideo || mediaType == MediaTypeVideoCollection ||
331       mediaType == MediaTypeMusicVideo || mediaType == MediaTypeMovie || mediaType == MediaTypeTvShow || mediaType == MediaTypeEpisode)
332     sortFields.insert(FieldTitle);
333   if (mediaType == MediaTypeEpisode)
334   {
335     sortFields.insert(FieldSeason);
336     sortFields.insert(FieldEpisodeNumber);
337   }
338   else if (mediaType == MediaTypeAlbum)
339     sortFields.insert(FieldAlbum);
340   else if (mediaType == MediaTypeSong)
341     sortFields.insert(FieldTrackNumber);
342   else if (mediaType == MediaTypeArtist)
343     sortFields.insert(FieldArtist);
344
345   selectFields.clear();
346   for (Fields::const_iterator it = sortFields.begin(); it != sortFields.end(); it++)
347   {
348     // ignore FieldLabel because it needs special handling (see further up)
349     if (*it == FieldLabel)
350       continue;
351
352     if (GetField(*it, mediaType, DatabaseQueryPartSelect).empty())
353     {
354       CLog::Log(LOGDEBUG, "DatabaseUtils::GetSortFieldList: unknown field %d", *it);
355       continue;
356     }
357     selectFields.push_back(*it);
358   }
359
360   return !selectFields.empty();
361 }
362
363 bool DatabaseUtils::GetFieldValue(const dbiplus::field_value &fieldValue, CVariant &variantValue)
364 {
365   if (fieldValue.get_isNull())
366   {
367     variantValue = CVariant::ConstNullVariant;
368     return true;
369   }
370
371   switch (fieldValue.get_fType())
372   {
373   case dbiplus::ft_String:
374   case dbiplus::ft_WideString:
375   case dbiplus::ft_Object:
376     variantValue = fieldValue.get_asString();
377     return true;
378   case dbiplus::ft_Char:
379   case dbiplus::ft_WChar:
380     variantValue = fieldValue.get_asChar();
381     return true;
382   case dbiplus::ft_Boolean:
383     variantValue = fieldValue.get_asBool();
384     return true;
385   case dbiplus::ft_Short:
386     variantValue = fieldValue.get_asShort();
387     return true;
388   case dbiplus::ft_UShort:
389     variantValue = fieldValue.get_asShort();
390     return true;
391   case dbiplus::ft_Int:
392     variantValue = fieldValue.get_asInt();
393     return true;
394   case dbiplus::ft_UInt:
395     variantValue = fieldValue.get_asUInt();
396     return true;
397   case dbiplus::ft_Float:
398     variantValue = fieldValue.get_asFloat();
399     return true;
400   case dbiplus::ft_Double:
401   case dbiplus::ft_LongDouble:
402     variantValue = fieldValue.get_asDouble();
403     return true;
404   case dbiplus::ft_Int64:
405     variantValue = fieldValue.get_asInt64();
406     return true;
407   }
408
409   return false;
410 }
411
412 bool DatabaseUtils::GetDatabaseResults(MediaType mediaType, const FieldList &fields, const std::auto_ptr<dbiplus::Dataset> &dataset, DatabaseResults &results)
413 {
414   if (dataset->num_rows() == 0)
415     return true;
416
417   const dbiplus::result_set &resultSet = dataset->get_result_set();
418   unsigned int offset = results.size();
419
420   if (fields.empty())
421   {
422     DatabaseResult result;
423     for (unsigned int index = 0; index < resultSet.records.size(); index++)
424     {
425       result[FieldRow] = index + offset;
426       results.push_back(result);
427     }
428
429     return true;
430   }
431
432   if (resultSet.record_header.size() < fields.size())
433     return false;
434
435   std::vector<int> fieldIndexLookup;
436   fieldIndexLookup.reserve(fields.size());
437   for (FieldList::const_iterator it = fields.begin(); it != fields.end(); it++)
438     fieldIndexLookup.push_back(GetFieldIndex(*it, mediaType));
439
440   results.reserve(resultSet.records.size() + offset);
441   for (unsigned int index = 0; index < resultSet.records.size(); index++)
442   {
443     DatabaseResult result;
444     result[FieldRow] = index + offset;
445
446     unsigned int lookupIndex = 0;
447     for (FieldList::const_iterator it = fields.begin(); it != fields.end(); it++)
448     {
449       int fieldIndex = fieldIndexLookup[lookupIndex++];
450       if (fieldIndex < 0)
451         return false;
452
453       std::pair<Field, CVariant> value;
454       value.first = *it;
455       if (!GetFieldValue(resultSet.records[index]->at(fieldIndex), value.second))
456         CLog::Log(LOGWARNING, "GetDatabaseResults: unable to retrieve value of field %s", resultSet.record_header[fieldIndex].name.c_str());
457
458       if (value.first == FieldYear &&
459          (mediaType == MediaTypeTvShow || mediaType == MediaTypeEpisode))
460       {
461         CDateTime dateTime;
462         dateTime.SetFromDBDate(value.second.asString());
463         if (dateTime.IsValid())
464         {
465           value.second.clear();
466           value.second = dateTime.GetYear();
467         }
468       }
469
470       result.insert(value);
471     }
472
473     result[FieldMediaType] = mediaType;
474     switch (mediaType)
475     {
476     case MediaTypeMovie:
477     case MediaTypeVideoCollection:
478     case MediaTypeTvShow:
479     case MediaTypeMusicVideo:
480       result[FieldLabel] = result.at(FieldTitle).asString();
481       break;
482       
483     case MediaTypeEpisode:
484     {
485       std::ostringstream label;
486       label << (int)(result.at(FieldSeason).asInteger() * 100 + result.at(FieldEpisodeNumber).asInteger());
487       label << ". ";
488       label << result.at(FieldTitle).asString();
489       result[FieldLabel] = label.str();
490       break;
491     }
492
493     case MediaTypeAlbum:
494       result[FieldLabel] = result.at(FieldAlbum).asString();
495       break;
496
497     case MediaTypeSong:
498     {
499       std::ostringstream label;
500       label << (int)result.at(FieldTrackNumber).asInteger();
501       label << ". ";
502       label << result.at(FieldTitle).asString();
503       result[FieldLabel] = label.str();
504       break;
505     }
506
507     case MediaTypeArtist:
508       result[FieldLabel] = result.at(FieldArtist).asString();
509       break;
510
511     default:
512       break;
513     }
514
515     results.push_back(result);
516   }
517
518   return true;
519 }
520
521 std::string DatabaseUtils::BuildLimitClause(int end, int start /* = 0 */)
522 {
523   std::ostringstream sql;
524   sql << " LIMIT ";
525   if (start > 0)
526   {
527     if (end > 0)
528     {
529       end = end - start;
530       if (end < 0)
531         end = 0;
532     }
533
534     sql << start << "," << end;
535   }
536   else
537     sql << end;
538
539   return sql.str();
540 }
541
542 int DatabaseUtils::GetField(Field field, MediaType mediaType, bool asIndex)
543 {
544   if (field == FieldNone || mediaType == MediaTypeNone)
545     return -1;
546
547   int index = -1;
548
549   if (mediaType == MediaTypeAlbum)
550   {
551     if (field == FieldId) return CMusicDatabase::album_idAlbum;
552     else if (field == FieldAlbum) return CMusicDatabase::album_strAlbum;
553     else if (field == FieldArtist || field == FieldAlbumArtist) return CMusicDatabase::album_strArtists;
554     else if (field == FieldGenre) return CMusicDatabase::album_strGenres;
555     else if (field == FieldYear) return CMusicDatabase::album_iYear;
556     else if (field == FieldMoods) return CMusicDatabase::album_strMoods;
557     else if (field == FieldStyles) return CMusicDatabase::album_strStyles;
558     else if (field == FieldThemes) return CMusicDatabase::album_strThemes;
559     else if (field == FieldReview) return CMusicDatabase::album_strReview;
560     else if (field == FieldMusicLabel) return CMusicDatabase::album_strLabel;
561     else if (field == FieldAlbumType) return CMusicDatabase::album_strType;
562     else if (field == FieldRating) return CMusicDatabase::album_iRating;
563     else if (field == FieldPlaycount) return CMusicDatabase::album_iTimesPlayed;
564   }
565   else if (mediaType == MediaTypeSong)
566   {
567     if (field == FieldId) return CMusicDatabase::song_idSong;
568     else if (field == FieldTitle) return CMusicDatabase::song_strTitle;
569     else if (field == FieldTrackNumber) return CMusicDatabase::song_iTrack;
570     else if (field == FieldTime) return CMusicDatabase::song_iDuration;
571     else if (field == FieldYear) return CMusicDatabase::song_iYear;
572     else if (field == FieldFilename) return CMusicDatabase::song_strFileName;
573     else if (field == FieldPlaycount) return CMusicDatabase::song_iTimesPlayed;
574     else if (field == FieldStartOffset) return CMusicDatabase::song_iStartOffset;
575     else if (field == FieldEndOffset) return CMusicDatabase::song_iEndOffset;
576     else if (field == FieldLastPlayed) return CMusicDatabase::song_lastplayed;
577     else if (field == FieldRating) return CMusicDatabase::song_rating;
578     else if (field == FieldComment) return CMusicDatabase::song_comment;
579     else if (field == FieldAlbum) return CMusicDatabase::song_strAlbum;
580     else if (field == FieldPath) return CMusicDatabase::song_strPath;
581     else if (field == FieldGenre) return CMusicDatabase::song_strGenres;
582     else if (field == FieldArtist || field == FieldAlbumArtist) return CMusicDatabase::song_strArtists;
583   }
584   else if (mediaType == MediaTypeArtist)
585   {
586     if (field == FieldId) return CMusicDatabase::artist_idArtist;
587     else if (field == FieldArtist) return CMusicDatabase::artist_strArtist;
588     else if (field == FieldGenre) return CMusicDatabase::artist_strGenres;
589     else if (field == FieldMoods) return CMusicDatabase::artist_strMoods;
590     else if (field == FieldStyles) return CMusicDatabase::artist_strStyles;
591     else if (field == FieldInstruments) return CMusicDatabase::artist_strInstruments;
592     else if (field == FieldBiography) return CMusicDatabase::artist_strBiography;
593     else if (field == FieldBorn) return CMusicDatabase::artist_strBorn;
594     else if (field == FieldBandFormed) return CMusicDatabase::artist_strFormed;
595     else if (field == FieldDisbanded) return CMusicDatabase::artist_strDisbanded;
596     else if (field == FieldDied) return CMusicDatabase::artist_strDied;
597   }
598   else if (mediaType == MediaTypeMusicVideo)
599   {
600     if (field == FieldId) return 0;
601     else if (field == FieldTitle) index = VIDEODB_ID_MUSICVIDEO_TITLE;
602     else if (field == FieldTime) index =  VIDEODB_ID_MUSICVIDEO_RUNTIME;
603     else if (field == FieldDirector) index =  VIDEODB_ID_MUSICVIDEO_DIRECTOR;
604     else if (field == FieldStudio) index =  VIDEODB_ID_MUSICVIDEO_STUDIOS;
605     else if (field == FieldYear) index = VIDEODB_ID_MUSICVIDEO_YEAR;
606     else if (field == FieldPlot) index =  VIDEODB_ID_MUSICVIDEO_PLOT;
607     else if (field == FieldAlbum) index = VIDEODB_ID_MUSICVIDEO_ALBUM;
608     else if (field == FieldArtist) index =  VIDEODB_ID_MUSICVIDEO_ARTIST;
609     else if (field == FieldGenre) index =  VIDEODB_ID_MUSICVIDEO_GENRE;
610     else if (field == FieldTrackNumber) index =  VIDEODB_ID_MUSICVIDEO_TRACK;
611     else if (field == FieldFilename) return VIDEODB_DETAILS_MUSICVIDEO_FILE;
612     else if (field == FieldPath) return VIDEODB_DETAILS_MUSICVIDEO_PATH;
613     else if (field == FieldPlaycount) return VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT;
614     else if (field == FieldLastPlayed) return VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED;
615     else if (field == FieldDateAdded) return VIDEODB_DETAILS_MUSICVIDEO_DATEADDED;
616
617     if (index < 0)
618       return index;
619
620     if (asIndex)
621     {
622       // see VideoDatabase.h
623       // the first field is the item's ID and the second is the item's file ID
624       index += 2;
625     }
626   }
627   else if (mediaType == MediaTypeMovie)
628   {
629     if (field == FieldId) return 0;
630     else if (field == FieldTitle) index = VIDEODB_ID_TITLE;
631     else if (field == FieldSortTitle) index = VIDEODB_ID_SORTTITLE;
632     else if (field == FieldPlot) index = VIDEODB_ID_PLOT;
633     else if (field == FieldPlotOutline) index = VIDEODB_ID_PLOTOUTLINE;
634     else if (field == FieldTagline) index = VIDEODB_ID_TAGLINE;
635     else if (field == FieldVotes) index = VIDEODB_ID_VOTES;
636     else if (field == FieldRating) index = VIDEODB_ID_RATING;
637     else if (field == FieldWriter) index = VIDEODB_ID_CREDITS;
638     else if (field == FieldYear) index = VIDEODB_ID_YEAR;
639     else if (field == FieldTime) index = VIDEODB_ID_RUNTIME;
640     else if (field == FieldMPAA) index = VIDEODB_ID_MPAA;
641     else if (field == FieldTop250) index = VIDEODB_ID_TOP250;
642     else if (field == FieldSet) return VIDEODB_DETAILS_MOVIE_SET_NAME;
643     else if (field == FieldGenre) index = VIDEODB_ID_GENRE;
644     else if (field == FieldDirector) index = VIDEODB_ID_DIRECTOR;
645     else if (field == FieldStudio) index = VIDEODB_ID_STUDIOS;
646     else if (field == FieldTrailer) index = VIDEODB_ID_TRAILER;
647     else if (field == FieldCountry) index = VIDEODB_ID_COUNTRY;
648     else if (field == FieldFilename) index = VIDEODB_DETAILS_MOVIE_FILE;
649     else if (field == FieldPath) return VIDEODB_DETAILS_MOVIE_PATH;
650     else if (field == FieldPlaycount) return VIDEODB_DETAILS_MOVIE_PLAYCOUNT;
651     else if (field == FieldLastPlayed) return VIDEODB_DETAILS_MOVIE_LASTPLAYED;
652     else if (field == FieldDateAdded) return VIDEODB_DETAILS_MOVIE_DATEADDED;
653
654     if (index < 0)
655       return index;
656
657     if (asIndex)
658     {
659       // see VideoDatabase.h
660       // the first field is the item's ID and the second is the item's file ID
661       index += 2;
662     }
663   }
664   else if (mediaType == MediaTypeTvShow)
665   {
666     if (field == FieldId) return 0;
667     else if (field == FieldTitle) index = VIDEODB_ID_TV_TITLE;
668     else if (field == FieldSortTitle) index = VIDEODB_ID_TV_SORTTITLE;
669     else if (field == FieldPlot) index = VIDEODB_ID_TV_PLOT;
670     else if (field == FieldTvShowStatus) index = VIDEODB_ID_TV_STATUS;
671     else if (field == FieldVotes) index = VIDEODB_ID_TV_VOTES;
672     else if (field == FieldRating) index = VIDEODB_ID_TV_RATING;
673     else if (field == FieldYear) index = VIDEODB_ID_TV_PREMIERED;
674     else if (field == FieldGenre) index = VIDEODB_ID_TV_GENRE;
675     else if (field == FieldMPAA) index = VIDEODB_ID_TV_MPAA;
676     else if (field == FieldStudio) index = VIDEODB_ID_TV_STUDIOS;
677     else if (field == FieldPath) return VIDEODB_DETAILS_TVSHOW_PATH;
678     else if (field == FieldDateAdded) return VIDEODB_DETAILS_TVSHOW_DATEADDED;
679     else if (field == FieldLastPlayed) return VIDEODB_DETAILS_TVSHOW_LASTPLAYED;
680     else if (field == FieldNumberOfEpisodes) return VIDEODB_DETAILS_TVSHOW_NUM_EPISODES;
681     else if (field == FieldNumberOfWatchedEpisodes) return VIDEODB_DETAILS_TVSHOW_NUM_WATCHED;
682     else if (field == FieldSeason) return VIDEODB_DETAILS_TVSHOW_NUM_SEASONS;
683
684     if (index < 0)
685       return index;
686
687     if (asIndex)
688     {
689       // see VideoDatabase.h
690       // the first field is the item's ID
691       index += 1;
692     }
693   }
694   else if (mediaType == MediaTypeEpisode)
695   {
696     if (field == FieldId) return 0;
697     else if (field == FieldTitle) index = VIDEODB_ID_EPISODE_TITLE;
698     else if (field == FieldPlot) index = VIDEODB_ID_EPISODE_PLOT;
699     else if (field == FieldVotes) index = VIDEODB_ID_EPISODE_VOTES;
700     else if (field == FieldRating) index = VIDEODB_ID_EPISODE_RATING;
701     else if (field == FieldWriter) index = VIDEODB_ID_EPISODE_CREDITS;
702     else if (field == FieldAirDate) index = VIDEODB_ID_EPISODE_AIRED;
703     else if (field == FieldTime) index = VIDEODB_ID_EPISODE_RUNTIME;
704     else if (field == FieldDirector) index = VIDEODB_ID_EPISODE_DIRECTOR;
705     else if (field == FieldSeason) index = VIDEODB_ID_EPISODE_SEASON;
706     else if (field == FieldEpisodeNumber) index = VIDEODB_ID_EPISODE_EPISODE;
707     else if (field == FieldUniqueId) index = VIDEODB_ID_EPISODE_UNIQUEID;
708     else if (field == FieldEpisodeNumberSpecialSort) index = VIDEODB_ID_EPISODE_SORTEPISODE;
709     else if (field == FieldSeasonSpecialSort) index = VIDEODB_ID_EPISODE_SORTSEASON;
710     else if (field == FieldFilename) return VIDEODB_DETAILS_EPISODE_FILE;
711     else if (field == FieldPath) return VIDEODB_DETAILS_EPISODE_PATH;
712     else if (field == FieldPlaycount) return VIDEODB_DETAILS_EPISODE_PLAYCOUNT;
713     else if (field == FieldLastPlayed) return VIDEODB_DETAILS_EPISODE_LASTPLAYED;
714     else if (field == FieldDateAdded) return VIDEODB_DETAILS_EPISODE_DATEADDED;
715     else if (field == FieldTvShowTitle) return VIDEODB_DETAILS_EPISODE_TVSHOW_NAME;
716     else if (field == FieldStudio) return VIDEODB_DETAILS_EPISODE_TVSHOW_STUDIO;
717     else if (field == FieldYear) return VIDEODB_DETAILS_EPISODE_TVSHOW_AIRED;
718     else if (field == FieldMPAA) return VIDEODB_DETAILS_EPISODE_TVSHOW_MPAA;
719
720     if (index < 0)
721       return index;
722
723     if (asIndex)
724     {
725       // see VideoDatabase.h
726       // the first field is the item's ID and the second is the item's file ID
727       index += 2;
728     }
729   }
730
731   return index;
732 }