Use min and max size when searching files.
[mediadatabase.git] / libdb / sqlite.c
blob479ac72bf110707b784766c29102537ae14cb687
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * $Id: sqlite.c,v 1.11 2004/09/18 21:32:34 nedko Exp $
6 * DESCRIPTION:
7 * SQLite backend implementation.
9 * AUTHOR:
10 * Nedko Arnaudov <nedko@users.sourceforge.net>
12 * LICENSE:
13 * GNU GENERAL PUBLIC LICENSE version 2
15 *****************************************************************************/
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <assert.h>
23 #include "../result.h"
24 #include "internal.h"
25 #include "memory.h"
27 #define MEDIADB_SQLITE_MEDIA_TABLE "media"
28 #define MEDIADB_SQLITE_FILES_TABLE "files"
29 #define MEDIADB_SQLITE_LOCATIONS_TABLE "locations"
30 #define MEDIADB_SQLITE_LOCATION_TYPES_TABLE "location_types"
32 //#define DUMMY_SQL_QUERIES
33 #define FORMATTING_BUFFER_SIZE 10240
35 #define MEDIADB_SQLITE_PMM_EXACT_CASE_INSENSITIVE 1
36 #define MEDIADB_SQLITE_PMM_EXACT_CASE_SENSITIVE 2
37 #define MEDIADB_SQLITE_PMM_LIKE_CASE_INSENSITIVE 3
38 #define MEDIADB_SQLITE_PMM_LIKE_CASE_SENSITIVE 4
39 #define MEDIADB_SQLITE_PMM_REGEXP_CASE_INSENSITIVE 5
40 #define MEDIADB_SQLITE_PMM_REGEXP_CASE_SENSITIVE 6
42 static struct mediadb_pattern_match_method
43 mediadb_sqlite_pattern_match_methods[] =
46 MEDIADB_SQLITE_PMM_EXACT_CASE_INSENSITIVE,
47 "exact - case insensitive",
48 "Match exactly, ignore case",
49 "Char by char match"
53 MEDIADB_SQLITE_PMM_EXACT_CASE_SENSITIVE,
54 "exact - case sensitive",
55 "Match exactly, do not ignore case",
56 "Char by char match"
60 MEDIADB_SQLITE_PMM_LIKE_CASE_INSENSITIVE,
61 "SQL \"LIKE\" - case insensitive",
62 "Traditional SQL \"LIKE\" oprator pattern matching, ignore case",
63 "SQL pattern matching allows you to use `_' to match any single character "
64 "and `%' to match an arbitrary number of characters (including zero characters). "
65 "LIKE pattern match succeeds only if the pattern matches the entire value."
69 MEDIADB_SQLITE_PMM_LIKE_CASE_SENSITIVE,
70 "SQL \"LIKE\" - case sensitive",
71 "Traditional SQL \"LIKE\" oprator pattern matching, do not ignore case",
72 "SQL pattern matching allows you to use `_' to match any single character "
73 "and `%' to match an arbitrary number of characters (including zero characters). "
74 "LIKE pattern match succeeds only if the pattern matches the entire value."
78 MEDIADB_PMM_NULL,
79 NULL,
80 NULL
84 static
85 void
86 set_error_message(
87 mediadb_sqlite *pDB,
88 const char *pszFormat,
89 ...)
91 mediadb_result r;
92 size_t s;
93 va_list argList;
94 char Buffer[FORMATTING_BUFFER_SIZE];
96 va_start(argList, pszFormat);
97 vsnprintf(Buffer, FORMATTING_BUFFER_SIZE-1, pszFormat, argList);
98 va_end(argList);
100 s = strlen(Buffer);
102 r = maybe_enlarge_buffer(
103 &pDB->pErrorMsgBuffer,
104 &pDB->sizeErrorMsgBuffer,
105 s+1);
106 if (MEDIADB_IS_ERROR(r))
108 if (pDB->sizeErrorMsgBuffer > 0)
110 pDB->pErrorMsgBuffer[0] = 0;
114 memcpy(pDB->pErrorMsgBuffer, Buffer, s + 1);
117 static
118 void
119 reset_error_message(
120 mediadb_sqlite *pDB)
122 if (pDB->pErrorMsgBuffer != NULL)
124 pDB->pErrorMsgBuffer[0] = 0;
128 const char *
129 mediadb_sqlite_get_error_message(
130 mediadb_sqlite *pDB)
132 if (pDB->pErrorMsgBuffer == NULL)
134 return "";
137 return pDB->pErrorMsgBuffer;
140 mediadb_result
141 mediadb_sqlite_open(
142 mediadb_sqlite *pDB,
143 const char *pszHost,
144 const char *pszUser,
145 const char *pszPass,
146 const char *pszDB)
148 sqlite * hDB;
149 char *pErrorMsg;
151 pDB->pErrorMsgBuffer = NULL;
152 pDB->sizeErrorMsgBuffer = 0;
154 hDB = sqlite_open(
155 pszDB,
157 &pErrorMsg);
158 if (hDB == NULL)
160 set_error_message(
161 pDB,
162 "Failed to open database. Error: %s",
163 pErrorMsg);
165 free(pErrorMsg);
167 return MEDIADB_FAIL;
170 pDB->hDB = hDB;
172 reset_error_message(pDB);
174 return MEDIADB_OK;
177 mediadb_result
178 mediadb_sqlite_close(
179 mediadb_sqlite *pDB)
181 if (pDB->pErrorMsgBuffer != NULL)
183 free(pDB->pErrorMsgBuffer);
186 sqlite_close(pDB->hDB);
188 return MEDIADB_OK;
191 mediadb_result
192 mediadb_sqlite_media_add_new(
193 mediadb_sqlite *pDB,
194 const char *pszName,
195 const char *pszComment,
196 mediadb_mediatype nType,
197 mediadb_uint *pnNewMediaID)
199 int nRet;
200 char *pErrorMsg;
201 my_ulonglong nMediaID;
203 nRet = sqlite_exec_printf(
204 pDB->hDB,
205 "INSERT INTO " MEDIADB_SQLITE_MEDIA_TABLE
206 " (catid,type,added,info1,info2,name,comment,location)"
207 " VALUES (0,%u,0,0,0,'%q','%q','0')",
210 &pErrorMsg,
211 (unsigned int)nType,
212 pszName,
213 pszComment);
214 if (nRet != SQLITE_OK)
216 set_error_message(
217 pDB,
218 "Failed to execute SQL query. Error: %s",
219 pErrorMsg);
221 free(pErrorMsg);
223 return MEDIADB_FAIL;
226 nMediaID = sqlite_last_insert_rowid(pDB->hDB);
227 if (nMediaID == 0ULL)
229 set_error_message(
230 pDB,
231 "Invalid media ID 0 after media INSERT");
232 return MEDIADB_FAIL;
235 *pnNewMediaID = nMediaID;
237 reset_error_message(pDB);
239 return MEDIADB_OK;
242 mediadb_result
243 mediadb_sqlite_media_update_properties(
244 mediadb_sqlite *pDB,
245 mediadb_uint nMediaID,
246 mediadb_uint nTimeAdded,
247 mediadb_uint nTotalFiles,
248 mediadb_uint nTotalSize)
250 int nRet;
251 char *pErrorMsg;
253 nRet = sqlite_exec_printf(
254 pDB->hDB,
255 "UPDATE " MEDIADB_SQLITE_MEDIA_TABLE " SET added=%u, info1=%u, info2=%u WHERE mediaid = %u",
258 &pErrorMsg,
259 (unsigned int)nTimeAdded,
260 (unsigned int)nTotalFiles,
261 (unsigned int)nTotalSize,
262 (unsigned int)nMediaID);
263 if (nRet != SQLITE_OK)
265 set_error_message(
266 pDB,
267 "Failed to execute SQL query. Error: %s",
268 pErrorMsg);
270 free(pErrorMsg);
272 return MEDIADB_FAIL;
275 reset_error_message(pDB);
277 return MEDIADB_OK;
280 mediadb_result
281 mediadb_sqlite_file_add_new(
282 mediadb_sqlite *pDB,
283 mediadb_uint nMediaID,
284 mediadb_filetype Filetype,
285 const char *pszPath,
286 const char *pszName,
287 mediadb_uint nFileSize,
288 mediadb_uint nFileTime)
290 int nRet;
291 char *pErrorMsg;
293 if (Filetype != MEDIADB_FILETYPE_FILE &&
294 Filetype != MEDIADB_FILETYPE_DIR)
296 set_error_message(
297 pDB,
298 "Cannot add file of unknown type");
299 return MEDIADB_INVAL_ARG;
302 nRet = sqlite_exec_printf(
303 pDB->hDB,
304 "INSERT INTO " MEDIADB_SQLITE_FILES_TABLE " (mediaid,size,time,path,name) VALUES (%u,%u,%u,'%q','%q%s')",
307 &pErrorMsg,
308 (unsigned int)nMediaID,
309 (unsigned int)nFileSize,
310 (unsigned int)nFileTime,
311 pszPath,
312 pszName,
313 (Filetype == MEDIADB_FILETYPE_DIR)?"/":"");
314 if (nRet != SQLITE_OK)
316 set_error_message(
317 pDB,
318 "Failed to execute SQL query. Error: %s",
319 pErrorMsg);
321 free(pErrorMsg);
323 return MEDIADB_FAIL;
326 reset_error_message(pDB);
328 return MEDIADB_OK;
331 mediadb_result
332 mediadb_sqlite_media_get_properties(
333 mediadb_sqlite *pDB,
334 mediadb_uint nMediaID,
335 mediadb_uint *pnTimeAdded,
336 mediadb_mediatype *pnType,
337 mediadb_uint *pnLocationID,
338 char **ppszTitle)
340 int nRet;
341 char *pErrorMsg;
342 char **pResult;
343 int nRows, nColumns;
345 nRet = sqlite_get_table_printf(
346 pDB->hDB,
347 "SELECT added, type, name, location FROM " MEDIADB_SQLITE_MEDIA_TABLE " WHERE mediaid = %u",
348 &pResult,
349 &nRows,
350 &nColumns,
351 &pErrorMsg,
352 (unsigned int)nMediaID);
353 if (nRet != SQLITE_OK)
355 set_error_message(
356 pDB,
357 "Failed to execute SQL query. Error: %s",
358 pErrorMsg);
360 free(pErrorMsg);
362 return MEDIADB_FAIL;
365 if (nColumns != 4 ||
366 nRows != 1)
368 set_error_message(
369 pDB,
370 "SQL query returned unexpected result (%d, %d).",
371 nColumns,
372 nRows);
374 sqlite_free_table(pResult);
376 free(pErrorMsg);
378 return MEDIADB_FAIL;
381 if (pResult[4] == NULL)
383 *pnTimeAdded = 0;
385 else
387 *pnTimeAdded = strtoull(pResult[4], NULL, 10);
390 if (pResult[5] == NULL)
392 *pnType = MEDIADB_MT_UNKNOWN;
394 else
396 *pnType = strtoull(pResult[5], NULL, 10);
399 if (pResult[6] == NULL)
401 *ppszTitle = strdup("");
403 else
405 *ppszTitle = strdup(pResult[6]);
408 if (pResult[7] == NULL)
410 *pnLocationID = MEDIADB_MT_UNKNOWN;
412 else
414 *pnLocationID = strtoull(pResult[7], NULL, 10);
417 sqlite_free_table(pResult);
419 reset_error_message(pDB);
421 return MEDIADB_OK;
424 mediadb_result
425 mediadb_sqlite_location_get_properties(
426 mediadb_sqlite *pDB,
427 mediadb_uint nLocationID,
428 mediadb_uint *pnLocationTypeID,
429 char **ppszDescription)
431 int nRet;
432 char *pErrorMsg;
433 char **pResult;
434 int nRows, nColumns;
436 nRet = sqlite_get_table_printf(
437 pDB->hDB,
438 "SELECT type, description FROM " MEDIADB_SQLITE_LOCATIONS_TABLE " WHERE id = %u",
439 &pResult,
440 &nRows,
441 &nColumns,
442 &pErrorMsg,
443 (unsigned int)nLocationID);
444 if (nRet != SQLITE_OK)
446 set_error_message(
447 pDB,
448 "Failed to execute SQL query. Error: %s",
449 pErrorMsg);
451 free(pErrorMsg);
453 return MEDIADB_FAIL;
456 if (nColumns != 2 ||
457 nRows != 1)
459 set_error_message(
460 pDB,
461 "SQL query returned unexpected result (%d, %d).",
462 nColumns,
463 nRows);
465 sqlite_free_table(pResult);
467 free(pErrorMsg);
469 return MEDIADB_FAIL;
472 if (pResult[2] == NULL)
474 *pnLocationTypeID = 0;
476 else
478 *pnLocationTypeID = strtoull(pResult[2], NULL, 10);
481 if (pResult[3] == NULL)
483 *ppszDescription = strdup("");
485 else
487 *ppszDescription = strdup(pResult[3]);
490 sqlite_free_table(pResult);
492 reset_error_message(pDB);
494 return MEDIADB_OK;
497 mediadb_result
498 mediadb_sqlite_location_type_get_properties(
499 mediadb_sqlite *pDB,
500 mediadb_uint nLocationTypeID,
501 char **ppszDescription)
503 int nRet;
504 char *pErrorMsg;
505 char **pResult;
506 int nRows, nColumns;
508 nRet = sqlite_get_table_printf(
509 pDB->hDB,
510 "SELECT description FROM " MEDIADB_SQLITE_LOCATION_TYPES_TABLE " WHERE id = %u",
511 &pResult,
512 &nRows,
513 &nColumns,
514 &pErrorMsg,
515 (unsigned int)nLocationTypeID);
516 if (nRet != SQLITE_OK)
518 set_error_message(
519 pDB,
520 "Failed to execute SQL query. Error: %s",
521 pErrorMsg);
523 free(pErrorMsg);
525 return MEDIADB_FAIL;
528 if (nColumns != 1 ||
529 nRows != 1)
531 set_error_message(
532 pDB,
533 "SQL query returned unexpected result (%d, %d).",
534 nColumns,
535 nRows);
537 sqlite_free_table(pResult);
539 free(pErrorMsg);
541 return MEDIADB_FAIL;
544 if (pResult[1] == NULL)
546 *ppszDescription = strdup("");
548 else
550 *ppszDescription = strdup(pResult[1]);
553 sqlite_free_table(pResult);
555 reset_error_message(pDB);
557 return MEDIADB_OK;
560 mediadb_result
561 mediadb_sqlite_media_get_properties_data(
562 mediadb_sqlite *pDB,
563 mediadb_uint nMediaID,
564 mediadb_uint *pnTotalFiles,
565 mediadb_uint *pnTotalSize)
567 int nRet;
568 char *pErrorMsg;
569 char **pResult;
570 int nRows, nColumns;
572 nRet = sqlite_get_table_printf(
573 pDB->hDB,
574 "SELECT info1, info2 FROM " MEDIADB_SQLITE_MEDIA_TABLE " WHERE mediaid = %u",
575 &pResult,
576 &nRows,
577 &nColumns,
578 &pErrorMsg,
579 (unsigned int)nMediaID);
580 if (nRet != SQLITE_OK)
582 set_error_message(
583 pDB,
584 "Failed to execute SQL query. Error: %s",
585 pErrorMsg);
587 free(pErrorMsg);
589 return MEDIADB_FAIL;
592 if (nColumns != 2 ||
593 nRows != 1)
595 set_error_message(
596 pDB,
597 "SQL query returned unexpected result (%d, %d).",
598 nColumns,
599 nRows);
601 sqlite_free_table(pResult);
603 free(pErrorMsg);
605 return MEDIADB_FAIL;
608 if (pResult[2] == NULL)
610 *pnTotalFiles = 0;
612 else
614 *pnTotalFiles = strtoull(pResult[2], NULL, 10);
617 if (pResult[3] == NULL)
619 *pnTotalSize = 0;
621 else
623 *pnTotalSize = strtoull(pResult[3], NULL, 10);
626 sqlite_free_table(pResult);
628 reset_error_message(pDB);
630 return MEDIADB_OK;
633 mediadb_result
634 mediadb_sqlite_delete_media_files(
635 mediadb_sqlite *pDB,
636 mediadb_uint nMediaID)
638 int nRet;
639 char *pErrorMsg;
641 nRet = sqlite_exec_printf(
642 pDB->hDB,
643 "DELETE FROM " MEDIADB_SQLITE_FILES_TABLE " WHERE mediaid = %u",
646 &pErrorMsg,
647 (unsigned int)nMediaID);
648 if (nRet != SQLITE_OK)
650 set_error_message(
651 pDB,
652 "Failed to execute SQL query. Error: %s",
653 pErrorMsg);
655 free(pErrorMsg);
657 return MEDIADB_FAIL;
660 reset_error_message(pDB);
662 return MEDIADB_OK;
665 mediadb_result
666 mediadb_sqlite_media_update_name(
667 mediadb_sqlite *pDB,
668 mediadb_uint nMediaID,
669 const char *pszName)
671 int nRet;
672 char *pErrorMsg;
674 nRet = sqlite_exec_printf(
675 pDB->hDB,
676 "UPDATE " MEDIADB_SQLITE_MEDIA_TABLE " SET name = '%q' WHERE mediaid = %u",
679 &pErrorMsg,
680 pszName,
681 (unsigned int)nMediaID);
682 if (nRet != SQLITE_OK)
684 set_error_message(
685 pDB,
686 "Failed to execute SQL query. Error: %s",
687 pErrorMsg);
689 free(pErrorMsg);
691 return MEDIADB_FAIL;
694 reset_error_message(pDB);
696 return MEDIADB_OK;
699 struct mediadb_media_callback_context
701 mediadb_media_callback pCallback;
702 void *pUserContext;
703 sqlite * hDB;
707 mediadb_sqlite_media_get_callback(
708 void *pArg,
709 int argc,
710 char **argv,
711 char **columnNames)
713 long nMediaID;
714 const char *pszName;
715 const char *pszComment;
716 long nAdded;
717 long nTotalFiles;
718 long nTotalSize;
719 long nLocationID;
720 mediadb_mediatype nType;
721 char strLocation[1000];
722 char *pszLocation;
723 char *pLocationDescriptionBuffer;
724 size_t s;
725 int nRet;
726 char *pErrorMsg;
727 char **pResult;
728 int nRows, nColumns;
730 pLocationDescriptionBuffer = NULL;
732 if (argv == NULL)
733 return 0;
735 if (argc != 9)
736 return SQLITE_ABORT;
738 /* mediaid */
739 if (argv[0] == NULL)
740 return SQLITE_ABORT;
742 nMediaID = atol(argv[0]);
743 if (nMediaID <= 0)
744 return SQLITE_ABORT;
746 /* catid */
747 /* not used */
749 /* type */
750 if (argv[2] == NULL)
751 return SQLITE_ABORT;
752 nType = atol(argv[2]);
753 if (nAdded <= 0)
755 nType = MEDIADB_MT_EMPTY;
758 /* added */
759 if (argv[3] == NULL)
760 return SQLITE_ABORT;
762 nAdded = atol(argv[3]);
763 if (nAdded <= 0)
764 return SQLITE_ABORT;
766 /* info1 */
767 if (argv[4] == NULL)
768 return SQLITE_ABORT;
769 nTotalFiles = atol(argv[4]);
770 if (nTotalFiles < 0)
771 return SQLITE_ABORT;
773 /* info2 */
774 if (argv[5] == NULL)
775 return SQLITE_ABORT;
776 nTotalSize = atol(argv[5]);
777 if (nTotalSize < 0)
778 return SQLITE_ABORT;
780 /* name */
781 if (argv[6] == NULL)
782 return SQLITE_ABORT;
784 pszName = argv[6];
786 /* comment */
787 if (argv[7] == NULL)
788 return SQLITE_ABORT;
790 pszComment = argv[7];
792 /* location */
793 if (argv[8] == NULL)
794 return SQLITE_ABORT;
795 nLocationID = atol(argv[8]);
796 if (nLocationID < 0)
797 return SQLITE_ABORT;
799 nRet = sqlite_get_table_printf(
800 ((struct mediadb_media_callback_context *) pArg)->hDB,
801 "SELECT description FROM " MEDIADB_SQLITE_LOCATIONS_TABLE " WHERE id = %u",
802 &pResult,
803 &nRows,
804 &nColumns,
805 &pErrorMsg,
806 (unsigned int)nLocationID);
807 if (nRet != SQLITE_OK)
809 sprintf(strLocation,
810 "Cannot get description for location with ID \"%ld\" (SQLite error \"%s\")",
811 nLocationID,
812 pErrorMsg);
814 free(pErrorMsg);
816 pszLocation = strLocation;
818 else if (nColumns != 1 ||
819 nRows != 1)
821 sprintf(strLocation,
822 "Cannot get description for location with ID \"%ld\" (SQLite query returned unexpected result (%d, %d).",
823 nLocationID,
824 nColumns,
825 nRows);
826 sqlite_free_table(pResult);
827 pszLocation = strLocation;
829 else if (pResult[1] == NULL)
831 sprintf(strLocation,
832 "Cannot get description for location with ID \"%ld\" (SQLite query returned NULL)",
833 nLocationID);
834 sqlite_free_table(pResult);
835 pszLocation = strLocation;
837 else
839 s = strlen(pResult[1]);
841 if (s < sizeof(strLocation))
843 memcpy(strLocation, pResult[1], s);
844 strLocation[s] = 0;
845 pszLocation = strLocation;
847 else
849 pLocationDescriptionBuffer = malloc(s+1);
850 if (pLocationDescriptionBuffer == NULL)
852 sprintf(strLocation,
853 "Cannot get description for location with ID \"%ld\" (out of memory)",
854 nLocationID);
855 pszLocation = strLocation;
857 else
859 memcpy(pLocationDescriptionBuffer, pResult[1], s);
860 pLocationDescriptionBuffer[s] = 0;
861 pszLocation = pLocationDescriptionBuffer;
865 sqlite_free_table(pResult);
868 ((struct mediadb_media_callback_context *) pArg)->pCallback(
869 ((struct mediadb_media_callback_context *) pArg)->pUserContext,
870 (mediadb_uint)nMediaID,
871 nType,
872 pszName,
873 pszComment,
874 (mediadb_uint)nAdded,
875 (mediadb_uint)nTotalFiles,
876 (mediadb_uint)nTotalSize,
877 (mediadb_uint)nLocationID,
878 pszLocation);
880 if (pLocationDescriptionBuffer != NULL)
882 free(pLocationDescriptionBuffer);
885 return 0;
888 mediadb_result
889 mediadb_sqlite_media_get_all(
890 mediadb_sqlite *pDB,
891 mediadb_media_callback pCallback,
892 void *pUserContext)
894 struct mediadb_media_callback_context context;
895 int nRet;
896 char *pErrorMsg;
898 context.pCallback = pCallback;
899 context.pUserContext = pUserContext;
900 context.hDB = pDB->hDB;
902 nRet = sqlite_exec(
903 pDB->hDB,
904 "SELECT * FROM " MEDIADB_SQLITE_MEDIA_TABLE " ORDER BY mediaid ASC",
905 mediadb_sqlite_media_get_callback,
906 &context,
907 &pErrorMsg);
908 if (nRet != SQLITE_OK)
910 set_error_message(
911 pDB,
912 "Failed to execute SQL query. Error: %s",
913 pErrorMsg);
915 free(pErrorMsg);
917 return MEDIADB_FAIL;
920 reset_error_message(pDB);
922 return MEDIADB_OK;
925 struct mediadb_files_callback_context
927 mediadb_files_callback pCallback;
928 void *pUserContext;
932 mediadb_sqlite_files_get_callback(
933 void *pArg,
934 int argc,
935 char **argv,
936 char **columnNames)
938 char *pszName;
939 char *pszPath;
940 long nSize;
941 long nTime;
942 mediadb_filetype Filetype = MEDIADB_FILETYPE_FILE;
943 size_t s;
945 if (argv == NULL)
946 return 0;
948 if (argc != 4)
949 return SQLITE_ABORT;
951 /* path */
952 if (argv[0] == NULL)
953 return SQLITE_ABORT;
955 pszPath = argv[0];
957 /* name */
958 if (argv[1] == NULL)
959 return SQLITE_ABORT;
961 pszName = argv[1];
963 /* size */
964 if (argv[2] == NULL)
965 return SQLITE_ABORT;
967 nSize = atol(argv[2]);
969 /* time */
970 if (argv[3] == NULL)
971 return SQLITE_ABORT;
973 nTime = atol(argv[3]);
975 s = strlen(pszName);
977 if (s > 1 && pszName[s-1] == '/')
979 Filetype = MEDIADB_FILETYPE_DIR;
980 pszName[s-1] = 0;
983 ((struct mediadb_files_callback_context *) pArg)->pCallback(
984 ((struct mediadb_files_callback_context *) pArg)->pUserContext,
985 pszPath,
986 pszName,
987 Filetype,
988 (mediadb_uint)nSize,
989 (mediadb_uint)nTime);
991 return 0;
994 mediadb_result
995 mediadb_sqlite_files_get(
996 mediadb_sqlite *pDB,
997 mediadb_uint nMediaID,
998 const char *pszPath,
999 mediadb_files_callback pCallback,
1000 void *pUserContext)
1002 struct mediadb_files_callback_context context;
1003 int nRet;
1004 char *pErrorMsg;
1006 context.pCallback = pCallback;
1007 context.pUserContext = pUserContext;
1009 nRet = sqlite_exec_printf(
1010 pDB->hDB,
1011 "SELECT path, name, size, time FROM " MEDIADB_SQLITE_FILES_TABLE " WHERE mediaid = %u AND path = '%q/'",
1012 mediadb_sqlite_files_get_callback,
1013 &context,
1014 &pErrorMsg,
1015 (unsigned int)nMediaID,
1016 pszPath?pszPath:"");
1017 if (nRet != SQLITE_OK)
1019 set_error_message(
1020 pDB,
1021 "Failed to execute SQL query. Error: %s",
1022 pErrorMsg);
1024 free(pErrorMsg);
1026 return MEDIADB_FAIL;
1029 reset_error_message(pDB);
1031 return MEDIADB_OK;
1034 mediadb_result
1035 mediadb_sqlite_get_pattern_match_methods(
1036 mediadb_sqlite *pDB,
1037 const struct mediadb_pattern_match_method **ppPMM)
1039 *ppPMM = mediadb_sqlite_pattern_match_methods;
1040 return MEDIADB_OK;
1043 struct mediadb_files_search_callback_context
1045 mediadb_files_search_callback pCallback;
1046 void *pUserContext;
1047 sqlite * hDB;
1051 mediadb_sqlite_files_search_callback(
1052 void *pArg,
1053 int argc,
1054 char **argv,
1055 char **columnNames)
1057 char *pszName;
1058 char *pszPath;
1059 long nSize;
1060 long nTime;
1061 long nMediaID;
1062 long nLocationID;
1063 mediadb_filetype Filetype = MEDIADB_FILETYPE_FILE;
1064 size_t s;
1065 char strMediaName[1000];
1066 char *pszMediaName;
1067 char *pMediaNameBuffer;
1068 char strLocation[1000];
1069 char *pszLocation;
1070 char *pLocationDescriptionBuffer;
1071 int nRet;
1072 char *pErrorMsg;
1073 char **pResult;
1074 int nRows, nColumns;
1076 pMediaNameBuffer = NULL;
1077 pLocationDescriptionBuffer = NULL;
1079 if (argv == NULL)
1080 return 0;
1082 if (argc != 5)
1083 return SQLITE_ABORT;
1085 /* mediaid */
1086 if (argv[0] == NULL)
1087 return SQLITE_ABORT;
1089 nMediaID = atol(argv[0]);
1091 /* path */
1092 if (argv[1] == NULL)
1093 return SQLITE_ABORT;
1095 pszPath = argv[1];
1097 /* name */
1098 if (argv[2] == NULL)
1099 return SQLITE_ABORT;
1101 pszName = argv[2];
1103 /* size */
1104 if (argv[3] == NULL)
1105 return SQLITE_ABORT;
1107 nSize = atol(argv[3]);
1109 /* time */
1110 if (argv[4] == NULL)
1111 return SQLITE_ABORT;
1113 nTime = atol(argv[4]);
1115 s = strlen(pszName);
1117 if (s > 1 && pszName[s-1] == '/')
1119 Filetype = MEDIADB_FILETYPE_DIR;
1120 pszName[s-1] = 0;
1123 nLocationID = -1;
1125 nRet = sqlite_get_table_printf(
1126 ((struct mediadb_files_search_callback_context *) pArg)->hDB,
1127 "SELECT name, location FROM " MEDIADB_SQLITE_MEDIA_TABLE " WHERE mediaid = %u",
1128 &pResult,
1129 &nRows,
1130 &nColumns,
1131 &pErrorMsg,
1132 (unsigned int)nMediaID);
1133 if (nRet != SQLITE_OK)
1135 sprintf(strMediaName,
1136 "Cannot get name of media with ID \"%ld\" (SQLite error \"%s\")",
1137 nMediaID,
1138 pErrorMsg);
1140 free(pErrorMsg);
1142 pszMediaName = strMediaName;
1144 else if (nColumns != 2 ||
1145 nRows != 1)
1147 sprintf(strMediaName,
1148 "Cannot get name of media ID \"%ld\" (SQLite query returned unexpected result (%d, %d).",
1149 nMediaID,
1150 nColumns,
1151 nRows);
1152 sqlite_free_table(pResult);
1153 pszMediaName = strMediaName;
1155 else
1157 if (pResult[2] == NULL)
1159 sprintf(strMediaName,
1160 "Cannot get name of media ID \"%ld\" (SQLite query returned NULL)",
1161 nMediaID);
1162 sqlite_free_table(pResult);
1163 pszMediaName = strMediaName;
1165 else
1167 s = strlen(pResult[2]);
1169 if (s < sizeof(strMediaName))
1171 memcpy(strMediaName, pResult[2], s);
1172 strMediaName[s] = 0;
1173 pszMediaName = strMediaName;
1175 else
1177 pMediaNameBuffer = malloc(s+1);
1178 if (pMediaNameBuffer == NULL)
1180 sprintf(strMediaName,
1181 "Cannot get description for location with ID \"%ld\" (out of memory)",
1182 nMediaID);
1183 pszMediaName = strMediaName;
1185 else
1187 memcpy(pMediaNameBuffer, pResult[2], s);
1188 pMediaNameBuffer[s] = 0;
1189 pszMediaName = pMediaNameBuffer;
1194 if (pResult[3] != NULL)
1196 nLocationID = atol(pResult[3]);
1199 sqlite_free_table(pResult);
1202 if (nLocationID >= 0)
1204 nRet = sqlite_get_table_printf(
1205 ((struct mediadb_media_callback_context *) pArg)->hDB,
1206 "SELECT description FROM " MEDIADB_SQLITE_LOCATIONS_TABLE " WHERE id = %u",
1207 &pResult,
1208 &nRows,
1209 &nColumns,
1210 &pErrorMsg,
1211 (unsigned int)nLocationID);
1212 if (nRet != SQLITE_OK)
1214 sprintf(strLocation,
1215 "Cannot get description for location with ID \"%ld\" (SQLite error \"%s\")",
1216 nLocationID,
1217 pErrorMsg);
1219 free(pErrorMsg);
1221 pszLocation = strLocation;
1223 else if (nColumns != 1 ||
1224 nRows != 1)
1226 sprintf(strLocation,
1227 "Cannot get description for location with ID \"%ld\" (SQLite query returned unexpected result (%d, %d).",
1228 nLocationID,
1229 nColumns,
1230 nRows);
1231 sqlite_free_table(pResult);
1232 pszLocation = strLocation;
1234 else if (pResult[1] == NULL)
1236 sprintf(strLocation,
1237 "Cannot get description for location with ID \"%ld\" (SQLite query returned NULL)",
1238 nLocationID);
1239 sqlite_free_table(pResult);
1240 pszLocation = strLocation;
1242 else
1244 s = strlen(pResult[1]);
1246 if (s < sizeof(strLocation))
1248 memcpy(strLocation, pResult[1], s);
1249 strLocation[s] = 0;
1250 pszLocation = strLocation;
1252 else
1254 pLocationDescriptionBuffer = malloc(s+1);
1255 if (pLocationDescriptionBuffer == NULL)
1257 sprintf(strLocation,
1258 "Cannot get description for location with ID \"%ld\" (out of memory)",
1259 nLocationID);
1260 pszLocation = strLocation;
1262 else
1264 memcpy(pLocationDescriptionBuffer, pResult[1], s);
1265 pLocationDescriptionBuffer[s] = 0;
1266 pszLocation = pLocationDescriptionBuffer;
1270 sqlite_free_table(pResult);
1273 else
1275 pszLocation = "Cannot retrieve location from database";
1278 ((struct mediadb_files_search_callback_context *) pArg)->pCallback(
1279 ((struct mediadb_files_search_callback_context *) pArg)->pUserContext,
1280 nMediaID,
1281 MEDIADB_MT_DATA,
1282 pszMediaName,
1283 pszLocation,
1284 pszPath,
1285 pszName,
1286 Filetype,
1287 (mediadb_uint)nSize,
1288 (mediadb_uint)nTime);
1290 if (pMediaNameBuffer != NULL)
1292 free(pMediaNameBuffer);
1295 if (pLocationDescriptionBuffer != NULL)
1297 free(pLocationDescriptionBuffer);
1300 return 0;
1303 const char *
1304 mediadb_sqlite_get_match_keyword(mediadb_uint nPMMID)
1306 switch (nPMMID)
1308 case MEDIADB_SQLITE_PMM_EXACT_CASE_INSENSITIVE:
1309 return " == ";
1310 case MEDIADB_SQLITE_PMM_LIKE_CASE_INSENSITIVE:
1311 return " LIKE ";
1314 assert(0);
1315 return "XXX_BUG_XXX";
1318 mediadb_result
1319 mediadb_sqlite_files_search(
1320 mediadb_sqlite *pDB,
1321 mediadb_uint nFilenamePMMID,
1322 const char *pszFilenamePattern,
1323 mediadb_uint nPathPMMID,
1324 const char *pszPathPattern,
1325 const mediadb_uint *pnMinSize,
1326 const mediadb_uint *pnMaxSize,
1327 mediadb_files_search_callback pCallback,
1328 void *pUserContext)
1330 struct mediadb_files_search_callback_context context;
1331 int nRet;
1332 char *pErrorMsg;
1333 mediadb_result r;
1334 char *pszWhere;
1335 size_t sizeWhereAllocated;
1336 size_t sizeWhereUsed;
1337 size_t sizeSearchCriteria;
1338 size_t sizeAND;
1339 int nCount;
1340 const char *pszAND;
1341 char *pszTemp;
1343 context.pCallback = pCallback;
1344 context.pUserContext = pUserContext;
1345 context.hDB = pDB->hDB;
1347 /* Compose SQL WHERE expression */
1349 pszWhere = NULL;
1350 sizeWhereAllocated = 0;
1351 sizeWhereUsed = 0;
1352 sizeSearchCriteria = 0;
1353 nCount = 0;
1354 pszAND = " AND ";
1355 sizeAND = strlen(pszAND);
1357 if (nFilenamePMMID != MEDIADB_PMM_NULL)
1359 nCount++;
1362 if (nPathPMMID != MEDIADB_PMM_NULL)
1364 nCount++;
1367 if (pnMinSize != NULL)
1369 nCount++;
1372 if (pnMaxSize != NULL)
1374 nCount++;
1377 if (nFilenamePMMID != MEDIADB_PMM_NULL)
1379 nCount--;
1381 pszTemp = sqlite_mprintf(
1382 "name%s'%q'",
1383 mediadb_sqlite_get_match_keyword(nFilenamePMMID),
1384 pszFilenamePattern);
1385 if (pszTemp == NULL)
1387 r = MEDIADB_MEM;
1388 goto FailFreeWhere;
1391 sizeSearchCriteria = strlen(pszTemp);
1392 r = maybe_enlarge_buffer(
1393 &pszWhere,
1394 &sizeWhereAllocated,
1395 sizeWhereUsed + sizeSearchCriteria + (nCount == 0?0:sizeAND));
1396 if (MEDIADB_IS_ERROR(r))
1398 goto FailFreeTemp;
1401 sizeWhereUsed += sprintf(
1402 pszWhere + sizeWhereUsed,
1403 "%s%s",
1404 pszTemp,
1405 nCount == 0?"":pszAND);
1407 sqlite_freemem(pszTemp);
1410 if (nPathPMMID != MEDIADB_PMM_NULL)
1412 nCount--;
1414 pszTemp = sqlite_mprintf(
1415 "path%s'%q'",
1416 mediadb_sqlite_get_match_keyword(nPathPMMID),
1417 pszPathPattern);
1418 if (pszTemp == NULL)
1420 r = MEDIADB_MEM;
1421 goto FailFreeWhere;
1424 sizeSearchCriteria = strlen(pszTemp);
1425 r = maybe_enlarge_buffer(
1426 &pszWhere,
1427 &sizeWhereAllocated,
1428 sizeWhereUsed + sizeSearchCriteria + (nCount == 0?0:sizeAND));
1429 if (MEDIADB_IS_ERROR(r))
1431 goto FailFreeTemp;
1434 sizeWhereUsed += sprintf(
1435 pszWhere + sizeWhereUsed,
1436 "%s%s",
1437 pszTemp,
1438 nCount == 0?"":pszAND);
1440 sqlite_freemem(pszTemp);
1443 if (pnMinSize != NULL)
1445 nCount--;
1447 pszTemp = sqlite_mprintf(
1448 "size >= %u",
1449 (unsigned int)*pnMinSize);
1450 if (pszTemp == NULL)
1452 r = MEDIADB_MEM;
1453 goto FailFreeWhere;
1456 sizeSearchCriteria = strlen(pszTemp);
1457 r = maybe_enlarge_buffer(
1458 &pszWhere,
1459 &sizeWhereAllocated,
1460 sizeWhereUsed + sizeSearchCriteria + (nCount == 0?0:sizeAND));
1461 if (MEDIADB_IS_ERROR(r))
1463 goto FailFreeTemp;
1466 sizeWhereUsed += sprintf(
1467 pszWhere + sizeWhereUsed,
1468 "%s%s",
1469 pszTemp,
1470 nCount == 0?"":pszAND);
1472 sqlite_freemem(pszTemp);
1475 if (pnMaxSize != NULL)
1477 nCount--;
1479 pszTemp = sqlite_mprintf(
1480 "size <= %u",
1481 (unsigned int)*pnMaxSize);
1482 if (pszTemp == NULL)
1484 r = MEDIADB_MEM;
1485 goto FailFreeWhere;
1488 sizeSearchCriteria = strlen(pszTemp);
1489 r = maybe_enlarge_buffer(
1490 &pszWhere,
1491 &sizeWhereAllocated,
1492 sizeWhereUsed + sizeSearchCriteria + (nCount == 0?0:sizeAND));
1493 if (MEDIADB_IS_ERROR(r))
1495 goto FailFreeTemp;
1498 sizeWhereUsed += sprintf(
1499 pszWhere + sizeWhereUsed,
1500 "%s%s",
1501 pszTemp,
1502 nCount == 0?"":pszAND);
1504 sqlite_freemem(pszTemp);
1507 if (pszWhere == NULL)
1509 /* Nothing to search - empty result */
1510 return MEDIADB_OK;
1513 assert(nCount == 0);
1515 /* Execute SQl query */
1516 nRet = sqlite_exec_printf(
1517 pDB->hDB,
1518 "SELECT mediaid, path, name, size, time FROM " MEDIADB_SQLITE_FILES_TABLE " WHERE %s",
1519 mediadb_sqlite_files_search_callback,
1520 &context,
1521 &pErrorMsg,
1522 pszWhere);
1523 if (nRet != SQLITE_OK)
1525 set_error_message(
1526 pDB,
1527 "Failed to execute SQL query. Error: %s",
1528 pErrorMsg);
1530 free(pErrorMsg);
1531 free(pszWhere);
1533 return MEDIADB_FAIL;
1536 free(pszWhere);
1538 reset_error_message(pDB);
1540 return MEDIADB_OK;
1542 FailFreeTemp:
1543 sqlite_freemem(pszTemp);
1545 FailFreeWhere:
1546 if (pszWhere != NULL)
1548 free(pszWhere);
1551 return r;
1554 /*****************************************************************************
1556 * Modifications log:
1558 * !!! WARNING !!! Following lines are automatically updated by the CVS system.
1560 * $Log: sqlite.c,v $
1561 * Revision 1.11 2004/09/18 21:32:34 nedko
1562 * Use min and max size when searching files.
1563 * Return media name, media type and media location when searching files.
1565 * Revision 1.10 2004/09/01 05:02:17 nedko
1566 * Implement search by filename and path
1568 * Revision 1.9 2004/08/31 22:40:15 nedko
1569 * Partitally implemented search feature.
1571 * Revision 1.8 2004/08/08 00:47:42 nedko
1572 * Get more info for media from database.
1574 * Revision 1.7 2004/05/21 23:40:46 nedko
1575 * New functionality: mediadb_files_get()
1577 * Revision 1.6 2004/05/16 18:57:12 nedko
1578 * media_get_all functionality implemented.
1580 * Revision 1.5 2004/05/11 01:18:53 nedko
1581 * Implement SQLite backend.
1583 * Revision 1.4 2004/05/03 20:47:15 nedko
1584 * Update mode for cui
1586 * Revision 1.3 2004/05/02 20:12:11 nedko
1587 * Improve error dumps.
1589 * Revision 1.2 2004/05/02 13:16:58 nedko
1590 * Supply filetype when adding new file
1592 * Revision 1.1 2004/04/27 09:12:28 nedko
1593 * Initial revision.
1595 *****************************************************************************/