00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023
00024 #include "xmms/xmms_config.h"
00025 #include "xmms/xmms_log.h"
00026 #include "xmmspriv/xmms_sqlite.h"
00027 #include "xmmspriv/xmms_statfs.h"
00028 #include "xmmspriv/xmms_utils.h"
00029 #include "xmmspriv/xmms_collection.h"
00030 #include "xmmsc/xmmsc_idnumbers.h"
00031
00032 #include <sqlite3.h>
00033 #include <string.h>
00034 #include <glib.h>
00035
00036
00037 #define DB_VERSION 35
00038
00039 const char set_version_stm[] = "PRAGMA user_version=" XMMS_STRINGIFY (DB_VERSION);
00040 const char create_Media_stm[] = "create table Media (id integer, key, value, source integer)";
00041 const char create_Sources_stm[] = "create table Sources (id integer primary key AUTOINCREMENT, source)";
00042 const char create_Playlist_stm[] = "create table Playlist (id primary key, name, pos integer)";
00043 const char create_PlaylistEntries_stm[] = "create table PlaylistEntries (playlist_id int, entry, pos integer primary key AUTOINCREMENT)";
00044 const char create_CollectionAttributes_stm[] = "create table CollectionAttributes (collid integer, key text, value text)";
00045 const char create_CollectionConnections_stm[] = "create table CollectionConnections (from_id integer, to_id integer)";
00046 const char create_CollectionIdlists_stm[] = "create table CollectionIdlists (collid integer, position integer, mid integer)";
00047 const char create_CollectionLabels_stm[] = "create table CollectionLabels (collid integer, namespace integer, name text)";
00048 const char create_CollectionOperators_stm[] = "create table CollectionOperators (id integer primary key AUTOINCREMENT, type integer)";
00049
00050
00051
00052
00053
00054 const char fill_stats[] = "INSERT INTO sqlite_stat1 VALUES('Media', 'key_idx', '199568 14 1 1');"
00055 "INSERT INTO sqlite_stat1 VALUES('Media', 'prop_idx', '199568 6653 3');"
00056 "INSERT INTO sqlite_stat1 VALUES('PlaylistEntries', 'playlistentries_idx', '12784 12784 1');"
00057 "INSERT INTO sqlite_stat1 VALUES('Playlist', 'playlist_idx', '2 1');"
00058 "INSERT INTO sqlite_stat1 VALUES('Playlist', 'sqlite_autoindex_Playlist_1', '2 1');"
00059 "INSERT INTO sqlite_stat1 VALUES('CollectionLabels', 'collectionlabels_idx', '2 2');"
00060 "INSERT INTO sqlite_stat1 VALUES('CollectionIdlists', 'collectionidlists_idx', '15 15 1');"
00061 "INSERT INTO sqlite_stat1 VALUES('CollectionAttributes', 'collectionattributes_idx', '2 2 1');";
00062
00063 const char fill_init_playlist_stm[] = "INSERT INTO CollectionOperators VALUES(1, %d);"
00064 "INSERT INTO CollectionLabels VALUES(1, %d, 'Default');"
00065 "INSERT INTO CollectionLabels VALUES(1, %d, '" XMMS_ACTIVE_PLAYLIST "');"
00066 "INSERT INTO CollectionIdlists VALUES(1, 1, 1);";
00067
00068 const char create_idx_stm[] = "create unique index key_idx on Media (id,key,source);"
00069 "CREATE INDEX id_key_value_1x ON Media (id, key, value COLLATE BINARY);"
00070 "CREATE INDEX id_key_value_2x ON Media (id, key, value COLLATE NOCASE);"
00071 "CREATE INDEX key_value_1x ON Media (key, value COLLATE BINARY);"
00072 "CREATE INDEX key_value_2x ON Media (key, value COLLATE NOCASE);"
00073 "create index playlistentries_idx on PlaylistEntries (playlist_id, entry);"
00074 "create index playlist_idx on Playlist (name);";
00075
00076 const char create_collidx_stm[] = "create unique index collectionconnections_idx on CollectionConnections (from_id, to_id);"
00077 "create unique index collectionattributes_idx on CollectionAttributes (collid, key);"
00078 "create unique index collectionidlists_idx on CollectionIdlists (collid, position);"
00079 "create index collectionlabels_idx on CollectionLabels (collid);";
00080
00081
00082
00083
00084
00085
00086
00087
00088 static int
00089 xmms_sqlite_version_cb (void *pArg, int argc, char **argv, char **columnName)
00090 {
00091 guint *id = pArg;
00092
00093 if (argv[0]) {
00094 *id = atoi (argv[0]);
00095 } else {
00096 *id = 0;
00097 }
00098
00099 return 0;
00100 }
00101
00102 static int
00103 xmms_sqlite_integer_coll (void *udata, int len1, const void *str1, int len2, const void *str2)
00104 {
00105 guint32 a, b;
00106 a = strtol (str1, NULL, 10);
00107 b = strtol (str2, NULL, 10);
00108 if (a < b) return -1;
00109 if (a == b) return 0;
00110 return 1;
00111 }
00112
00113 static void
00114 upgrade_v26_to_v27 (sqlite3 *sql)
00115 {
00116 XMMS_DBG ("Upgrade v26->v27");
00117 sqlite3_exec (sql,
00118 "drop view albums;"
00119 "drop view artists;"
00120 "drop view compilations;"
00121 "drop view songs;",
00122 NULL, NULL, NULL);
00123
00124 XMMS_DBG ("done");
00125 }
00126
00127 static void
00128 upgrade_v27_to_v28 (sqlite3 *sql)
00129 {
00130 XMMS_DBG ("Upgrade v27->v28");
00131
00132 sqlite3_exec (sql,
00133 "drop table Log;",
00134 NULL, NULL, NULL);
00135
00136 XMMS_DBG ("done");
00137 }
00138
00139 static void
00140 upgrade_v28_to_v29 (sqlite3 *sql)
00141 {
00142 XMMS_DBG ("Upgrade v28->v29");
00143
00144 sqlite3_exec (sql, "delete from Media where source in"
00145 "(select id from Sources where source like 'plugin%')",
00146 NULL, NULL, NULL);
00147 sqlite3_exec (sql, "delete from Sources where source like 'plugin%'",
00148 NULL, NULL, NULL);
00149 sqlite3_exec (sql, "update Media set value=0 where key='resolved'",
00150 NULL, NULL, NULL);
00151
00152 XMMS_DBG ("done");
00153 }
00154
00155 static void
00156 upgrade_v29_to_v30 (sqlite3 *sql)
00157 {
00158 XMMS_DBG ("Upgrade v29->v30");
00159 sqlite3_exec (sql, "insert into Media (id, key, value, source) select distinct id, 'available', 1, (select id from Sources where source='server') from Media", NULL, NULL, NULL);
00160 XMMS_DBG ("done");
00161 }
00162
00163 static void
00164 upgrade_v30_to_v31 (sqlite3 *sql)
00165 {
00166 XMMS_DBG ("Upgrade v30->v31");
00167
00168 sqlite3_exec (sql, create_CollectionAttributes_stm, NULL, NULL, NULL);
00169 sqlite3_exec (sql, create_CollectionConnections_stm, NULL, NULL, NULL);
00170 sqlite3_exec (sql, create_CollectionIdlists_stm, NULL, NULL, NULL);
00171 sqlite3_exec (sql, create_CollectionLabels_stm, NULL, NULL, NULL);
00172 sqlite3_exec (sql, create_CollectionOperators_stm, NULL, NULL, NULL);
00173 sqlite3_exec (sql, create_collidx_stm, NULL, NULL, NULL);
00174
00175
00176 xmms_sqlite_exec (sql, fill_init_playlist_stm, XMMS_COLLECTION_TYPE_IDLIST,
00177 XMMS_COLLECTION_NSID_PLAYLISTS,
00178 XMMS_COLLECTION_NSID_PLAYLISTS);
00179
00180 XMMS_DBG ("done");
00181 }
00182
00183 static void
00184 upgrade_v31_to_v32 (sqlite3 *sql)
00185 {
00186 XMMS_DBG ("upgrade v31->v32");
00187 sqlite3_exec (sql, "delete from Media where id = (select id from Media where key='available' and value=0)", NULL, NULL, NULL);
00188 sqlite3_exec (sql, "delete from Media where key='available' and source = 1", NULL, NULL, NULL);
00189 sqlite3_exec (sql, "update media set key='status' where key='resolved' and source = 1", NULL, NULL, NULL);
00190 XMMS_DBG ("done");
00191 }
00192
00193 static void
00194 upgrade_v32_to_v33 (sqlite3 *sql)
00195 {
00196
00197 XMMS_DBG ("upgrade v32->v33");
00198 sqlite3_exec (sql, "update CollectionOperators set type=type - 1", NULL, NULL, NULL);
00199 XMMS_DBG ("done");
00200 }
00201
00202 static void
00203 upgrade_v33_to_v34 (sqlite3 *sql)
00204 {
00205 XMMS_DBG ("upgrade v33->v34");
00206 sqlite3_exec (sql, "update CollectionAttributes set value=replace(replace(value, '%', '*'), '_', '?') WHERE collid IN (SELECT id FROM CollectionOperators WHERE type='6')", NULL, NULL, NULL);
00207 XMMS_DBG ("done");
00208 }
00209
00210
00211 static void
00212 upgrade_v34_to_v35 (sqlite3 *sql)
00213 {
00214 XMMS_DBG ("upgrade v34->v35");
00215 sqlite3_exec (sql, "DROP INDEX prop_idx;"
00216 "CREATE INDEX id_key_value_1x ON Media (id, key, value COLLATE BINARY);"
00217 "CREATE INDEX id_key_value_2x ON Media (id, key, value COLLATE NOCASE);"
00218 "CREATE INDEX key_value_1x ON Media (key, value COLLATE BINARY);"
00219 "CREATE INDEX key_value_2x ON Media (key, value COLLATE NOCASE);"
00220 "UPDATE CollectionAttributes SET value=replace(replace(value, '%', '*'), '_', '?') WHERE collid IN (SELECT id FROM CollectionOperators WHERE type='6');", NULL, NULL, NULL);
00221 XMMS_DBG ("done");
00222 }
00223
00224 static gboolean
00225 try_upgrade (sqlite3 *sql, gint version)
00226 {
00227 gboolean can_upgrade = TRUE;
00228
00229 switch (version) {
00230 case 26:
00231 upgrade_v26_to_v27 (sql);
00232 case 27:
00233 upgrade_v27_to_v28 (sql);
00234 case 28:
00235 upgrade_v28_to_v29 (sql);
00236 case 29:
00237 upgrade_v29_to_v30 (sql);
00238 case 30:
00239 upgrade_v30_to_v31 (sql);
00240 case 31:
00241 upgrade_v31_to_v32 (sql);
00242 case 32:
00243 upgrade_v32_to_v33 (sql);
00244 case 33:
00245 upgrade_v33_to_v34 (sql);
00246 case 34:
00247 upgrade_v34_to_v35 (sql);
00248 break;
00249 default:
00250 can_upgrade = FALSE;
00251 break;
00252 }
00253
00254 if (can_upgrade) {
00255
00256 sqlite3_exec (sql, set_version_stm, NULL, NULL, NULL);
00257 }
00258
00259 return can_upgrade;
00260 }
00261
00262 static void
00263 xmms_sqlite_set_common_properties (sqlite3 *sql)
00264 {
00265 sqlite3_exec (sql, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
00266 sqlite3_exec (sql, "PRAGMA auto_vacuum = 1", NULL, NULL, NULL);
00267 sqlite3_exec (sql, "PRAGMA cache_size = 8000", NULL, NULL, NULL);
00268 sqlite3_exec (sql, "PRAGMA temp_store = MEMORY", NULL, NULL, NULL);
00269
00270
00271 sqlite3_busy_timeout (sql, 60000);
00272
00273 sqlite3_create_collation (sql, "INTCOLL", SQLITE_UTF8, NULL, xmms_sqlite_integer_coll);
00274 }
00275
00276 gboolean
00277 xmms_sqlite_create (gboolean *create)
00278 {
00279 xmms_config_property_t *cv;
00280 gchar *tmp;
00281 gboolean analyze = FALSE;
00282 const gchar *dbpath;
00283 gint version = 0;
00284 sqlite3 *sql;
00285
00286 *create = FALSE;
00287
00288 cv = xmms_config_lookup ("medialib.path");
00289 dbpath = xmms_config_property_get_string (cv);
00290
00291 if (!g_file_test (dbpath, G_FILE_TEST_EXISTS)) {
00292 *create = TRUE;
00293 }
00294
00295 if (sqlite3_open (dbpath, &sql)) {
00296 xmms_log_fatal ("Error opening sqlite db: %s", sqlite3_errmsg (sql));
00297 return FALSE;
00298 }
00299
00300 xmms_sqlite_set_common_properties (sql);
00301
00302 if (!*create) {
00303 sqlite3_exec (sql, "PRAGMA user_version",
00304 xmms_sqlite_version_cb, &version, NULL);
00305
00306 if (version != DB_VERSION && !try_upgrade (sql, version)) {
00307 gchar *old;
00308
00309 sqlite3_close (sql);
00310
00311 old = XMMS_BUILD_PATH ("medialib.db.old");
00312 rename (dbpath, old);
00313 if (sqlite3_open (dbpath, &sql)) {
00314 xmms_log_fatal ("Error creating sqlite db: %s",
00315 sqlite3_errmsg (sql));
00316 g_free (old);
00317 return FALSE;
00318 }
00319 g_free (old);
00320
00321 sqlite3_exec (sql, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
00322 *create = TRUE;
00323 }
00324
00325 cv = xmms_config_lookup ("medialib.analyze_on_startup");
00326 analyze = xmms_config_property_get_int (cv);
00327 if (analyze) {
00328 xmms_log_info ("Analyzing db, please wait a few seconds");
00329 sqlite3_exec (sql, "ANALYZE", NULL, NULL, NULL);
00330 xmms_log_info ("Done with analyze");
00331 }
00332 }
00333
00334 if (*create) {
00335
00336
00337
00338
00339
00340
00341
00342 tmp = g_path_get_dirname (dbpath);
00343 if (xmms_statfs_is_remote (tmp)) {
00344 cv = xmms_config_lookup ("medialib.allow_remote_fs");
00345 if (xmms_config_property_get_int (cv) == 1) {
00346 xmms_log_info ("Allowing database on remote system against best judgement.");
00347 } else {
00348 xmms_log_fatal ("Remote filesystem detected!\n"
00349 "* It looks like you are putting your database: %s\n"
00350 "* on a remote filesystem, this is a bad idea since there are many known bugs\n"
00351 "* with SQLite on some remote filesystems. We recomend that you put the db\n"
00352 "* somewhere else. You can do this by editing the xmms2.conf and find the\n"
00353 "* property for medialib.path. If you however still want to try to run the\n"
00354 "* db on a remote filesystem please set medialib.allow_remote_fs=1 in your\n"
00355 "* config and restart xmms2d.", dbpath);
00356 }
00357 }
00358
00359 g_free (tmp);
00360
00361 XMMS_DBG ("Creating the database...");
00362
00363
00364
00365
00366
00367 sqlite3_exec (sql, "ANALYZE", NULL, NULL, NULL);
00368
00369
00370
00371 sqlite3_exec (sql, fill_stats, NULL, NULL, NULL);
00372
00373
00374
00375 sqlite3_exec (sql, create_Media_stm, NULL, NULL, NULL);
00376 sqlite3_exec (sql, create_Sources_stm, NULL, NULL, NULL);
00377 sqlite3_exec (sql, "insert into Sources (source) values ('server')", NULL, NULL, NULL);
00378 sqlite3_exec (sql, create_PlaylistEntries_stm, NULL, NULL, NULL);
00379 sqlite3_exec (sql, create_Playlist_stm, NULL, NULL, NULL);
00380 sqlite3_exec (sql, create_CollectionAttributes_stm, NULL, NULL, NULL);
00381 sqlite3_exec (sql, create_CollectionConnections_stm, NULL, NULL, NULL);
00382 sqlite3_exec (sql, create_CollectionIdlists_stm, NULL, NULL, NULL);
00383 sqlite3_exec (sql, create_CollectionLabels_stm, NULL, NULL, NULL);
00384 sqlite3_exec (sql, create_CollectionOperators_stm, NULL, NULL, NULL);
00385 sqlite3_exec (sql, create_idx_stm, NULL, NULL, NULL);
00386 sqlite3_exec (sql, create_collidx_stm, NULL, NULL, NULL);
00387 sqlite3_exec (sql, set_version_stm, NULL, NULL, NULL);
00388
00389
00390
00391 xmms_sqlite_exec (sql, fill_init_playlist_stm, XMMS_COLLECTION_TYPE_IDLIST,
00392 XMMS_COLLECTION_NSID_PLAYLISTS,
00393 XMMS_COLLECTION_NSID_PLAYLISTS);
00394 }
00395
00396 sqlite3_close (sql);
00397
00398 XMMS_DBG ("xmms_sqlite_create done!");
00399 return TRUE;
00400 }
00401
00402
00403
00404
00405 sqlite3 *
00406 xmms_sqlite_open ()
00407 {
00408 sqlite3 *sql;
00409 const gchar *dbpath;
00410 xmms_config_property_t *cv;
00411
00412 cv = xmms_config_lookup ("medialib.path");
00413 dbpath = xmms_config_property_get_string (cv);
00414
00415 if (sqlite3_open (dbpath, &sql)) {
00416 xmms_log_fatal ("Error opening sqlite db: %s", sqlite3_errmsg (sql));
00417 return NULL;
00418 }
00419
00420 g_return_val_if_fail (sql, NULL);
00421
00422 xmms_sqlite_set_common_properties (sql);
00423
00424 return sql;
00425 }
00426
00427 static xmms_object_cmd_value_t *
00428 xmms_sqlite_column_to_val (sqlite3_stmt *stm, gint column)
00429 {
00430 xmms_object_cmd_value_t *val = NULL;
00431
00432 switch (sqlite3_column_type (stm, column)) {
00433 case SQLITE_INTEGER:
00434 case SQLITE_FLOAT:
00435 val = xmms_object_cmd_value_int_new (sqlite3_column_int (stm, column));
00436 break;
00437 case SQLITE_TEXT:
00438 case SQLITE_BLOB:
00439 val = xmms_object_cmd_value_str_new ((gchar *)sqlite3_column_text (stm, column));
00440 break;
00441 case SQLITE_NULL:
00442 val = xmms_object_cmd_value_none_new ();
00443 break;
00444 default:
00445 XMMS_DBG ("Unhandled SQLite type!");
00446 break;
00447 }
00448
00449 return val;
00450
00451 }
00452
00453
00454
00455
00456 gboolean
00457 xmms_sqlite_exec (sqlite3 *sql, const char *query, ...)
00458 {
00459 gchar *q, *err;
00460 va_list ap;
00461 gint ret;
00462
00463 g_return_val_if_fail (query, FALSE);
00464 g_return_val_if_fail (sql, FALSE);
00465
00466 va_start (ap, query);
00467
00468 q = sqlite3_vmprintf (query, ap);
00469
00470 ret = sqlite3_exec (sql, q, NULL, NULL, &err);
00471 if (ret == SQLITE_BUSY) {
00472 xmms_log_fatal ("BUSY EVENT!");
00473 g_assert_not_reached ();
00474 }
00475 if (ret != SQLITE_OK) {
00476 xmms_log_error ("Error in query! \"%s\" (%d) - %s", q, ret, err);
00477 sqlite3_free (q);
00478 va_end (ap);
00479 return FALSE;
00480 }
00481
00482 sqlite3_free (q);
00483 va_end (ap);
00484
00485 return TRUE;
00486 }
00487
00488
00489
00490
00491 gboolean
00492 xmms_sqlite_query_table (sqlite3 *sql, xmms_medialib_row_table_method_t method, gpointer udata, xmms_error_t *error, const gchar *query, ...)
00493 {
00494 gchar *q;
00495 va_list ap;
00496 gint ret;
00497 sqlite3_stmt *stm;
00498
00499 g_return_val_if_fail (query, FALSE);
00500 g_return_val_if_fail (sql, FALSE);
00501
00502 va_start (ap, query);
00503 q = sqlite3_vmprintf (query, ap);
00504 va_end (ap);
00505
00506 ret = sqlite3_prepare (sql, q, -1, &stm, NULL);
00507
00508 if (ret == SQLITE_BUSY) {
00509 xmms_log_fatal ("BUSY EVENT!");
00510 g_assert_not_reached ();
00511 }
00512
00513 if (ret != SQLITE_OK) {
00514 gchar err[256];
00515 g_snprintf (err, sizeof (err),
00516 "Error in query: %s", sqlite3_errmsg (sql));
00517 xmms_error_set (error, XMMS_ERROR_GENERIC, err);
00518 xmms_log_error ("Error %d (%s) in query '%s'", ret, sqlite3_errmsg (sql), q);
00519 sqlite3_free (q);
00520 return FALSE;
00521 }
00522
00523 while ((ret = sqlite3_step (stm)) == SQLITE_ROW) {
00524 gint i;
00525 xmms_object_cmd_value_t *val;
00526 GHashTable *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
00527 g_free,
00528 (GDestroyNotify)xmms_object_cmd_value_unref);
00529 gint num = sqlite3_data_count (stm);
00530
00531 for (i = 0; i < num; i++) {
00532 val = xmms_sqlite_column_to_val (stm, i);
00533 g_hash_table_insert (ret, g_strdup (sqlite3_column_name (stm, i)), val);
00534 }
00535
00536 if (!method (ret, udata)) {
00537 break;
00538 }
00539
00540 }
00541
00542 if (ret == SQLITE_ERROR) {
00543 xmms_log_error ("SQLite Error code %d (%s) on query '%s'", ret, sqlite3_errmsg (sql), q);
00544 } else if (ret == SQLITE_MISUSE) {
00545 xmms_log_error ("SQLite api misuse on query '%s'", q);
00546 } else if (ret == SQLITE_BUSY) {
00547 xmms_log_error ("SQLite busy on query '%s'", q);
00548 g_assert_not_reached ();
00549 }
00550
00551 sqlite3_free (q);
00552 sqlite3_finalize (stm);
00553
00554 return (ret == SQLITE_DONE);
00555 }
00556
00557
00558
00559
00560 gboolean
00561 xmms_sqlite_query_array (sqlite3 *sql, xmms_medialib_row_array_method_t method, gpointer udata, const gchar *query, ...)
00562 {
00563 gchar *q;
00564 va_list ap;
00565 gint ret, num_cols;
00566 xmms_object_cmd_value_t **row;
00567 sqlite3_stmt *stm = NULL;
00568
00569 g_return_val_if_fail (query, FALSE);
00570 g_return_val_if_fail (sql, FALSE);
00571
00572 va_start (ap, query);
00573 q = sqlite3_vmprintf (query, ap);
00574 va_end (ap);
00575
00576 ret = sqlite3_prepare (sql, q, -1, &stm, NULL);
00577
00578 if (ret == SQLITE_BUSY) {
00579 xmms_log_fatal ("BUSY EVENT!");
00580 g_assert_not_reached ();
00581 }
00582
00583 if (ret != SQLITE_OK) {
00584 xmms_log_error ("Error %d (%s) in query '%s'", ret, sqlite3_errmsg (sql), q);
00585 sqlite3_free (q);
00586 return FALSE;
00587 }
00588
00589 num_cols = sqlite3_column_count (stm);
00590
00591 row = g_new (xmms_object_cmd_value_t *, num_cols + 1);
00592 row[num_cols] = NULL;
00593
00594 while ((ret = sqlite3_step (stm)) == SQLITE_ROW) {
00595 gint i;
00596 gboolean b;
00597
00598
00599 g_assert (num_cols == sqlite3_data_count (stm));
00600
00601 for (i = 0; i < num_cols; i++) {
00602 row[i] = xmms_sqlite_column_to_val (stm, i);
00603 }
00604
00605 b = method (row, udata);
00606
00607 for (i = 0; i < num_cols; i++) {
00608 xmms_object_cmd_value_unref (row[i]);
00609 }
00610
00611 if (!b) {
00612 break;
00613 }
00614 }
00615
00616 g_free (row);
00617
00618 if (ret == SQLITE_ERROR) {
00619 xmms_log_error ("SQLite Error code %d (%s) on query '%s'", ret, sqlite3_errmsg (sql), q);
00620 } else if (ret == SQLITE_MISUSE) {
00621 xmms_log_error ("SQLite api misuse on query '%s'", q);
00622 } else if (ret == SQLITE_BUSY) {
00623 xmms_log_error ("SQLite busy on query '%s'", q);
00624 }
00625
00626 sqlite3_free (q);
00627 sqlite3_finalize (stm);
00628
00629 return (ret == SQLITE_DONE);
00630 }
00631
00632
00633
00634
00635 void
00636 xmms_sqlite_close (sqlite3 *sql)
00637 {
00638 g_return_if_fail (sql);
00639 sqlite3_close (sql);
00640 }
00641
00642 void
00643 xmms_sqlite_print_version (void)
00644 {
00645 printf (" Using sqlite version %d (compiled against "
00646 XMMS_STRINGIFY (SQLITE_VERSION_NUMBER) ")\n",
00647 sqlite3_libversion_number ());
00648 }
00649
00650
00651 gchar *
00652 sqlite_prepare_string (const gchar *input) {
00653 gchar *q, *str;
00654 q = sqlite3_mprintf ("%Q", input);
00655 str = g_strdup (q);
00656 sqlite3_free (q);
00657 return str;
00658 }
00659
00660