00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config/sqlite.h>
00025 #include <core/threading/mutex.h>
00026 #include <core/exceptions/system.h>
00027
00028 #include <sqlite3.h>
00029
00030 #ifndef _GNU_SOURCE
00031 #define _GNU_SOURCE
00032 #endif
00033 #include <cstdio>
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <cerrno>
00037
00038 namespace fawkes {
00039
00040
00041
00042 #define TABLE_HOST_CONFIG "config"
00043 #define TABLE_DEFAULT_CONFIG "defaults.config"
00044 #define TABLE_HOST_TAGGED "tagged_config"
00045
00046 #define SQL_CREATE_TABLE_HOST_CONFIG \
00047 "CREATE TABLE IF NOT EXISTS config (\n" \
00048 " path TEXT NOT NULL,\n" \
00049 " type TEXT NOT NULL,\n" \
00050 " value NOT NULL,\n" \
00051 " comment TEXT,\n" \
00052 " PRIMARY KEY (path)\n" \
00053 ")"
00054
00055 #define SQL_CREATE_TABLE_DEFAULT_CONFIG \
00056 "CREATE TABLE IF NOT EXISTS defaults.config (\n" \
00057 " path TEXT NOT NULL,\n" \
00058 " type TEXT NOT NULL,\n" \
00059 " value NOT NULL,\n" \
00060 " comment TEXT,\n" \
00061 " PRIMARY KEY (path)\n" \
00062 ")"
00063
00064 #define SQL_CREATE_TABLE_TAGGED_CONFIG \
00065 "CREATE TABLE IF NOT EXISTS tagged_config (\n" \
00066 " tag TEXT NOT NULL,\n" \
00067 " path TEXT NOT NULL,\n" \
00068 " type TEXT NOT NULL,\n" \
00069 " value NOT NULL,\n" \
00070 " comment TEXT,\n" \
00071 " PRIMARY KEY (tag, path)\n" \
00072 ")"
00073
00074 #define SQL_CREATE_TABLE_MODIFIED_CONFIG \
00075 "CREATE TABLE IF NOT EXISTS modified.config (\n" \
00076 " path TEXT NOT NULL,\n" \
00077 " type TEXT NOT NULL,\n" \
00078 " value NOT NULL,\n" \
00079 " comment TEXT,\n" \
00080 " modtype TEXT NOT NULL,\n" \
00081 " oldvalue NOT NULL,\n" \
00082 " PRIMARY KEY (path)\n" \
00083 ")"
00084
00085 #define SQL_ATTACH_DEFAULTS \
00086 "ATTACH DATABASE '%s' AS defaults"
00087
00088 #define SQL_ATTACH_MODIFIED \
00089 "ATTACH DATABASE ':memory:' AS modified"
00090
00091 #define SQL_ATTACH_DUMPED \
00092 "ATTACH DATABASE '%s' AS dumped"
00093
00094 #define SQL_DETACH_DUMPED \
00095 "DETACH DATABASE dumped"
00096
00097 #define SQL_SELECT_VALUE_TYPE \
00098 "SELECT type, value, 0 AS is_default FROM config WHERE path=? UNION " \
00099 "SELECT type, value, 1 AS is_default FROM defaults.config AS dc " \
00100 "WHERE path=? AND NOT EXISTS " \
00101 "(SELECT path FROM config WHERE dc.path=path)"
00102
00103 #define SQL_SELECT_COMPLETE \
00104 "SELECT *, 0 AS is_default FROM config WHERE path LIKE ? UNION " \
00105 "SELECT *, 1 AS is_default FROM defaults.config AS dc " \
00106 "WHERE path LIKE ? AND NOT EXISTS " \
00107 "(SELECT path FROM config WHERE dc.path = path) " \
00108 "ORDER BY path"
00109
00110 #define SQL_SELECT_TYPE \
00111 "SELECT type, 0 AS is_default FROM config WHERE path=? UNION " \
00112 "SELECT type, 1 AS is_default FROM defaults.config AS dc " \
00113 "WHERE path=? AND NOT EXISTS " \
00114 "(SELECT path FROM config WHERE dc.path = path)"
00115
00116 #define SQL_SELECT_COMMENT \
00117 "SELECT comment, 0 AS is_default FROM config WHERE path=?"
00118
00119 #define SQL_SELECT_DEFAULT_COMMENT \
00120 "SELECT comment, 1 AS is_default FROM defaults.config AS dc " \
00121 "WHERE dc.path=?"
00122
00123 #define SQL_UPDATE_VALUE \
00124 "UPDATE config SET value=? WHERE path=?"
00125
00126 #define SQL_UPDATE_DEFAULT_VALUE \
00127 "UPDATE defaults.config SET value=? WHERE path=?"
00128
00129 #define SQL_UPDATE_COMMENT \
00130 "UPDATE config SET comment=? WHERE path=?"
00131
00132 #define SQL_UPDATE_DEFAULT_COMMENT \
00133 "UPDATE defaults.config SET comment=? WHERE path=?"
00134
00135 #define SQL_INSERT_VALUE \
00136 "INSERT INTO config (path, type, value) VALUES (?, ?, ?)"
00137
00138 #define SQL_INSERT_DEFAULT_VALUE \
00139 "INSERT INTO defaults.config (path, type, value) VALUES (?, ?, ?)"
00140
00141 #define SQL_SELECT_TAGS \
00142 "SELECT tag FROM tagged_config GROUP BY tag"
00143
00144 #define SQL_INSERT_TAG \
00145 "INSERT INTO tagged_config " \
00146 "(tag, path, type, value, comment) " \
00147 "SELECT \"%s\",* FROM config"
00148
00149 #define SQL_SELECT_ALL \
00150 "SELECT *, 0 AS is_default FROM config UNION " \
00151 "SELECT *, 1 AS is_default FROM defaults.config AS dc " \
00152 "WHERE NOT EXISTS " \
00153 "(SELECT path FROM config WHERE dc.path = path) " \
00154 "ORDER BY path"
00155
00156 #define SQL_SELECT_ALL_DEFAULT \
00157 "SELECT *, 1 AS is_default FROM defaults.config"
00158
00159 #define SQL_SELECT_ALL_HOSTSPECIFIC \
00160 "SELECT *, 0 AS is_default FROM config"
00161
00162 #define SQL_DELETE_VALUE \
00163 "DELETE FROM config WHERE path=?"
00164
00165 #define SQL_DELETE_DEFAULT_VALUE \
00166 "DELETE FROM defaults.config WHERE path=?"
00167
00168 #define SQL_UPDATE_DEFAULT_DB \
00169 "INSERT INTO config SELECT * FROM defaults.config AS dc " \
00170 "WHERE NOT EXISTS (SELECT path from config WHERE path = dc.path)"
00171
00172 #define SQL_UPDATE_MODIFIED_DB_ADDED \
00173 "INSERT INTO modified.config " \
00174 " SELECT duc.*,'added' AS modtype, duc.value " \
00175 " FROM dumped.config AS duc " \
00176 " WHERE NOT EXISTS (SELECT dc.path FROM defaults.config AS dc " \
00177 " WHERE dc.path=duc.path) " \
00178 " ORDER BY path"
00179
00180 #define SQL_UPDATE_MODIFIED_DB_ERASED \
00181 "INSERT INTO modified.config " \
00182 " SELECT dc.*,'erased' AS modtype, dc.value " \
00183 " FROM defaults.config AS dc " \
00184 " WHERE NOT EXISTS (SELECT duc.path FROM dumped.config AS duc " \
00185 " WHERE duc.path=dc.path) " \
00186 " ORDER BY path"
00187
00188 #define SQL_UPDATE_MODIFIED_DB_CHANGED \
00189 "INSERT INTO modified.config " \
00190 " SELECT duc.*,'changed' AS modtype, dc.value " \
00191 " FROM dumped.config AS duc, defaults.config AS dc " \
00192 " WHERE duc.path = dc.path " \
00193 " AND (dc.type != duc.type OR dc.value != duc.value) " \
00194 " ORDER BY duc.path"
00195
00196 #define SQL_COPY_DUMP \
00197 "DELETE FROM defaults.config; " \
00198 "INSERT INTO defaults.config SELECT * FROM dumped.config"
00199
00200 #define SQL_SELECT_MODIFIED_ALL \
00201 "SELECT * FROM modified.config"
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 SQLiteConfiguration::SQLiteConfiguration(const char *conf_path)
00223 {
00224 this->conf_path = conf_path;
00225 opened = false;
00226 mutex = new Mutex();
00227
00228 __default_file = NULL;
00229 __default_dump = NULL;
00230 }
00231
00232
00233
00234 SQLiteConfiguration::~SQLiteConfiguration()
00235 {
00236 if (opened) {
00237 opened = false;
00238 if ( sqlite3_close(db) == SQLITE_BUSY ) {
00239 printf("Boom, we are dead, database cannot be closed because there are open handles\n");
00240 } else if ( __default_dump) {
00241 sqlite3 *tdb;
00242 if ( sqlite3_open(__default_file, &tdb) == SQLITE_OK ) {
00243 try {
00244 dump(tdb, __default_dump);
00245 } catch (Exception &e) {
00246 e.print_trace();
00247 }
00248 sqlite3_close(tdb);
00249 }
00250 }
00251 }
00252
00253 if (__host_file) free(__host_file);
00254 if (__default_file) free(__default_file);
00255 if (__default_dump) free(__default_dump);
00256 delete mutex;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 void
00310 SQLiteConfiguration::init_dbs()
00311 {
00312 char *errmsg;
00313 if ( (sqlite3_exec(db, SQL_CREATE_TABLE_HOST_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ||
00314 (sqlite3_exec(db, SQL_CREATE_TABLE_DEFAULT_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ||
00315 (sqlite3_exec(db, SQL_CREATE_TABLE_TAGGED_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00316 CouldNotOpenConfigException ce(sqlite3_errmsg(db));
00317 sqlite3_close(db);
00318 throw ce;
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329 static void
00330 dump_table(FILE *f, ::sqlite3 *tdb, const char *table_name)
00331 {
00332 std::string tisql = "PRAGMA table_info(\"";
00333 tisql += table_name;
00334 tisql += "\");";
00335
00336 sqlite3_stmt *stmt;
00337 if ( sqlite3_prepare(tdb, tisql.c_str(), -1, &stmt, 0) != SQLITE_OK ) {
00338 throw ConfigurationException("dump_table/prepare", sqlite3_errmsg(tdb));
00339 }
00340 std::string value_query = "SELECT 'INSERT INTO ' || '\"";
00341 value_query += table_name;
00342 value_query += "\"' || ' VALUES(' || ";
00343 int rv = sqlite3_step(stmt);
00344 while ( rv == SQLITE_ROW ) {
00345 value_query += "quote(\"";
00346 value_query += (const char *)sqlite3_column_text(stmt, 1);
00347 value_query += "\") || ";
00348 rv = sqlite3_step(stmt);
00349 if ( rv == SQLITE_ROW ) {
00350 value_query += " ',' || ";
00351 }
00352 }
00353 value_query += "')' FROM ";
00354 value_query += table_name;
00355 sqlite3_finalize(stmt);
00356
00357 sqlite3_stmt *vstmt;
00358 if ( sqlite3_prepare(tdb, value_query.c_str(), -1, &vstmt, 0) != SQLITE_OK ) {
00359 throw ConfigurationException("dump_table/prepare 2", sqlite3_errmsg(tdb));
00360 }
00361 while ( sqlite3_step(vstmt) == SQLITE_ROW ) {
00362 fprintf(f, "%s;\n", sqlite3_column_text(vstmt, 0));
00363 }
00364 sqlite3_finalize(vstmt);
00365 }
00366
00367 void
00368 SQLiteConfiguration::dump(::sqlite3 *tdb, const char *dumpfile)
00369 {
00370 FILE *f = fopen(dumpfile, "w");
00371 if ( ! f ) {
00372 throw CouldNotOpenFileException(dumpfile, errno, "Could not open SQLite dump file");
00373 }
00374
00375 fprintf(f, "BEGIN TRANSACTION;\n");
00376
00377 const char *sql = "SELECT name, sql FROM sqlite_master "
00378 "WHERE sql NOT NULL AND type=='table'";
00379 sqlite3_stmt *stmt;
00380 if ( (sqlite3_prepare(tdb, sql, -1, &stmt, 0) != SQLITE_OK) || ! stmt ) {
00381 throw ConfigurationException("dump_query/prepare", sqlite3_errmsg(tdb));
00382 }
00383 while ( sqlite3_step(stmt) == SQLITE_ROW ) {
00384 fprintf(f, "%s;\n", sqlite3_column_text(stmt, 1));
00385 dump_table(f, tdb, (const char *)sqlite3_column_text(stmt, 0));
00386 }
00387 sqlite3_finalize(stmt);
00388
00389 fprintf(f, "COMMIT;\n");
00390 fclose(f);
00391 }
00392
00393
00394 void
00395 SQLiteConfiguration::import(::sqlite3 *tdb, const char *dumpfile)
00396 {
00397 FILE *f = fopen(dumpfile, "r");
00398
00399 char line[4096];
00400 char *errmsg;
00401 while (! feof(f) ) {
00402 line[0] = 0;
00403 unsigned int i = 0;
00404 while (! feof(f) && (i < sizeof(line) - 1)) {
00405 if (fread(&(line[i]), 1, 1, f) == 1) {
00406 ++i;
00407 if ( (i > 2) && (line[i-1] == '\n') && (line[i-2] == ';') ) {
00408 break;
00409 }
00410 } else {
00411 break;
00412 }
00413 }
00414 line[i] = 0;
00415 if ( line[0] != 0 ) {
00416 if ( sqlite3_exec(tdb, line, 0, 0, &errmsg) != SQLITE_OK ) {
00417 ConfigurationException e(errmsg, line);
00418 sqlite3_free(errmsg);
00419 throw e;
00420 }
00421 }
00422 }
00423
00424 fclose(f);
00425 }
00426
00427
00428 void
00429 SQLiteConfiguration::import_default(const char *default_dump)
00430 {
00431 char *tmpfile = (char *)malloc(strlen(conf_path) + strlen("/tmp_default_XXXXXX") + 1);
00432 sprintf(tmpfile, "%s/tmp_default_XXXXXX", conf_path);
00433 tmpfile = mktemp(tmpfile);
00434 if ( tmpfile[0] == 0 ) {
00435 throw CouldNotOpenConfigException("Failed to create temp file for default DB import");
00436 }
00437
00438
00439 sqlite3 *dump_db;
00440 if ( sqlite3_open(tmpfile, &dump_db) == SQLITE_OK ) {
00441 import(dump_db, default_dump);
00442 sqlite3_close(dump_db);
00443 } else {
00444 throw CouldNotOpenConfigException("Failed to import dump file into temp DB");
00445 }
00446
00447
00448 char *attach_sql;
00449 char *errmsg;
00450 if ( asprintf(&attach_sql, SQL_ATTACH_DUMPED, tmpfile) == -1 ) {
00451 throw CouldNotOpenConfigException("Could not create attachment SQL in merge");
00452 }
00453 if ( sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK ) {
00454 free(attach_sql);
00455 CouldNotOpenConfigException e("Could not attach dump DB in merge: %s", errmsg);
00456 sqlite3_free(errmsg);
00457 throw e;
00458 }
00459 free(attach_sql);
00460
00461
00462 if ( (sqlite3_exec(db, SQL_ATTACH_MODIFIED, NULL, NULL, &errmsg) != SQLITE_OK) ||
00463 (sqlite3_exec(db, SQL_CREATE_TABLE_MODIFIED_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00464 CouldNotOpenConfigException ce("Could not create or attach modified memory database: %s", errmsg);
00465 sqlite3_free(errmsg);
00466 throw ce;
00467 }
00468
00469
00470 if ( (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ADDED, NULL, NULL, &errmsg) != SQLITE_OK) ||
00471 (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ERASED, NULL, NULL, &errmsg) != SQLITE_OK) ||
00472 (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_CHANGED, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00473 CouldNotOpenConfigException ce("Could not update modified memory database: %s", errmsg);
00474 sqlite3_free(errmsg);
00475 throw ce;
00476 }
00477
00478
00479 if ( (sqlite3_exec(db, SQL_COPY_DUMP, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00480 CouldNotOpenConfigException ce("Could not copy dump to default: %s", errmsg);
00481 sqlite3_free(errmsg);
00482 throw ce;
00483 }
00484
00485
00486 if ( sqlite3_exec(db, SQL_DETACH_DUMPED, NULL, NULL, &errmsg) != SQLITE_OK ) {
00487 CouldNotOpenConfigException e("Could not detach dump DB in import: %s", errmsg);
00488 sqlite3_free(errmsg);
00489 throw e;
00490 }
00491
00492 unlink(tmpfile);
00493 free(tmpfile);
00494 }
00495
00496
00497
00498
00499
00500 void
00501 SQLiteConfiguration::transaction_begin(transaction_type_t ttype)
00502 {
00503 const char *sql = "BEGIN DEFERRED TRANSACTION;";
00504 if (ttype == TRANSACTION_IMMEDIATE) {
00505 sql = "BEGIN IMMEDIATE TRANSACTION;";
00506 } else if (ttype == TRANSACTION_EXCLUSIVE) {
00507 sql = "BEGIN EXCLUSIVE TRANSACTION;";
00508 }
00509
00510 char *errmsg;
00511 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00512 throw ConfigurationException("Could not begin transaction (%s)", errmsg);
00513 }
00514 }
00515
00516
00517 void
00518 SQLiteConfiguration::transaction_commit()
00519 {
00520 const char *sql = "COMMIT TRANSACTION;";
00521
00522 char *errmsg;
00523 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00524 throw ConfigurationException("Could not commit transaction (%s)", errmsg);
00525 }
00526 }
00527
00528
00529
00530 void
00531 SQLiteConfiguration::transaction_rollback()
00532 {
00533 const char *sql = "ROLLBACK TRANSACTION;";
00534
00535 char *errmsg;
00536 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00537 throw ConfigurationException("Could not rollback transaction (%s)", errmsg);
00538 }
00539 }
00540
00541
00542 void
00543 SQLiteConfiguration::load(const char *name, const char *defaults_name,
00544 const char *tag)
00545 {
00546 char *errmsg;
00547 char *attach_sql;
00548
00549 mutex->lock();
00550
00551 if ( name ) {
00552 __host_file = strdup(name);
00553 } else {
00554 HostInfo hostinfo;
00555 if ( asprintf(&__host_file, "%s.db", hostinfo.short_name()) == -1 ) {
00556 __host_file = strdup(hostinfo.short_name());
00557 }
00558 }
00559
00560 if (__default_file) free(__default_file);
00561 if (__default_dump) free(__default_dump);
00562 if (defaults_name) {
00563 __default_file = strdup(defaults_name);
00564 if (strcmp(defaults_name, ":memory:") != 0) {
00565 __default_dump = (char *)malloc(strlen(__default_file) + 5);
00566 strcpy(__default_dump, __default_file);
00567 strcat(__default_dump, ".sql");
00568 }
00569 } else {
00570 __default_file = strdup("default.db");
00571 __default_dump = strdup("default.sql");
00572 }
00573
00574 if ( conf_path == NULL ) {
00575 conf_path = ".";
00576 }
00577
00578 if (strcmp(__default_file, ":memory:") != 0) {
00579 if ( (access(__default_file, F_OK) != 0) && (__default_file[0] != '/') ) {
00580
00581 char *tdf = __default_file;
00582 if ( asprintf(&__default_file, "%s/%s", conf_path, tdf) == -1 ) {
00583 free(tdf);
00584 throw CouldNotOpenConfigException("Could not create default filename");
00585 }
00586 free(tdf);
00587 }
00588 }
00589
00590 if (__default_dump && (access(__default_dump, F_OK) != 0) && (__default_dump[0] != '/') ) {
00591
00592 char *tdf = __default_dump;
00593 if ( asprintf(&__default_dump, "%s/%s", conf_path, tdf) == -1 ) {
00594 free(tdf);
00595 throw CouldNotOpenConfigException("Could not create default filename");
00596 }
00597 free(tdf);
00598 }
00599
00600 if (strcmp(__host_file, ":memory:") != 0) {
00601 if ( (access(__host_file, F_OK) != 0) && (__host_file[0] != '/') ) {
00602
00603 char *thf = __host_file;
00604 if ( asprintf(&__host_file, "%s/%s", conf_path, thf) == -1 ) {
00605 free(thf);
00606 throw CouldNotOpenConfigException("Could not create filename");
00607 }
00608 free(thf);
00609 }
00610 }
00611
00612 if ( asprintf(&attach_sql, SQL_ATTACH_DEFAULTS, __default_file) == -1 ) {
00613 free(__host_file);
00614 free(__default_file);
00615 if (__default_dump) free(__default_dump);
00616 throw CouldNotOpenConfigException("Could not create attachment SQL");
00617 }
00618
00619
00620 if ( (sqlite3_open(__host_file, &db) != SQLITE_OK) ||
00621 (sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK) ) {
00622 CouldNotOpenConfigException ce(sqlite3_errmsg(db));
00623 ce.append("Failed to open host file '%s' or attaching default file (%s)",
00624 __host_file, __default_file);
00625 free(attach_sql);
00626 free(__host_file);
00627 free(__default_file);
00628 if (__default_dump) free(__default_dump);
00629 sqlite3_close(db);
00630 throw ce;
00631 }
00632 free(attach_sql);
00633
00634 init_dbs();
00635
00636 if ( __default_dump && access(__default_dump, F_OK | R_OK) == 0 ) {
00637 import_default(__default_dump);
00638 }
00639
00640 mutex->unlock();
00641
00642 opened = true;
00643 }
00644
00645
00646
00647
00648
00649
00650
00651 void
00652 SQLiteConfiguration::load(const char *tag)
00653 {
00654 load(NULL, NULL, tag);
00655 }
00656
00657
00658 void
00659 SQLiteConfiguration::copy(Configuration *copyconf)
00660 {
00661 copyconf->lock();
00662 transaction_begin();
00663 Configuration::ValueIterator *i = copyconf->iterator();
00664 while ( i->next() ) {
00665 if ( i->is_float() ) {
00666 set_float(i->path(), i->get_float());
00667 } else if ( i->is_int() ) {
00668 set_int(i->path(), i->get_int());
00669 } else if ( i->is_uint() ) {
00670 set_uint(i->path(), i->get_uint());
00671 } else if ( i->is_bool() ) {
00672 set_bool(i->path(), i->get_bool());
00673 } else if ( i->is_string() ) {
00674 std::string s = i->get_string();
00675 set_string(i->path(), s);
00676 }
00677 }
00678 delete i;
00679 transaction_commit();
00680 copyconf->unlock();
00681 }
00682
00683
00684
00685
00686
00687
00688
00689 void
00690 SQLiteConfiguration::tag(const char *tag)
00691 {
00692 char *insert_sql;
00693 char *errmsg;
00694
00695 mutex->lock();
00696
00697 if ( asprintf(&insert_sql, SQL_INSERT_TAG, tag) == -1 ) {
00698 mutex->unlock();
00699 throw ConfigurationException("Could not create insert statement for tagging");
00700 }
00701
00702 if (sqlite3_exec(db, insert_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
00703 ConfigurationException ce("Could not insert tag", sqlite3_errmsg(db));
00704 free(insert_sql);
00705 mutex->unlock();
00706 throw ce;
00707 }
00708
00709 free(insert_sql);
00710 mutex->unlock();
00711 }
00712
00713
00714 std::list<std::string>
00715 SQLiteConfiguration::tags()
00716 {
00717 mutex->lock();
00718 std::list<std::string> l;
00719 sqlite3_stmt *stmt;
00720 const char *tail;
00721 if ( sqlite3_prepare(db, SQL_SELECT_TAGS, -1, &stmt, &tail) != SQLITE_OK ) {
00722 mutex->unlock();
00723 throw ConfigurationException("get_type: Preparation SQL failed");
00724 }
00725 while ( sqlite3_step(stmt) == SQLITE_ROW ) {
00726 l.push_back((char *)sqlite3_column_text(stmt, 0));
00727 }
00728 sqlite3_finalize(stmt);
00729 mutex->unlock();
00730 return l;
00731 }
00732
00733
00734 bool
00735 SQLiteConfiguration::exists(const char *path)
00736 {
00737 mutex->lock();
00738 sqlite3_stmt *stmt;
00739 const char *tail;
00740 bool e;
00741
00742 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) {
00743 mutex->unlock();
00744 throw ConfigurationException("exists/prepare", sqlite3_errmsg(db));
00745 }
00746 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00747 mutex->unlock();
00748 throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db));
00749 }
00750 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
00751 mutex->unlock();
00752 throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db));
00753 }
00754 e = ( sqlite3_step(stmt) == SQLITE_ROW );
00755 sqlite3_finalize(stmt);
00756
00757 mutex->unlock();
00758 return e;
00759 }
00760
00761
00762 std::string
00763 SQLiteConfiguration::get_type(const char *path)
00764 {
00765 sqlite3_stmt *stmt;
00766 const char *tail;
00767 std::string s = "";
00768
00769 mutex->lock();
00770
00771 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) {
00772 mutex->unlock();
00773 throw ConfigurationException("get_type: Preparation SQL failed");
00774 }
00775 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00776 mutex->unlock();
00777 throw ConfigurationException("get_type: Binding text for path failed (1)");
00778 }
00779 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
00780 mutex->unlock();
00781 throw ConfigurationException("get_type: Binding text for path failed (2)");
00782 }
00783 if ( sqlite3_step(stmt) == SQLITE_ROW ) {
00784 s = (char *)sqlite3_column_text(stmt, 0);
00785 sqlite3_finalize(stmt);
00786 mutex->unlock();
00787 return s;
00788 } else {
00789 sqlite3_finalize(stmt);
00790 mutex->unlock();
00791 throw ConfigEntryNotFoundException(path);
00792 }
00793 }
00794
00795
00796 std::string
00797 SQLiteConfiguration::get_comment(const char *path)
00798 {
00799 sqlite3_stmt *stmt;
00800 const char *tail;
00801 std::string s = "";
00802
00803 mutex->lock();
00804
00805 if ( sqlite3_prepare(db, SQL_SELECT_COMMENT, -1, &stmt, &tail) != SQLITE_OK ) {
00806 mutex->unlock();
00807 throw ConfigurationException("get_comment: Preparation SQL failed");
00808 }
00809 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00810 mutex->unlock();
00811 throw ConfigurationException("get_comment: Binding text for path failed (1)");
00812 }
00813 if ( sqlite3_step(stmt) == SQLITE_ROW ) {
00814 s = (char *)sqlite3_column_text(stmt, 0);
00815 sqlite3_finalize(stmt);
00816 mutex->unlock();
00817 return s;
00818 } else {
00819 sqlite3_finalize(stmt);
00820 mutex->unlock();
00821 throw ConfigEntryNotFoundException(path);
00822 }
00823 }
00824
00825
00826 std::string
00827 SQLiteConfiguration::get_default_comment(const char *path)
00828 {
00829 sqlite3_stmt *stmt;
00830 const char *tail;
00831 std::string s = "";
00832
00833 mutex->lock();
00834
00835 if ( sqlite3_prepare(db, SQL_SELECT_DEFAULT_COMMENT, -1, &stmt, &tail) != SQLITE_OK ) {
00836 mutex->unlock();
00837 throw ConfigurationException("get_default_comment: Preparation SQL failed");
00838 }
00839 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00840 mutex->unlock();
00841 throw ConfigurationException("get_default_comment: Binding text for path failed (1)");
00842 }
00843 if ( sqlite3_step(stmt) == SQLITE_ROW ) {
00844 s = (char *)sqlite3_column_text(stmt, 0);
00845 sqlite3_finalize(stmt);
00846 mutex->unlock();
00847 return s;
00848 } else {
00849 sqlite3_finalize(stmt);
00850 mutex->unlock();
00851 throw ConfigEntryNotFoundException(path);
00852 }
00853 }
00854
00855
00856 bool
00857 SQLiteConfiguration::is_float(const char *path)
00858 {
00859 return (get_type(path) == "float");
00860 }
00861
00862
00863 bool
00864 SQLiteConfiguration::is_uint(const char *path)
00865 {
00866 return (get_type(path) == "unsigned int");
00867 }
00868
00869
00870 bool
00871 SQLiteConfiguration::is_int(const char *path)
00872 {
00873 return (get_type(path) == "int");
00874 }
00875
00876
00877 bool
00878 SQLiteConfiguration::is_bool(const char *path)
00879 {
00880 return (get_type(path) == "bool");
00881 }
00882
00883
00884 bool
00885 SQLiteConfiguration::is_string(const char *path)
00886 {
00887 return (get_type(path) == "string");
00888 }
00889
00890
00891 bool
00892 SQLiteConfiguration::is_default(const char *path)
00893 {
00894 mutex->lock();
00895 sqlite3_stmt *stmt;
00896 const char *tail;
00897 bool e;
00898
00899 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) {
00900 mutex->unlock();
00901 throw ConfigurationException("is_default/prepare", sqlite3_errmsg(db));
00902 }
00903 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00904 mutex->unlock();
00905 throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db));
00906 }
00907 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
00908 mutex->unlock();
00909 throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db));
00910 }
00911 e = ( (sqlite3_step(stmt) == SQLITE_ROW) && (sqlite3_column_int(stmt, 1) == 1 ));
00912 sqlite3_finalize(stmt);
00913
00914 mutex->unlock();
00915 return e;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 sqlite3_stmt *
00925 SQLiteConfiguration::get_value(const char *path,
00926 const char *type)
00927 {
00928 sqlite3_stmt *stmt;
00929 const char *tail;
00930
00931 if ( sqlite3_prepare(db, SQL_SELECT_VALUE_TYPE, -1, &stmt, &tail) != SQLITE_OK ) {
00932 throw ConfigurationException("get_value/prepare", sqlite3_errmsg(db));
00933 }
00934 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
00935 throw ConfigurationException("get_value/bind/path (1)", sqlite3_errmsg(db));
00936 }
00937 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
00938 throw ConfigurationException("get_value/bind/path (2)", sqlite3_errmsg(db));
00939 }
00940
00941 if ( sqlite3_step(stmt) == SQLITE_ROW ) {
00942 if ( type == NULL ) {
00943
00944 return stmt;
00945 } else {
00946 if (strcmp((char *)sqlite3_column_text(stmt, 0), type) != 0) {
00947 ConfigTypeMismatchException ce(path, (char *)sqlite3_column_text(stmt, 0), type);
00948 sqlite3_finalize(stmt);
00949 throw ce;
00950 } else {
00951 return stmt;
00952 }
00953 }
00954 } else {
00955 sqlite3_finalize(stmt);
00956 throw ConfigEntryNotFoundException(path);
00957 }
00958 }
00959
00960
00961 float
00962 SQLiteConfiguration::get_float(const char *path)
00963 {
00964 sqlite3_stmt *stmt;
00965 mutex->lock();
00966 try {
00967 stmt = get_value(path, "float");
00968 float f = (float)sqlite3_column_double(stmt, 1);
00969 sqlite3_finalize(stmt);
00970 mutex->unlock();
00971 return f;
00972 } catch (Exception &e) {
00973
00974 mutex->unlock();
00975 throw;
00976 }
00977 }
00978
00979
00980 unsigned int
00981 SQLiteConfiguration::get_uint(const char *path)
00982 {
00983 sqlite3_stmt *stmt;
00984 mutex->lock();
00985 try {
00986 stmt = get_value(path, "unsigned int");
00987 int i = sqlite3_column_int(stmt, 1);
00988 sqlite3_finalize(stmt);
00989 if ( i < 0 ) {
00990 mutex->unlock();
00991 throw ConfigTypeMismatchException(path, "int", "unsigned int");
00992 }
00993 mutex->unlock();
00994 return i;
00995 } catch (Exception &e) {
00996
00997 mutex->unlock();
00998 throw;
00999 }
01000 }
01001
01002
01003 int
01004 SQLiteConfiguration::get_int(const char *path)
01005 {
01006 sqlite3_stmt *stmt;
01007 mutex->lock();
01008 try {
01009 stmt = get_value(path, "int");
01010 int i = sqlite3_column_int(stmt, 1);
01011 sqlite3_finalize(stmt);
01012 mutex->unlock();
01013 return i;
01014 } catch (Exception &e) {
01015
01016 mutex->unlock();
01017 throw;
01018 }
01019 }
01020
01021
01022 bool
01023 SQLiteConfiguration::get_bool(const char *path)
01024 {
01025 sqlite3_stmt *stmt;
01026 mutex->lock();
01027 try {
01028 stmt = get_value(path, "bool");
01029 int i = sqlite3_column_int(stmt, 1);
01030 sqlite3_finalize(stmt);
01031 mutex->unlock();
01032 return (i != 0);
01033 } catch (Exception &e) {
01034
01035 mutex->unlock();
01036 throw;
01037 }
01038 }
01039
01040 std::string
01041 SQLiteConfiguration::get_string(const char *path)
01042 {
01043 sqlite3_stmt *stmt;
01044 mutex->lock();
01045 try {
01046 stmt = get_value(path, "string");
01047 const char *c = (char *)sqlite3_column_text(stmt, 1);
01048 std::string rv = c;
01049 sqlite3_finalize(stmt);
01050 mutex->unlock();
01051 return rv;
01052 } catch (Exception &e) {
01053
01054 e.append("SQLiteConfiguration::get_string: Fetching %s failed.", path);
01055 mutex->unlock();
01056 throw;
01057 }
01058 }
01059
01060
01061 Configuration::ValueIterator *
01062 SQLiteConfiguration::get_value(const char *path)
01063 {
01064 sqlite3_stmt *stmt;
01065 const char *tail;
01066
01067 if ( sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK ) {
01068 throw ConfigurationException("get_value/prepare", sqlite3_errmsg(db));
01069 }
01070 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
01071 throw ConfigurationException("get_value/bind/path (1)", sqlite3_errmsg(db));
01072 }
01073 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
01074 throw ConfigurationException("get_value/bind/path (2)", sqlite3_errmsg(db));
01075 }
01076
01077 return new SQLiteValueIterator(stmt);
01078 }
01079
01080
01081 sqlite3_stmt *
01082 SQLiteConfiguration::prepare_update(const char *sql,
01083 const char *path)
01084 {
01085 sqlite3_stmt *stmt;
01086 const char *tail;
01087
01088 if ( sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK ) {
01089 throw ConfigurationException("prepare_update/prepare", sqlite3_errmsg(db));
01090 }
01091 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) {
01092 ConfigurationException ce("prepare_update/bind", sqlite3_errmsg(db));
01093 sqlite3_finalize(stmt);
01094 throw ce;
01095 }
01096
01097 return stmt;
01098 }
01099
01100
01101 sqlite3_stmt *
01102 SQLiteConfiguration::prepare_insert_value(const char *sql, const char *type,
01103 const char *path)
01104 {
01105 sqlite3_stmt *stmt;
01106 const char *tail;
01107
01108 if ( sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK ) {
01109 throw ConfigurationException("prepare_insert_value/prepare", sqlite3_errmsg(db));
01110 }
01111 if ( (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) ||
01112 (sqlite3_bind_text(stmt, 2, type, -1, NULL) != SQLITE_OK) ) {
01113 ConfigurationException ce("prepare_insert_value/bind", sqlite3_errmsg(db));
01114 sqlite3_finalize(stmt);
01115 throw ce;
01116 }
01117
01118 return stmt;
01119 }
01120
01121
01122 void
01123 SQLiteConfiguration::execute_insert_or_update(sqlite3_stmt *stmt)
01124 {
01125 if ( sqlite3_step(stmt) != SQLITE_DONE ) {
01126 ConfigurationException ce("execute_insert_or_update", sqlite3_errmsg(db));
01127 sqlite3_finalize(stmt);
01128 throw ce;
01129 }
01130 }
01131
01132
01133 void
01134 SQLiteConfiguration::set_float(const char *path, float f)
01135 {
01136 sqlite3_stmt *stmt = NULL;
01137
01138 mutex->lock();
01139
01140 try {
01141 stmt = prepare_update(SQL_UPDATE_VALUE, path);
01142 if ( (sqlite3_bind_double(stmt, 1, f) != SQLITE_OK) ) {
01143 ConfigurationException ce("set_float/update/bind", sqlite3_errmsg(db));
01144 sqlite3_finalize(stmt);
01145 mutex->unlock();
01146 throw ce;
01147 }
01148 execute_insert_or_update(stmt);
01149 sqlite3_finalize(stmt);
01150 } catch (Exception &e) {
01151 if ( stmt != NULL ) sqlite3_finalize(stmt);
01152 mutex->unlock();
01153 throw;
01154 }
01155
01156 if ( sqlite3_changes(db) == 0 ) {
01157
01158
01159 try {
01160 stmt = prepare_insert_value(SQL_INSERT_VALUE, "float", path);
01161 if ( (sqlite3_bind_double(stmt, 3, f) != SQLITE_OK) ) {
01162 ConfigurationException ce("set_float/insert/bind", sqlite3_errmsg(db));
01163 sqlite3_finalize(stmt);
01164 mutex->unlock();
01165 throw ce;
01166 }
01167 execute_insert_or_update(stmt);
01168 sqlite3_finalize(stmt);
01169 } catch (Exception &e) {
01170 if ( stmt != NULL ) sqlite3_finalize(stmt);
01171 mutex->unlock();
01172 throw;
01173 }
01174 }
01175
01176 mutex->unlock();
01177
01178 ChangeHandlerList *h = find_handlers(path);
01179 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01180 (*i)->config_value_changed(path, false, f);
01181 }
01182 delete h;
01183 }
01184
01185
01186 void
01187 SQLiteConfiguration::set_uint(const char *path, unsigned int uint)
01188 {
01189 sqlite3_stmt *stmt = NULL;
01190
01191 mutex->lock();
01192
01193 try {
01194 stmt = prepare_update(SQL_UPDATE_VALUE, path);
01195 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) {
01196 ConfigurationException ce("set_uint/update/bind", sqlite3_errmsg(db));
01197 sqlite3_finalize(stmt);
01198 mutex->unlock();
01199 throw ce;
01200 }
01201 execute_insert_or_update(stmt);
01202 sqlite3_finalize(stmt);
01203 } catch (Exception &e) {
01204 if ( stmt != NULL ) sqlite3_finalize(stmt);
01205 mutex->unlock();
01206 throw;
01207 }
01208
01209 if ( sqlite3_changes(db) == 0 ) {
01210
01211
01212 try {
01213 stmt = prepare_insert_value(SQL_INSERT_VALUE, "unsigned int", path);
01214 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) {
01215 ConfigurationException ce("set_uint/insert/bind", sqlite3_errmsg(db));
01216 sqlite3_finalize(stmt);
01217 mutex->unlock();
01218 throw ce;
01219 }
01220 execute_insert_or_update(stmt);
01221 sqlite3_finalize(stmt);
01222 } catch (Exception &e) {
01223 if ( stmt != NULL ) sqlite3_finalize(stmt);
01224 mutex->unlock();
01225 throw;
01226 }
01227 }
01228 mutex->unlock();
01229
01230 ChangeHandlerList *h = find_handlers(path);
01231 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01232 (*i)->config_value_changed(path, false, uint);
01233 }
01234 delete h;
01235 }
01236
01237
01238 void
01239 SQLiteConfiguration::set_int(const char *path, int i)
01240 {
01241 sqlite3_stmt *stmt = NULL;
01242
01243 mutex->lock();
01244
01245 try {
01246 stmt = prepare_update(SQL_UPDATE_VALUE, path);
01247 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) {
01248 ConfigurationException ce("set_int/update/bind", sqlite3_errmsg(db));
01249 sqlite3_finalize(stmt);
01250 mutex->unlock();
01251 throw ce;
01252 }
01253 execute_insert_or_update(stmt);
01254 sqlite3_finalize(stmt);
01255 } catch (Exception &e) {
01256 if ( stmt != NULL ) sqlite3_finalize(stmt);
01257 mutex->unlock();
01258 throw;
01259 }
01260
01261 if ( sqlite3_changes(db) == 0 ) {
01262
01263
01264 try {
01265 stmt = prepare_insert_value(SQL_INSERT_VALUE, "int", path);
01266 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) {
01267 ConfigurationException ce("set_int/insert/bind", sqlite3_errmsg(db));
01268 sqlite3_finalize(stmt);
01269 mutex->unlock();
01270 throw ce;
01271 }
01272 execute_insert_or_update(stmt);
01273 sqlite3_finalize(stmt);
01274 } catch (Exception &e) {
01275 if ( stmt != NULL ) sqlite3_finalize(stmt);
01276 mutex->unlock();
01277 throw;
01278 }
01279 }
01280
01281 mutex->unlock();
01282
01283 ChangeHandlerList *h = find_handlers(path);
01284 for (ChangeHandlerList::const_iterator j = h->begin(); j != h->end(); ++j) {
01285 (*j)->config_value_changed(path, false, i);
01286 }
01287 delete h;
01288 }
01289
01290
01291 void
01292 SQLiteConfiguration::set_bool(const char *path, bool b)
01293 {
01294 sqlite3_stmt *stmt = NULL;
01295
01296 mutex->lock();
01297
01298 try {
01299 stmt = prepare_update(SQL_UPDATE_VALUE, path);
01300 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) {
01301 ConfigurationException ce("set_bool/update/bind", sqlite3_errmsg(db));
01302 sqlite3_finalize(stmt);
01303 mutex->unlock();
01304 throw ce;
01305 }
01306 execute_insert_or_update(stmt);
01307 sqlite3_finalize(stmt);
01308 } catch (Exception &e) {
01309 if ( stmt != NULL ) sqlite3_finalize(stmt);
01310 mutex->unlock();
01311 throw;
01312 }
01313
01314 if ( sqlite3_changes(db) == 0 ) {
01315
01316
01317 try {
01318 stmt = prepare_insert_value(SQL_INSERT_VALUE, "bool", path);
01319 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) {
01320 ConfigurationException ce("set_bool/insert/bind", sqlite3_errmsg(db));
01321 sqlite3_finalize(stmt);
01322 mutex->unlock();
01323 throw ce;
01324 }
01325 execute_insert_or_update(stmt);
01326 sqlite3_finalize(stmt);
01327 } catch (Exception &e) {
01328 if ( stmt != NULL ) sqlite3_finalize(stmt);
01329 mutex->unlock();
01330 throw;
01331 }
01332 }
01333
01334 mutex->unlock();
01335
01336 ChangeHandlerList *h = find_handlers(path);
01337 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01338 (*i)->config_value_changed(path, false, b);
01339 }
01340 delete h;
01341 }
01342
01343
01344 void
01345 SQLiteConfiguration::set_string(const char *path,
01346 const char *s)
01347 {
01348 sqlite3_stmt *stmt = NULL;
01349
01350 mutex->lock();
01351
01352 size_t s_length = strlen(s);
01353
01354 try {
01355 stmt = prepare_update(SQL_UPDATE_VALUE, path);
01356 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01357 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db));
01358 sqlite3_finalize(stmt);
01359 mutex->unlock();
01360 throw ce;
01361 }
01362 execute_insert_or_update(stmt);
01363 sqlite3_finalize(stmt);
01364 } catch (Exception &e) {
01365 if ( stmt != NULL ) sqlite3_finalize(stmt);
01366 mutex->unlock();
01367 throw;
01368 }
01369
01370 if ( sqlite3_changes(db) == 0 ) {
01371
01372
01373 try {
01374 stmt = prepare_insert_value(SQL_INSERT_VALUE, "string", path);
01375 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01376 ConfigurationException ce("set_string/insert/bind", sqlite3_errmsg(db));
01377 sqlite3_finalize(stmt);
01378 mutex->unlock();
01379 throw ce;
01380 }
01381 execute_insert_or_update(stmt);
01382 sqlite3_finalize(stmt);
01383 } catch (Exception &e) {
01384 if ( stmt != NULL ) sqlite3_finalize(stmt);
01385 mutex->unlock();
01386 throw;
01387 }
01388 }
01389
01390 mutex->unlock();
01391
01392 ChangeHandlerList *h = find_handlers(path);
01393 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01394 (*i)->config_value_changed(path, false, s);
01395 }
01396 delete h;
01397 }
01398
01399
01400 void
01401 SQLiteConfiguration::set_string(const char *path, std::string &s)
01402 {
01403 set_string(path, s.c_str());
01404 }
01405
01406
01407 void
01408 SQLiteConfiguration::set_comment(const char *path, const char *comment)
01409 {
01410 sqlite3_stmt *stmt = NULL;
01411
01412 mutex->lock();
01413
01414 size_t s_length = strlen(comment);
01415
01416 try {
01417 stmt = prepare_update(SQL_UPDATE_COMMENT, path);
01418 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01419 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db));
01420 sqlite3_finalize(stmt);
01421 mutex->unlock();
01422 throw ce;
01423 }
01424 execute_insert_or_update(stmt);
01425 sqlite3_finalize(stmt);
01426 } catch (Exception &e) {
01427 if ( stmt != NULL ) sqlite3_finalize(stmt);
01428 mutex->unlock();
01429 throw;
01430 }
01431
01432 if ( sqlite3_changes(db) == 0 ) {
01433
01434 mutex->unlock();
01435 throw ConfigurationException("set_comment", "Cannot set comment for inexistent path");
01436 }
01437
01438 mutex->unlock();
01439
01440 ChangeHandlerList *h = find_handlers(path);
01441 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01442 (*i)->config_comment_changed(path, false, comment);
01443 }
01444 delete h;
01445 }
01446
01447
01448 void
01449 SQLiteConfiguration::set_comment(const char *path, std::string &comment)
01450 {
01451 set_comment(path, comment.c_str());
01452 }
01453
01454
01455 void
01456 SQLiteConfiguration::erase(const char *path)
01457 {
01458 sqlite3_stmt *stmt;
01459 const char *tail;
01460
01461 if ( sqlite3_prepare(db, SQL_DELETE_VALUE, -1, &stmt, &tail) != SQLITE_OK ) {
01462 throw ConfigurationException("erase/prepare", sqlite3_errmsg(db));
01463 }
01464 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
01465 ConfigurationException ce("erase/bind", sqlite3_errmsg(db));
01466 sqlite3_finalize(stmt);
01467 throw ce;
01468 }
01469
01470 if ( sqlite3_step(stmt) != SQLITE_DONE ) {
01471 ConfigurationException ce("erase/execute", sqlite3_errmsg(db));
01472 sqlite3_finalize(stmt);
01473 throw ce;
01474 }
01475
01476 sqlite3_finalize(stmt);
01477
01478 ChangeHandlerList *h = find_handlers(path);
01479 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01480 (*i)->config_value_erased(path, false);
01481 }
01482 delete h;
01483 }
01484
01485
01486 void
01487 SQLiteConfiguration::set_default_float(const char *path, float f)
01488 {
01489 sqlite3_stmt *stmt = NULL;
01490
01491 mutex->lock();
01492
01493 try {
01494 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
01495 if ( (sqlite3_bind_double(stmt, 1, f) != SQLITE_OK) ) {
01496 ConfigurationException ce("set_default_float/update/bind", sqlite3_errmsg(db));
01497 sqlite3_finalize(stmt);
01498 mutex->unlock();
01499 throw ce;
01500 }
01501 execute_insert_or_update(stmt);
01502 sqlite3_finalize(stmt);
01503 } catch (Exception &e) {
01504 if ( stmt != NULL ) sqlite3_finalize(stmt);
01505 mutex->unlock();
01506 throw;
01507 }
01508
01509 if ( sqlite3_changes(db) == 0 ) {
01510
01511
01512 try {
01513 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "float", path);
01514 if ( (sqlite3_bind_double(stmt, 3, f) != SQLITE_OK) ) {
01515 ConfigurationException ce("set_default_float/insert/bind", sqlite3_errmsg(db));
01516 sqlite3_finalize(stmt);
01517 mutex->unlock();
01518 throw ce;
01519 }
01520 execute_insert_or_update(stmt);
01521 sqlite3_finalize(stmt);
01522 } catch (Exception &e) {
01523 if ( stmt != NULL ) sqlite3_finalize(stmt);
01524 mutex->unlock();
01525 throw;
01526 }
01527 }
01528
01529 mutex->unlock();
01530
01531 ChangeHandlerList *h = find_handlers(path);
01532 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01533 (*i)->config_value_changed(path, true, f);
01534 }
01535 delete h;
01536 }
01537
01538
01539 void
01540 SQLiteConfiguration::set_default_uint(const char *path, unsigned int uint)
01541 {
01542 sqlite3_stmt *stmt = NULL;
01543
01544 mutex->lock();
01545
01546 try {
01547 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
01548 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) {
01549 ConfigurationException ce("set_default_uint/update/bind", sqlite3_errmsg(db));
01550 sqlite3_finalize(stmt);
01551 mutex->unlock();
01552 throw ce;
01553 }
01554 execute_insert_or_update(stmt);
01555 sqlite3_finalize(stmt);
01556 } catch (Exception &e) {
01557 if ( stmt != NULL ) sqlite3_finalize(stmt);
01558 mutex->unlock();
01559 throw;
01560 }
01561
01562 if ( sqlite3_changes(db) == 0 ) {
01563
01564
01565 try {
01566 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "unsigned int", path);
01567 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) {
01568 ConfigurationException ce("set_default_uint/insert/bind", sqlite3_errmsg(db));
01569 sqlite3_finalize(stmt);
01570 mutex->unlock();
01571 throw ce;
01572 }
01573 execute_insert_or_update(stmt);
01574 sqlite3_finalize(stmt);
01575 } catch (Exception &e) {
01576 if ( stmt != NULL ) sqlite3_finalize(stmt);
01577 mutex->unlock();
01578 throw;
01579 }
01580 }
01581 mutex->unlock();
01582
01583 ChangeHandlerList *h = find_handlers(path);
01584 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01585 (*i)->config_value_changed(path, true, uint);
01586 }
01587 delete h;
01588 }
01589
01590
01591 void
01592 SQLiteConfiguration::set_default_int(const char *path, int i)
01593 {
01594 sqlite3_stmt *stmt = NULL;
01595 mutex->lock();
01596
01597 try {
01598 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
01599 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) {
01600 ConfigurationException ce("set_default_int/update/bind", sqlite3_errmsg(db));
01601 sqlite3_finalize(stmt);
01602 mutex->unlock();
01603 throw ce;
01604 }
01605 execute_insert_or_update(stmt);
01606 sqlite3_finalize(stmt);
01607 } catch (Exception &e) {
01608 if ( stmt != NULL ) sqlite3_finalize(stmt);
01609 mutex->unlock();
01610 throw;
01611 }
01612
01613 if ( sqlite3_changes(db) == 0 ) {
01614
01615 try {
01616 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "int", path);
01617 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) {
01618 ConfigurationException ce("set_default_int/insert/bind", sqlite3_errmsg(db));
01619 sqlite3_finalize(stmt);
01620 mutex->unlock();
01621 throw ce;
01622 }
01623 execute_insert_or_update(stmt);
01624 sqlite3_finalize(stmt);
01625 } catch (Exception &e) {
01626 if ( stmt != NULL ) sqlite3_finalize(stmt);
01627 mutex->unlock();
01628 throw;
01629 }
01630 }
01631
01632 mutex->unlock();
01633
01634 ChangeHandlerList *h = find_handlers(path);
01635 for (ChangeHandlerList::const_iterator j = h->begin(); j != h->end(); ++j) {
01636 (*j)->config_value_changed(path, true, i);
01637 }
01638 delete h;
01639 }
01640
01641
01642 void
01643 SQLiteConfiguration::set_default_bool(const char *path, bool b)
01644 {
01645 sqlite3_stmt *stmt = NULL;
01646
01647 mutex->lock();
01648
01649 try {
01650 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
01651 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) {
01652 ConfigurationException ce("set_default_bool/update/bind", sqlite3_errmsg(db));
01653 sqlite3_finalize(stmt);
01654 mutex->unlock();
01655 throw ce;
01656 }
01657 execute_insert_or_update(stmt);
01658 sqlite3_finalize(stmt);
01659 } catch (Exception &e) {
01660 if ( stmt != NULL ) sqlite3_finalize(stmt);
01661 mutex->unlock();
01662 throw;
01663 }
01664
01665 if ( sqlite3_changes(db) == 0 ) {
01666
01667
01668 try {
01669 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "bool", path);
01670 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) {
01671 ConfigurationException ce("set_default_bool/insert/bind", sqlite3_errmsg(db));
01672 sqlite3_finalize(stmt);
01673 mutex->unlock();
01674 throw ce;
01675 }
01676 execute_insert_or_update(stmt);
01677 sqlite3_finalize(stmt);
01678 } catch (Exception &e) {
01679 if ( stmt != NULL ) sqlite3_finalize(stmt);
01680 mutex->unlock();
01681 throw;
01682 }
01683 }
01684
01685 mutex->unlock();
01686
01687 ChangeHandlerList *h = find_handlers(path);
01688 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01689 (*i)->config_value_changed(path, true, b);
01690 }
01691 delete h;
01692 }
01693
01694
01695 void
01696 SQLiteConfiguration::set_default_string(const char *path,
01697 const char *s)
01698 {
01699 sqlite3_stmt *stmt = NULL;
01700
01701 mutex->lock();
01702 size_t s_length = strlen(s);
01703
01704 try {
01705 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
01706 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01707 ConfigurationException ce("set_default_string/update/bind", sqlite3_errmsg(db));
01708 sqlite3_finalize(stmt);
01709 mutex->unlock();
01710 throw ce;
01711 }
01712 execute_insert_or_update(stmt);
01713 sqlite3_finalize(stmt);
01714 } catch (Exception &e) {
01715 if ( stmt != NULL ) sqlite3_finalize(stmt);
01716 mutex->unlock();
01717 throw;
01718 }
01719
01720 if ( sqlite3_changes(db) == 0 ) {
01721
01722
01723 try {
01724 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "string", path);
01725 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01726 ConfigurationException ce("set_default_string/insert/bind", sqlite3_errmsg(db));
01727 sqlite3_finalize(stmt);
01728 mutex->unlock();
01729 throw ce;
01730 }
01731 execute_insert_or_update(stmt);
01732 sqlite3_finalize(stmt);
01733 } catch (Exception &e) {
01734 if ( stmt != NULL ) sqlite3_finalize(stmt);
01735 mutex->unlock();
01736 throw;
01737 }
01738 }
01739
01740 mutex->unlock();
01741
01742 ChangeHandlerList *h = find_handlers(path);
01743 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01744 (*i)->config_value_changed(path, true, s);
01745 }
01746 delete h;
01747 }
01748
01749
01750 void
01751 SQLiteConfiguration::set_default_string(const char *path, std::string &s)
01752 {
01753 set_default_string(path, s.c_str());
01754 }
01755
01756
01757 void
01758 SQLiteConfiguration::set_default_comment(const char *path, const char *comment)
01759 {
01760 sqlite3_stmt *stmt = NULL;
01761
01762 mutex->lock();
01763 size_t s_length = strlen(comment);
01764
01765 try {
01766 stmt = prepare_update(SQL_UPDATE_DEFAULT_COMMENT, path);
01767 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) {
01768 ConfigurationException ce("set_default_comment/update/bind", sqlite3_errmsg(db));
01769 sqlite3_finalize(stmt);
01770 mutex->unlock();
01771 throw ce;
01772 }
01773 execute_insert_or_update(stmt);
01774 sqlite3_finalize(stmt);
01775 } catch (Exception &e) {
01776 if ( stmt != NULL ) sqlite3_finalize(stmt);
01777 mutex->unlock();
01778 throw;
01779 }
01780
01781 if ( sqlite3_changes(db) == 0 ) {
01782
01783 mutex->unlock();
01784 throw ConfigurationException("set_default_comment", "Cannot set comment for inexistent path");
01785 }
01786
01787 mutex->unlock();
01788
01789 ChangeHandlerList *h = find_handlers(path);
01790 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01791 (*i)->config_comment_changed(path, true, comment);
01792 }
01793 delete h;
01794 }
01795
01796
01797 void
01798 SQLiteConfiguration::set_default_comment(const char *path, std::string &comment)
01799 {
01800 set_default_comment(path, comment.c_str());
01801 }
01802
01803
01804 void
01805 SQLiteConfiguration::erase_default(const char *path)
01806 {
01807 sqlite3_stmt *stmt;
01808 const char *tail;
01809
01810 if ( sqlite3_prepare(db, SQL_DELETE_DEFAULT_VALUE, -1, &stmt, &tail) != SQLITE_OK ) {
01811 throw ConfigurationException("erase_default/prepare", sqlite3_errmsg(db));
01812 }
01813 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) {
01814 ConfigurationException ce("erase_default/bind", sqlite3_errmsg(db));
01815 sqlite3_finalize(stmt);
01816 throw ce;
01817 }
01818
01819 if ( sqlite3_step(stmt) != SQLITE_DONE ) {
01820 ConfigurationException ce("erase_default/execute", sqlite3_errmsg(db));
01821 sqlite3_finalize(stmt);
01822 throw ce;
01823 }
01824
01825 sqlite3_finalize(stmt);
01826
01827 ChangeHandlerList *h = find_handlers(path);
01828 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) {
01829 (*i)->config_value_erased(path, true);
01830 }
01831 delete h;
01832 }
01833
01834
01835
01836
01837
01838
01839 void
01840 SQLiteConfiguration::lock()
01841 {
01842 mutex->lock();
01843 }
01844
01845
01846
01847
01848
01849
01850 bool
01851 SQLiteConfiguration::try_lock()
01852 {
01853 return mutex->try_lock();
01854 }
01855
01856
01857
01858
01859 void
01860 SQLiteConfiguration::unlock()
01861 {
01862 mutex->unlock();
01863 }
01864
01865
01866 Configuration::ValueIterator *
01867 SQLiteConfiguration::iterator()
01868 {
01869 sqlite3_stmt *stmt;
01870 const char *tail;
01871
01872 if ( sqlite3_prepare(db, SQL_SELECT_ALL, -1, &stmt, &tail) != SQLITE_OK ) {
01873 throw ConfigurationException("iterator: Preparation SQL failed");
01874 }
01875
01876 return new SQLiteValueIterator(stmt);
01877 }
01878
01879
01880 Configuration::ValueIterator *
01881 SQLiteConfiguration::iterator_default()
01882 {
01883 sqlite3_stmt *stmt;
01884 const char *tail;
01885
01886 if ( sqlite3_prepare(db, SQL_SELECT_ALL_DEFAULT, -1, &stmt, &tail) != SQLITE_OK ) {
01887 throw ConfigurationException("iterator_default: Preparation SQL failed");
01888 }
01889
01890 return new SQLiteValueIterator(stmt);
01891 }
01892
01893 Configuration::ValueIterator *
01894 SQLiteConfiguration::iterator_hostspecific()
01895 {
01896 sqlite3_stmt *stmt;
01897 const char *tail;
01898
01899 if ( sqlite3_prepare(db, SQL_SELECT_ALL_HOSTSPECIFIC, -1, &stmt, &tail) != SQLITE_OK ) {
01900 throw ConfigurationException("iterator_hostspecific: Preparation SQL failed");
01901 }
01902
01903 return new SQLiteValueIterator(stmt);
01904 }
01905
01906
01907
01908
01909
01910
01911 SQLiteConfiguration::SQLiteValueIterator *
01912 SQLiteConfiguration::modified_iterator()
01913 {
01914 sqlite3_stmt *stmt;
01915 const char *tail;
01916
01917 if ( sqlite3_prepare(db, SQL_SELECT_MODIFIED_ALL, -1, &stmt, &tail) != SQLITE_OK ) {
01918 throw ConfigurationException("modified_iterator: Preparation SQL failed");
01919 }
01920
01921 return new SQLiteValueIterator(stmt);
01922 }
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936 Configuration::ValueIterator *
01937 SQLiteConfiguration::search(const char *path)
01938 {
01939 sqlite3_stmt *stmt;
01940 const char *tail;
01941
01942 char *p;
01943 if ( asprintf(&p, "%s%%", path) == -1 ) {
01944 throw ConfigurationException("search: could not allocate component string");
01945 }
01946
01947 if ( sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK ) {
01948 free(p);
01949 throw ConfigurationException("begin: Preparation SQL failed");
01950 }
01951 if ( sqlite3_bind_text(stmt, 1, p, -1, NULL) != SQLITE_OK ) {
01952 free(p);
01953 throw ConfigurationException("begin: Binding text for path failed (1)");
01954 }
01955 if ( sqlite3_bind_text(stmt, 2, p, -1, NULL) != SQLITE_OK ) {
01956 free(p);
01957 throw ConfigurationException("begin: Binding text for path failed (2)");
01958 }
01959
01960 return new SQLiteValueIterator(stmt, p);
01961 }
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 SQLiteConfiguration::SQLiteValueIterator::SQLiteValueIterator(::sqlite3_stmt *stmt, void *p)
01974 {
01975 __stmt = stmt;
01976 __p = p;
01977 }
01978
01979
01980
01981 SQLiteConfiguration::SQLiteValueIterator::~SQLiteValueIterator()
01982 {
01983 if ( __stmt != NULL ) {
01984 sqlite3_finalize(__stmt);
01985 __stmt = NULL;
01986 }
01987 if ( __p != NULL ) {
01988 free(__p);
01989 }
01990 }
01991
01992
01993
01994
01995
01996
01997 bool
01998 SQLiteConfiguration::SQLiteValueIterator::next()
01999 {
02000 if ( __stmt == NULL) return false;
02001
02002 if (sqlite3_step(__stmt) == SQLITE_ROW ) {
02003 return true;
02004 } else {
02005 sqlite3_finalize(__stmt);
02006 __stmt = NULL;
02007 return false;
02008 }
02009 }
02010
02011
02012
02013
02014
02015
02016 bool
02017 SQLiteConfiguration::SQLiteValueIterator::valid()
02018 {
02019 return ( __stmt != NULL);
02020 }
02021
02022
02023
02024
02025
02026 const char *
02027 SQLiteConfiguration::SQLiteValueIterator::path()
02028 {
02029 return (const char *)sqlite3_column_text(__stmt, 0);
02030 }
02031
02032
02033
02034
02035
02036 const char *
02037 SQLiteConfiguration::SQLiteValueIterator::type()
02038 {
02039 return (const char *)sqlite3_column_text(__stmt, 1);
02040 }
02041
02042
02043
02044
02045
02046 bool
02047 SQLiteConfiguration::SQLiteValueIterator::is_float()
02048 {
02049 return (strcmp("float", (const char *)sqlite3_column_text(__stmt, 1)) == 0);
02050 }
02051
02052
02053
02054
02055
02056 bool
02057 SQLiteConfiguration::SQLiteValueIterator::is_uint()
02058 {
02059 return (strcmp("unsigned int", (const char *)sqlite3_column_text(__stmt, 1)) == 0);
02060 }
02061
02062
02063
02064
02065 bool
02066 SQLiteConfiguration::SQLiteValueIterator::is_int()
02067 {
02068 return (strcmp("int", (const char *)sqlite3_column_text(__stmt, 1)) == 0);
02069 }
02070
02071
02072
02073
02074
02075 bool
02076 SQLiteConfiguration::SQLiteValueIterator::is_bool()
02077 {
02078 return (strcmp("bool", (const char *)sqlite3_column_text(__stmt, 1)) == 0);
02079 }
02080
02081
02082
02083
02084
02085 bool
02086 SQLiteConfiguration::SQLiteValueIterator::is_string()
02087 {
02088 return (strcmp("string", (const char *)sqlite3_column_text(__stmt, 1)) == 0);
02089 }
02090
02091 bool
02092 SQLiteConfiguration::SQLiteValueIterator::is_default()
02093 {
02094 return (sqlite3_column_int(__stmt, 4) == 1);
02095 }
02096
02097
02098
02099
02100
02101 float
02102 SQLiteConfiguration::SQLiteValueIterator::get_float()
02103 {
02104 return (float)sqlite3_column_double(__stmt, 2);
02105 }
02106
02107
02108
02109
02110
02111 unsigned int
02112 SQLiteConfiguration::SQLiteValueIterator::get_uint()
02113 {
02114 int i = sqlite3_column_int(__stmt, 2);
02115 if( i < 0 ) {
02116 return 0;
02117 } else {
02118 return i;
02119 }
02120 }
02121
02122
02123
02124
02125
02126 int
02127 SQLiteConfiguration::SQLiteValueIterator::get_int()
02128 {
02129 return sqlite3_column_int(__stmt, 2);
02130 }
02131
02132
02133
02134
02135 bool
02136 SQLiteConfiguration::SQLiteValueIterator::get_bool()
02137 {
02138 return (sqlite3_column_int(__stmt, 2) != 0);
02139 }
02140
02141
02142
02143
02144 std::string
02145 SQLiteConfiguration::SQLiteValueIterator::get_string()
02146 {
02147 return (const char *)sqlite3_column_text(__stmt, 2);
02148 }
02149
02150
02151
02152
02153
02154 std::string
02155 SQLiteConfiguration::SQLiteValueIterator::get_as_string()
02156 {
02157 return (const char *)sqlite3_column_text(__stmt, 2);
02158 }
02159
02160
02161
02162
02163 std::string
02164 SQLiteConfiguration::SQLiteValueIterator::get_comment()
02165 {
02166 const char *c = (const char *)sqlite3_column_text(__stmt, 3);
02167 return c ? c : "";
02168 }
02169
02170
02171
02172
02173
02174
02175
02176 std::string
02177 SQLiteConfiguration::SQLiteValueIterator::get_modtype()
02178 {
02179 const char *c = (const char *)sqlite3_column_text(__stmt, 4);
02180 return c ? c : "";
02181 }
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192 std::string
02193 SQLiteConfiguration::SQLiteValueIterator::get_oldvalue()
02194 {
02195 const char *c = (const char *)sqlite3_column_text(__stmt, 5);
02196 return c ? c : "";
02197 }
02198
02199
02200 }