94ff64660d537c1dad7d3fcc28de08e76a53a1e1
[lms] / lightmediascanner / src / lib / lightmediascanner_db_common.c
1 #include "lightmediascanner_db_private.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #if SQLITE_VERSION_NUMBER < 3003009
7 int
8 sqlite3_prepare_v2(sqlite3 *db, const char *sql, int len, sqlite3_stmt **stmt, const char **tail)
9 {
10     return sqlite3_prepare(db, sql, len, stmt, tail);
11 }
12 #endif /* SQLITE_VERSION_NUMBER < 3003009 */
13
14 #if SQLITE_VERSION_NUMBER < 3003007
15 int
16 sqlite3_clear_bindings(sqlite3_stmt *stmt)
17 {
18     int i, last;
19     int rc;
20
21     rc = SQLITE_OK;
22     last = sqlite3_bind_parameter_count(stmt);
23     for(i = 1; rc == SQLITE_OK && i <= last; i++) {
24         rc = sqlite3_bind_null(stmt, i);
25     }
26     return rc;
27 }
28 #endif /* SQLITE_VERSION_NUMBER < 3003007 */
29
30 #if SQLITE_VERSION_NUMBER < 3003008
31 /* Until 3.3.8 it doesn't support CREATE TRIGGER IF NOT EXISTS, so
32  * just ignore errors :-(
33  */
34 int
35 lms_db_create_trigger_if_not_exists(sqlite3 *db, const char *sql)
36 {
37     char *errmsg, *query;
38     int r, sql_len, prefix_len;
39
40     prefix_len = sizeof("CREATE TRIGGER ") - 1;
41     sql_len = strlen(sql);
42     query = malloc((prefix_len + sql_len + 1) * sizeof(char));
43     if (!query)
44         return -1;
45
46     memcpy(query, "CREATE TRIGGER ", prefix_len);
47     memcpy(query + prefix_len, sql, sql_len + 1);
48     r = sqlite3_exec(db, query, NULL, NULL, &errmsg);
49     free(query);
50     if (r != SQLITE_OK)
51         sqlite3_free(errmsg);
52     return 0;
53 }
54 #else /* SQLITE_VERSION_NUMBER < 3003008 */
55 int
56 lms_db_create_trigger_if_not_exists(sqlite3 *db, const char *sql)
57 {
58     char *errmsg, *query;
59     int r, sql_len, prefix_len;
60
61     prefix_len = sizeof("CREATE TRIGGER IF NOT EXISTS ") - 1;
62     sql_len = strlen(sql);
63     query = malloc((prefix_len + sql_len + 1) * sizeof(char));
64     if (!query)
65         return -1;
66
67     memcpy(query, "CREATE TRIGGER IF NOT EXISTS ", prefix_len);
68     memcpy(query + prefix_len, sql, sql_len + 1);
69     r = sqlite3_exec(db, query, NULL, NULL, &errmsg);
70     free(query);
71     if (r != SQLITE_OK) {
72         fprintf(stderr, "ERROR: could not create trigger: %s\n", errmsg);
73         sqlite3_free(errmsg);
74         return -2;
75     }
76     return 0;
77 }
78 #endif /* SQLITE_VERSION_NUMBER < 3003008 */
79
80 sqlite3_stmt *
81 lms_db_compile_stmt(sqlite3 *db, const char *sql)
82 {
83     sqlite3_stmt *stmt;
84
85     if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
86         fprintf(stderr, "ERROR: could not prepare \"%s\": %s\n", sql,
87                 sqlite3_errmsg(db));
88
89     return stmt;
90 }
91
92 int
93 lms_db_finalize_stmt(sqlite3_stmt *stmt, const char *name)
94 {
95     int r;
96
97     r = sqlite3_finalize(stmt);
98     if (r != SQLITE_OK) {
99         fprintf(stderr, "ERROR: could not finalize %s statement: #%d\n",
100                 name, r);
101         return -1;
102     }
103
104     return 0;
105 }
106
107 int
108 lms_db_reset_stmt(sqlite3_stmt *stmt)
109 {
110     int r, ret;
111
112     ret = r = sqlite3_reset(stmt);
113     if (r != SQLITE_OK)
114         fprintf(stderr, "ERROR: could not reset SQL statement: #%d\n", r);
115
116     r = sqlite3_clear_bindings(stmt);
117     ret += r;
118     if (r != SQLITE_OK)
119         fprintf(stderr, "ERROR: could not clear SQL: #%d\n", r);
120
121     return ret;
122 }
123
124 int
125 lms_db_bind_text(sqlite3_stmt *stmt, int col, const char *text, int len)
126 {
127     int r;
128
129     if (text)
130         r = sqlite3_bind_text(stmt, col, text, len, SQLITE_STATIC);
131     else
132         r = sqlite3_bind_null(stmt, col);
133
134     if (r == SQLITE_OK)
135         return 0;
136     else {
137         sqlite3 *db;
138         const char *err;
139
140         db = sqlite3_db_handle(stmt);
141         err = sqlite3_errmsg(db);
142         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
143         return -col;
144     }
145 }
146
147 int
148 lms_db_bind_blob(sqlite3_stmt *stmt, int col, const void *blob, int len)
149 {
150     int r;
151
152     if (blob)
153         r = sqlite3_bind_blob(stmt, col, blob, len, SQLITE_STATIC);
154     else
155         r = sqlite3_bind_null(stmt, col);
156
157     if (r == SQLITE_OK)
158         return 0;
159     else {
160         sqlite3 *db;
161         const char *err;
162
163         db = sqlite3_db_handle(stmt);
164         err = sqlite3_errmsg(db);
165         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
166         return -col;
167     }
168 }
169
170 int
171 lms_db_bind_int64(sqlite3_stmt *stmt, int col, int64_t value)
172 {
173     int r;
174
175     r = sqlite3_bind_int64(stmt, col, value);
176     if (r == SQLITE_OK)
177         return 0;
178     else {
179         sqlite3 *db;
180         const char *err;
181
182         db = sqlite3_db_handle(stmt);
183         err = sqlite3_errmsg(db);
184         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
185         return -col;
186     }
187 }
188
189 int
190 lms_db_bind_int64_or_null(sqlite3_stmt *stmt, int col, int64_t *p_value)
191 {
192     int r;
193
194     if (p_value)
195         r = sqlite3_bind_int64(stmt, col, *p_value);
196     else
197         r = sqlite3_bind_null(stmt, col);
198     if (r == SQLITE_OK)
199         return 0;
200     else {
201         sqlite3 *db;
202         const char *err;
203
204         db = sqlite3_db_handle(stmt);
205         err = sqlite3_errmsg(db);
206         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
207         return -col;
208     }
209 }
210
211 int
212 lms_db_bind_int(sqlite3_stmt *stmt, int col, int value)
213 {
214     int r;
215
216     r = sqlite3_bind_int(stmt, col, value);
217     if (r == SQLITE_OK)
218         return 0;
219     else {
220         sqlite3 *db;
221         const char *err;
222
223         db = sqlite3_db_handle(stmt);
224         err = sqlite3_errmsg(db);
225         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
226         return -col;
227     }
228 }
229
230 int
231 lms_db_bind_double(sqlite3_stmt *stmt, int col, double value)
232 {
233     int r;
234
235     r = sqlite3_bind_double(stmt, col, value);
236     if (r == SQLITE_OK)
237         return 0;
238     else {
239         sqlite3 *db;
240         const char *err;
241
242         db = sqlite3_db_handle(stmt);
243         err = sqlite3_errmsg(db);
244         fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err);
245         return -col;
246     }
247 }
248
249 int
250 lms_db_table_version_get(sqlite3 *db, const char *table)
251 {
252     int r, version;
253     sqlite3_stmt *stmt;
254
255     stmt = lms_db_compile_stmt(db,
256          "SELECT version FROM lms_internal WHERE tab = ?");
257     if (!stmt)
258         return -1;
259
260     if (lms_db_bind_text(stmt, 1, table, -1) != 0) {
261         version = -1;
262         goto done;
263     }
264
265     r = sqlite3_step(stmt);
266     if (r == SQLITE_DONE)
267         version = 0;
268     else if (r == SQLITE_ROW)
269         version = sqlite3_column_int(stmt, 1);
270     else {
271         version = -1;
272         fprintf(stderr, "ERROR: could not get table '%s' version: %s\n",
273                 table, sqlite3_errmsg(db));
274     }
275
276   done:
277     lms_db_reset_stmt(stmt);
278     lms_db_finalize_stmt(stmt, "table_version_get");
279
280     return version;
281 }
282
283 int
284 lms_db_table_version_set(sqlite3 *db, const char *table, unsigned int version)
285 {
286     int r, ret;
287     sqlite3_stmt *stmt;
288
289     stmt = lms_db_compile_stmt(db,
290         "INSERT OR REPLACE INTO lms_internal (tab, version) VALUES (?, ?)");
291     if (!stmt)
292         return -1;
293
294     ret = lms_db_bind_text(stmt, 1, table, -1);
295     if (ret != 0)
296         goto done;
297
298     ret = lms_db_bind_int(stmt, 2, version);
299     if (ret != 0)
300         goto done;
301
302     r = sqlite3_step(stmt);
303     if (r != SQLITE_DONE) {
304         ret = -1;
305         fprintf(stderr, "ERROR: could not set table '%s' version: %s\n",
306                 table, sqlite3_errmsg(db));
307     }
308
309   done:
310     lms_db_reset_stmt(stmt);
311     lms_db_finalize_stmt(stmt, "table_version_set");
312
313     return ret;
314 }
315
316 int
317 lms_db_table_update(sqlite3 *db, const char *table, unsigned int current_version, unsigned int last_version, const lms_db_table_updater_t *updaters)
318 {
319     if (current_version == last_version)
320         return 0;
321     else if (current_version > last_version) {
322         fprintf(stderr,
323                 "WARNING: current version (%d) of table '%s' is greater than "
324                 "last known version (%d), no updates will be made.\n",
325                 current_version, table, last_version);
326         return 0;
327     }
328
329     for (; current_version < last_version; current_version++) {
330         int r, is_last_run;
331
332         is_last_run = current_version == (last_version - 1);
333         r = updaters[current_version](db, table, current_version, is_last_run);
334         if (r != 0) {
335             fprintf(stderr,
336                     "ERROR: could not update table '%s' from version %d->%d\n",
337                     table, current_version, current_version + 1);
338             return r;
339         }
340         lms_db_table_version_set(db, table, current_version + 1);
341     }
342
343     return 0;
344 }
345
346 int
347 lms_db_table_update_if_required(sqlite3 *db, const char *table, unsigned int last_version, lms_db_table_updater_t *updaters)
348 {
349     int current_version;
350
351     current_version = lms_db_table_version_get(db, table);
352     if (current_version < 0)
353         return -1;
354     else
355         return lms_db_table_update(db, table, current_version, last_version,
356                                    updaters);
357 }
358
359 static int
360 lms_db_cache_find_db(const struct lms_db_cache *cache, const sqlite3 *db)
361 {
362     int i;
363
364     for (i = 0; i < cache->size; i++)
365         if (cache->entries[i].db == db)
366             return i;
367
368     return -1;
369 }
370
371 static int
372 lms_db_cache_resize(struct lms_db_cache *cache, int new_size)
373 {
374     cache->size = new_size;
375     cache->entries = realloc(cache->entries,
376                              cache->size * sizeof(*cache->entries));
377     if (cache->size && !cache->entries) {
378         perror("realloc");
379         cache->size = 0;
380         return -1;
381     }
382
383     return 0;
384 }
385
386 int
387 lms_db_cache_add(struct lms_db_cache *cache, const sqlite3 *db, void *data)
388 {
389     struct lms_db_cache_entry *e;
390     int idx;
391
392     idx = lms_db_cache_find_db(cache, db);
393     if (idx >= 0) {
394         e = cache->entries + idx;
395         if (e->data == data)
396             return 0;
397         else {
398             fprintf(stderr,
399                     "ERROR: cache %p for db %p has another data registered"
400                     ": %p (current is %p)\n", cache, db, e->data, data);
401             return -1;
402         }
403     }
404
405     idx = cache->size;
406     if (lms_db_cache_resize(cache, cache->size + 1) != 0) {
407         return -2;
408     }
409
410     e = cache->entries + idx;
411     e->db = db;
412     e->data = data;
413     return 0;
414 }
415
416 int
417 lms_db_cache_del(struct lms_db_cache *cache, const sqlite3 *db, void *data)
418 {
419     int idx;
420     struct lms_db_cache_entry *e;
421
422     idx = lms_db_cache_find_db(cache, db);
423     if (idx < 0) {
424         fprintf(stderr, "ERROR: no db %p found in cache %p\n", db, cache);
425         return -1;
426     }
427
428     e = cache->entries + idx;
429     if (e->data != data) {
430         fprintf(stderr, "ERROR: data mismatch in request to delete from cache: "
431                 "want %p, has %p, cache %p, db %p\n", data, e->data, cache, db);
432         return -2;
433     }
434
435     for (; idx < cache->size - 1; idx++)
436         cache->entries[idx] = cache->entries[idx + 1];
437
438     return lms_db_cache_resize(cache, cache->size - 1);
439 }
440
441 int
442 lms_db_cache_get(struct lms_db_cache *cache, const sqlite3 *db, void **pdata)
443 {
444     int idx;
445
446     idx = lms_db_cache_find_db(cache, db);
447     if (idx < 0)
448         return -1;
449
450     *pdata = cache->entries[idx].data;
451     return 0;
452 }
453
454 int
455 lms_db_create_core_tables_if_required(sqlite3 *db)
456 {
457     char *errmsg;
458     int r;
459
460     errmsg = NULL;
461     r = sqlite3_exec(db,
462                      "CREATE TABLE IF NOT EXISTS lms_internal ("
463                      "tab TEXT NOT NULL UNIQUE, "
464                      "version INTEGER NOT NULL"
465                      ")",
466                      NULL, NULL, &errmsg);
467     if (r != SQLITE_OK) {
468         fprintf(stderr, "ERROR: could not create 'lms_internal' table: %s\n",
469                 errmsg);
470         sqlite3_free(errmsg);
471         return -1;
472     }
473
474     r = sqlite3_exec(db,
475                      "CREATE TABLE IF NOT EXISTS files ("
476                      "id INTEGER PRIMARY KEY AUTOINCREMENT, "
477                      "path BLOB NOT NULL UNIQUE, "
478                      "mtime INTEGER NOT NULL, "
479                      "dtime INTEGER NOT NULL, "
480                      "size INTEGER NOT NULL"
481                      ")",
482                      NULL, NULL, &errmsg);
483     if (r != SQLITE_OK) {
484         fprintf(stderr, "ERROR: could not create 'files' table: %s\n", errmsg);
485         sqlite3_free(errmsg);
486         return -2;
487     }
488
489     r = sqlite3_exec(db,
490                      "CREATE INDEX IF NOT EXISTS files_path_idx ON files ("
491                      "path"
492                      ")",
493                      NULL, NULL, &errmsg);
494     if (r != SQLITE_OK) {
495         fprintf(stderr, "ERROR: could not create 'files_path_idx' index: %s\n",
496                 errmsg);
497         sqlite3_free(errmsg);
498         return -3;
499     }
500
501     return 0;
502 }
503
504
505 sqlite3_stmt *
506 lms_db_compile_stmt_begin_transaction(sqlite3 *db)
507 {
508     return lms_db_compile_stmt(db, "BEGIN TRANSACTION");
509 }
510
511 int
512 lms_db_begin_transaction(sqlite3_stmt *stmt)
513 {
514     int r, ret;
515
516     ret = 0;
517     r = sqlite3_step(stmt);
518     if (r != SQLITE_DONE) {
519         fprintf(stderr, "ERROR: could not begin transaction: %s\n",
520                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
521         ret = -1;
522     }
523
524     r = sqlite3_reset(stmt);
525     if (r != SQLITE_OK)
526         fprintf(stderr, "ERROR: could not reset SQL statement: %s\n",
527                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
528
529     return ret;
530 }
531
532 sqlite3_stmt *
533 lms_db_compile_stmt_end_transaction(sqlite3 *db)
534 {
535     return lms_db_compile_stmt(db, "COMMIT");
536 }
537
538 int
539 lms_db_end_transaction(sqlite3_stmt *stmt)
540 {
541     int r, ret;
542
543     ret = 0;
544     r = sqlite3_step(stmt);
545     if (r != SQLITE_DONE) {
546         fprintf(stderr, "ERROR: could not end transaction: %s\n",
547                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
548         ret = -1;
549     }
550
551     r = sqlite3_reset(stmt);
552     if (r != SQLITE_OK)
553         fprintf(stderr, "ERROR: could not reset SQL statement: %s\n",
554                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
555
556     return ret;
557 }
558
559 sqlite3_stmt *
560 lms_db_compile_stmt_get_file_info(sqlite3 *db)
561 {
562     return lms_db_compile_stmt(db,
563         "SELECT id, mtime, dtime, size FROM files WHERE path = ?");
564 }
565
566 int
567 lms_db_get_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo)
568 {
569     int r, ret;
570
571     ret = lms_db_bind_blob(stmt, 1, finfo->path, finfo->path_len);
572     if (ret != 0)
573         goto done;
574
575     r = sqlite3_step(stmt);
576     if (r == SQLITE_DONE) {
577         ret = 1;
578         finfo->id = -1;
579         goto done;
580     }
581
582     if (r != SQLITE_ROW) {
583         fprintf(stderr, "ERROR: could not get file info from table: %s\n",
584                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
585         ret = -2;
586         goto done;
587     }
588
589     finfo->id = sqlite3_column_int64(stmt, 0);
590     finfo->mtime = sqlite3_column_int(stmt, 1);
591     finfo->dtime = sqlite3_column_int(stmt, 2);
592     finfo->size = sqlite3_column_int(stmt, 3);
593     ret = 0;
594
595   done:
596     lms_db_reset_stmt(stmt);
597
598     return ret;
599 }
600
601 sqlite3_stmt *
602 lms_db_compile_stmt_update_file_info(sqlite3 *db)
603 {
604     return lms_db_compile_stmt(db,
605         "UPDATE files SET mtime = ?, dtime = ?, size = ? WHERE id = ?");
606 }
607
608 int
609 lms_db_update_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo)
610 {
611     int r, ret;
612
613     ret = lms_db_bind_int(stmt, 1, finfo->mtime);
614     if (ret != 0)
615         goto done;
616
617     ret = lms_db_bind_int(stmt, 2, finfo->dtime);
618     if (ret != 0)
619         goto done;
620
621     ret = lms_db_bind_int(stmt, 3, finfo->size);
622     if (ret != 0)
623         goto done;
624
625     ret = lms_db_bind_int(stmt, 4, finfo->id);
626     if (ret != 0)
627         goto done;
628
629     r = sqlite3_step(stmt);
630     if (r != SQLITE_DONE) {
631         fprintf(stderr, "ERROR: could not update file info: %s\n",
632                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
633         ret = -5;
634         goto done;
635     }
636
637     ret = 0;
638
639   done:
640     lms_db_reset_stmt(stmt);
641
642     return ret;
643 }
644
645 sqlite3_stmt *
646 lms_db_compile_stmt_insert_file_info(sqlite3 *db)
647 {
648     return lms_db_compile_stmt(db,
649         "INSERT INTO files (path, mtime, dtime, size) VALUES(?, ?, ?, ?)");
650 }
651
652 int
653 lms_db_insert_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo)
654 {
655     int r, ret;
656
657     ret = lms_db_bind_blob(stmt, 1, finfo->path, finfo->path_len);
658     if (ret != 0)
659         goto done;
660
661     ret = lms_db_bind_int(stmt, 2, finfo->mtime);
662     if (ret != 0)
663         goto done;
664
665     ret = lms_db_bind_int(stmt, 3, finfo->dtime);
666     if (ret != 0)
667         goto done;
668
669     ret = lms_db_bind_int(stmt, 4, finfo->size);
670     if (ret != 0)
671         goto done;
672
673     r = sqlite3_step(stmt);
674     if (r != SQLITE_DONE) {
675         fprintf(stderr, "ERROR: could not insert file info: %s\n",
676                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
677         ret = -5;
678         goto done;
679     }
680
681     finfo->id = sqlite3_last_insert_rowid(sqlite3_db_handle(stmt));
682     ret = 0;
683
684   done:
685     lms_db_reset_stmt(stmt);
686
687     return ret;
688 }
689
690 sqlite3_stmt *
691 lms_db_compile_stmt_delete_file_info(sqlite3 *db)
692 {
693     return lms_db_compile_stmt(db, "DELETE FROM files WHERE id = ?");
694 }
695
696 int
697 lms_db_delete_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo)
698 {
699     int r, ret;
700
701     ret = lms_db_bind_int64(stmt, 1, finfo->id);
702     if (ret != 0)
703         goto done;
704
705     r = sqlite3_step(stmt);
706     if (r != SQLITE_DONE) {
707         fprintf(stderr, "ERROR: could not delete file info: %s\n",
708                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
709         ret = -2;
710         goto done;
711     }
712     ret = 0;
713
714   done:
715     lms_db_reset_stmt(stmt);
716
717     return ret;
718 }
719
720 sqlite3_stmt *
721 lms_db_compile_stmt_set_file_dtime(sqlite3 *db)
722 {
723     return lms_db_compile_stmt(db, "UPDATE files SET dtime = ? WHERE id = ?");
724 }
725
726 int
727 lms_db_set_file_dtime(sqlite3_stmt *stmt, const struct lms_file_info *finfo)
728 {
729     int r, ret;
730
731     ret = lms_db_bind_int(stmt, 1, finfo->dtime);
732     if (ret != 0)
733         goto done;
734
735     ret = lms_db_bind_int64(stmt, 1, finfo->id);
736     if (ret != 0)
737         goto done;
738
739     r = sqlite3_step(stmt);
740     if (r != SQLITE_DONE) {
741         fprintf(stderr, "ERROR: could not set file dtime: %s\n",
742                 sqlite3_errmsg(sqlite3_db_handle(stmt)));
743         ret = -3;
744         goto done;
745     }
746
747     ret = 0;
748
749   done:
750     lms_db_reset_stmt(stmt);
751
752     return ret;
753 }
754
755 sqlite3_stmt *
756 lms_db_compile_stmt_get_files(sqlite3 *db)
757 {
758     return lms_db_compile_stmt(db,
759         "SELECT id, path, mtime, dtime, size FROM files WHERE path LIKE ?");
760 }
761
762 int
763 lms_db_get_files(sqlite3_stmt *stmt, const char *path, int len)
764 {
765     int ret;
766
767     ret = lms_db_bind_blob(stmt, 1, path, len);
768     return ret;
769 }