The unified diff between revisions [65f52f37..] and [36cf2167..] is displayed below. It can also be downloaded as a raw diff.
#
#
# patch "init.sql"
# from [1a59f2ab0d1a31dc4596d27c1bb5c4909ce142c8]
# to [d2b63fc6563a0cb09ce7d56c1edeb4919295f2a0]
#
# patch "sqlite-backend.c"
# from [af95cdd5712ae796993989b936e174564c6d3c72]
# to [4be9ea4621c58f7736a6fa49103d27643c14a946]
#
============================================================
--- init.sql 1a59f2ab0d1a31dc4596d27c1bb5c4909ce142c8
+++ init.sql d2b63fc6563a0cb09ce7d56c1edeb4919295f2a0
@@ -11,7 +11,7 @@ CREATE TABLE directories (
UNIQUE (name, parent_id)
);
-CREATE TABLE entries (
+CREATE TABLE keys (
id integer primary key,
name text,
directory_id integer not null,
@@ -24,9 +24,18 @@ CREATE TABLE lists (
);
CREATE TABLE lists (
- list_id integer,
+ key_id integer,
list_idx integer,
value_type text,
- value blob
+ value,
+ UNIQUE (key_id, list_idx)
);
+CREATE TABLE pairs (
+ key_id integer primary key,
+ car_value_type text,
+ car_value,
+ cdr_value_type text,
+ cdr_value
+);
+
============================================================
--- sqlite-backend.c af95cdd5712ae796993989b936e174564c6d3c72
+++ sqlite-backend.c 4be9ea4621c58f7736a6fa49103d27643c14a946
@@ -30,9 +30,12 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sqlite3.h>
+#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
+#include <pwd.h>
#define ROOT_DIRECTORY_PARENT -1
#define ROOT_DIRECTORY_NAME ""
@@ -112,6 +115,7 @@ update_failure (GError **err)
static void
update_failure (GError **err)
{
+ return; // TODO: don't leave this commented out!
g_set_error (err, GCONF_ERROR,
GCONF_ERROR_FAILED,
_("Failed to write some configuration data to disk\n"));
@@ -125,6 +129,7 @@ get_directory (SqliteSource *ss, SqliteD
static gboolean
get_directory (SqliteSource *ss, SqliteDirectory *parent, const char *name, SqliteDirectory *dir)
{
+ long long int id;
char *query, *tail;
gboolean rv;
long long int nrow;
@@ -151,7 +156,7 @@ get_directory (SqliteSource *ss, SqliteD
res = sqlite3_step (statement);
if (res == SQLITE_ROW) {
nrow++;
- dir->id = sqlite3_column_int64(statement, 0);
+ id = sqlite3_column_int64(statement, 0);
} else if (res == SQLITE_DONE) {
break;
} else {
@@ -159,6 +164,7 @@ get_directory (SqliteSource *ss, SqliteD
SQLITE_BUSY || res == SQLITE_ERROR || res == SQLITE_MISUSE
*/
gconf_log (GCL_ERR, "(get_directory) query error\n");
+ rv = FALSE;
break;
}
}
@@ -166,6 +172,9 @@ get_directory (SqliteSource *ss, SqliteD
if (nrow != 1)
rv = FALSE;
+ if (rv)
+ dir->id = id;
+
sqlite3_finalize (statement);
sqlite3_free (query);
@@ -256,13 +265,246 @@ traverse_to_directory (SqliteSource *ss,
return rv;
}
+static char *
+get_username (void)
+{
+ uid_t uid;
+ struct passwd *pw;
+
+ uid = getuid();
+ if (uid < 0)
+ return NULL;
+ pw = getpwuid(uid);
+ if (!pw)
+ return NULL;
+ return g_strdup(pw->pw_name);
+}
+
+static gboolean
+start_transaction (SqliteSource *ss)
+{
+ gboolean rv;
+ char *query, *err_mesg;
+
+ rv = TRUE;
+ query = "BEGIN";
+ if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(start_transaction) SQL error: %s", err_mesg);
+ sqlite3_free (err_mesg);
+ rv = FALSE;
+ }
+ return rv;
+}
+
+static gboolean
+abort_transaction (SqliteSource *ss)
+{
+ gboolean rv;
+ char *query, *err_mesg;
+
+ rv = TRUE;
+ query = "ABORT";
+ if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(abort_transaction) SQL error: %s", err_mesg);
+ sqlite3_free (err_mesg);
+ rv = FALSE;
+ }
+ return rv;
+}
+
+static gboolean
+commit_transaction (SqliteSource *ss)
+{
+ gboolean rv;
+ char *query, *err_mesg;
+
+ rv = TRUE;
+ query = "COMMIT";
+ if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(commit_transaction) SQL error: %s", err_mesg);
+ sqlite3_free (err_mesg);
+ rv = FALSE;
+ }
+ return rv;
+}
+
gboolean
-set_value_in_directory (SqliteSource *ss, SqliteDirectory *dir, const char *name, gboolean do_create, GError **error)
+get_value_id_in_directory (SqliteSource *ss, SqliteDirectory *dir, const char *name, long long int *id)
{
+ long long int possible_id, nrow;
+ char *query, *tail;
+ gboolean rv;
+ int res;
+ sqlite3_stmt *statement;
+
g_return_val_if_fail (ss != NULL, FALSE);
g_return_val_if_fail (dir != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
+ query = sqlite3_mprintf ("SELECT id FROM keys WHERE directory_id=%lld AND name='%q'", dir->id, name);
+ if (sqlite3_prepare (ss->db, query, strlen(query), &statement, (const char **)&tail) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(get_value_id_in_directory) Unable to compile query: %s", query);
+ sqlite3_free (query);
+ return FALSE;
+ }
+
+ nrow = 0;
+ rv = TRUE;
+
+ for (;;) {
+ res = sqlite3_step (statement);
+ if (res == SQLITE_ROW) {
+ nrow++;
+ possible_id = sqlite3_column_int64 (statement, 0);
+ } else if (res == SQLITE_DONE) {
+ break;
+ } else {
+ /* ought to be one of:
+ SQLITE_BUSY || res == SQLITE_ERROR || res == SQLITE_MISUSE
+ */
+ gconf_log (GCL_ERR, "(get_directory) query error\n");
+ break;
+ }
+ }
+
+ if (nrow != 1)
+ rv = FALSE;
+
+ if (rv)
+ *id = possible_id;
+
+ sqlite3_free (query);
+ sqlite3_finalize (statement);
+ return rv;
+}
+
+gboolean
+delete_old_list (SqliteSource *ss, long long int id)
+{
+ gboolean rv;
+ char *query, *err_mesg;
+
+ rv = TRUE;
+ query = sqlite3_mprintf ("DELETE FROM lists WHERE key_id=%lld", id);
+ if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(delete_old_list) SQL error: %s", err_mesg);
+ sqlite3_free (err_mesg);
+ rv = FALSE;
+ }
+
+ sqlite3_free (query);
+ return rv;
+}
+
+gboolean
+delete_old_pair (SqliteSource *ss, long long int id)
+{
+ gboolean rv;
+ char *query, *err_mesg;
+
+ rv = TRUE;
+ query = sqlite3_mprintf ("DELETE FROM pairs WHERE key_id=%lld", id);
+ if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+ gconf_log (GCL_ERR, "(delete_old_pair) SQL error: %s", err_mesg);
+ sqlite3_free (err_mesg);
+ rv = FALSE;
+ }
+
+ sqlite3_free (query);
+ return rv;
+}
+
+gboolean
+set_value_in_directory (SqliteSource *ss, SqliteDirectory *dir, const char *name, const GConfValue *value, GError **error)
+{
+ char *query = NULL;
+ GTime mod_time;
+ gchar *mod_user;
+ gboolean rv;
+ long long int existing_id;
+
+ g_return_val_if_fail (ss != NULL, FALSE);
+ g_return_val_if_fail (dir != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ /*
+ * we need to handle several things here
+ *
+ * first consideration; this might be a new key, or it might be an update to an existing key
+ * if we're updating, we need to handle non-scalar types correctly. this basically means removing
+ * the old list / pair and then adding a new one in.
+ *
+ * second consideration; need to do clean insert of non-scalar types.
+ *
+ * third consideration; make sure we do it all in a transaction block, and abort the transaction
+ * appropriately if something goes wrong.
+ */
+
+ rv = TRUE;
+ mod_time = time (NULL);
+ mod_user = get_username ();
+
+ do {
+ if (!start_transaction (ss)) {
+ rv = FALSE;
+ break;
+ }
+ if (get_value_id_in_directory (ss, dir, name, &existing_id)) {
+ if (!delete_old_list (ss, existing_id)) {
+ rv = FALSE;
+ break;
+ }
+ if (!delete_old_pair (ss, existing_id)) {
+ rv = FALSE;
+ break;
+ }
+ }
+ /*
+ if (!insert_or_update (ss, value)) {
+ rv = FALSE;
+ break;
+ } */
+ } while (0);
+
+ if (rv) {
+ commit_transaction (ss);
+ } else {
+ abort_transaction (ss);
+ }
+
+ switch (value->type) {
+ case GCONF_VALUE_STRING:
+ query = sqlite3_mprintf ("INSERT OR REPLACE INTO keys (name, directory_id, value_type, value) VALUES ('%q', %lld, '%c', '%q')",
+ name, dir->id, 's', gconf_value_get_string (value));
+ break;
+ case GCONF_VALUE_INT:
+ query = g_strdup("int");
+ break;
+ case GCONF_VALUE_FLOAT:
+ query = g_strdup("float");
+ break;
+ case GCONF_VALUE_BOOL:
+ query = g_strdup("bool");
+ break;
+ case GCONF_VALUE_LIST:
+ query = g_strdup("list");
+ break;
+ case GCONF_VALUE_PAIR:
+ query = g_strdup("pair");
+ break;
+ case GCONF_VALUE_INVALID:
+ default:
+ /* invalid */
+ break;
+ }
+
+ if (!query)
+ return FALSE;
+
+ printf("query is: %s\n", query);
+
+ sqlite3_free (query);
+
return FALSE;
}
@@ -481,8 +723,9 @@ set_value (GConfSource *source,
update_failure (err);
break;
}
- if (!set_value_in_directory ((SqliteSource *)source, dir, relative_key, TRUE, err)) {
+ if (!set_value_in_directory ((SqliteSource *)source, dir, relative_key, value, err)) {
update_failure (err);
+ break;
}
} while (0);