The unified diff between revisions [30d555c4..] and [900934c7..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "init.sql"
#  from [d2b63fc6563a0cb09ce7d56c1edeb4919295f2a0]
#    to [98c619d34be3c004009e650df8c5282ec4fce633]
#
# patch "sqlite-backend.c"
#  from [0946a508d2831f62ee1d1c7784d62b1eaef7f1b0]
#    to [9396b2d5c05b0c4802dd5c7e19f076cf97a48426]
#
============================================================
--- init.sql	d2b63fc6563a0cb09ce7d56c1edeb4919295f2a0
+++ init.sql	98c619d34be3c004009e650df8c5282ec4fce633
@@ -17,21 +17,62 @@ CREATE TABLE keys (
 	directory_id integer not null,
 	mod_user text,
 	mod_time text,
-	schema_name text,
 	value_type text,
 	value,
 	UNIQUE (name, directory_id)
 );

+CREATE TABLE keys_to_schema_name (
+	key_id integer primary key,
+	schema_name text
+);
+
 CREATE TABLE lists (
 	key_id integer,
 	list_idx integer,
+	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
+);
+
+CREATE TABLE schemas (
+	key_id integer primary key,
+	schema_type text,
+	scheam_list_type text,
+	schema_car_type text,
+	schema_cdr_type text,
+	locale text,
+	owner text,
+	short_desc text,
+	long_desc text,
+	default_value_id integer
+);
+
+CREATE TABLE schemas_keys (
+	id integer primary key,
+	name text,
+	directory_id integer not null,
 	value_type text,
+	value,
+	UNIQUE (name, directory_id)
+);
+
+CREATE TABLE schemas_lists (
+	key_id integer,
+	list_idx integer,
+	value_type text,
 	value,
 	UNIQUE (key_id, list_idx)
 );

-CREATE TABLE pairs (
+CREATE TABLE schemas_pairs (
 	key_id integer primary key,
 	car_value_type text,
 	car_value,
============================================================
--- sqlite-backend.c	0946a508d2831f62ee1d1c7784d62b1eaef7f1b0
+++ sqlite-backend.c	9396b2d5c05b0c4802dd5c7e19f076cf97a48426
@@ -303,7 +303,7 @@ abort_transaction (SqliteSource *ss)
 	char *query, *err_mesg;

 	rv = TRUE;
-	query = "ABORT";
+	query = "ROLLBACK";
 	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);
@@ -415,11 +415,133 @@ gboolean
 }

 gboolean
+insert_or_update_value (SqliteSource *ss, SqliteDirectory *dir, const char *name, const GConfValue *value)
+{
+	gchar *mod_user;
+	GTime mod_time;
+	gboolean rv;
+	GConfValueType list_type;
+	char *query, *lt, *err_mesg;
+
+	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 want to update these at the same time */
+	mod_user = get_username ();
+	mod_time = time (NULL);
+
+#define BASIC_INSERT	"INSERT OR REPLACE INTO keys (name, directory_id, mod_user, mod_time, value_type, value) VALUES "
+#define T_STRING	"s"
+#define T_INT		"i"
+#define T_FLOAT		"f"
+#define T_BOOL		"b"
+#define T_SCHEMA	"c"
+#define T_LIST		"l"
+#define T_PAIR		"p"
+
+	rv = TRUE;
+	query = NULL;
+	switch (value->type) {
+		case GCONF_VALUE_STRING:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', '%q')",
+					name, dir->id, mod_user, mod_time, T_STRING, gconf_value_get_string (value));
+			break;
+		case GCONF_VALUE_INT:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', %d)",
+					name, dir->id, mod_user, mod_time, T_INT, gconf_value_get_int (value));
+			break;
+		case GCONF_VALUE_FLOAT:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', %f)",
+					name, dir->id, mod_user, mod_time, T_FLOAT, gconf_value_get_float (value));
+			break;
+		case GCONF_VALUE_BOOL:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', %d)",
+					name, dir->id, mod_user, mod_time, T_BOOL, gconf_value_get_bool (value));
+			break;
+		case GCONF_VALUE_SCHEMA:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', NULL)",
+					name, dir->id, mod_user, mod_time, T_SCHEMA);
+			break;
+		case GCONF_VALUE_LIST:
+			list_type = gconf_value_get_list_type (value);
+			if (list_type == GCONF_VALUE_STRING) {
+				lt = T_STRING;
+			} else if (list_type == GCONF_VALUE_INT) {
+				lt = T_INT;
+			} else if (list_type == GCONF_VALUE_FLOAT) {
+				lt = T_FLOAT;
+			} else if (list_type == GCONF_VALUE_BOOL) {
+				lt = T_BOOL;
+			} else {
+				gconf_log (GCL_ERR, "(insert_or_update_value) List is of invalid type.");
+				rv = FALSE;
+				break;
+			}
+			printf("%lld\n", dir->id);
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', '%q')",
+					name, dir->id, mod_user, mod_time, T_LIST, lt);
+			break;
+		case GCONF_VALUE_PAIR:
+			query = sqlite3_mprintf (BASIC_INSERT "('%q', %lld, '%q', %d, '%q', NULL)",
+					name, dir->id, mod_user, mod_time, T_PAIR);
+			break;
+		case GCONF_VALUE_INVALID:
+		default:
+			gconf_log (GCL_ERR, "(insert_or_update_value) Attempt to insert item with invalid type.");
+			rv = FALSE;
+			break;
+	}
+
+	if (!rv) {
+		if (query)
+			sqlite3_free (query);
+		return rv;
+	}
+
+	/* okay, so we have a query that does what we want. execute it. */
+	if (sqlite3_exec (ss->db, query, NULL, NULL, &err_mesg) != SQLITE_OK) {
+		gconf_log (GCL_ERR, "(insert_or_update_value) SQL error: %s", err_mesg);
+		sqlite3_free (err_mesg);
+		rv = FALSE;
+	}
+
+	sqlite3_free (query);
+
+	return rv;
+}
+
+gboolean
+insert_list_for_key (SqliteSource *ss, const GConfValue *value, long long int last_rowid)
+{
+	g_return_val_if_fail (ss != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	return FALSE;
+}
+
+gboolean
+insert_pair_for_key (SqliteSource *ss, const GConfValue *value, long long int last_rowid)
+{
+	g_return_val_if_fail (ss != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	return FALSE;
+}
+
+gboolean
+insert_schema_for_key (SqliteSource *ss, const GConfValue *value, long long int last_rowid)
+{
+	g_return_val_if_fail (ss != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	return FALSE;
+}
+
+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;

@@ -441,8 +563,6 @@ set_value_in_directory (SqliteSource *ss
 	 */

 	rv = TRUE;
-	mod_time = time (NULL);
-	mod_user = get_username ();

 	do {
 		if (!start_transaction (ss)) {
@@ -454,6 +574,9 @@ set_value_in_directory (SqliteSource *ss
 		 * the best; it's slower (eg. might do a pair of DELETEs we don't need)
 		 * but it does mean that there's no chance of us leaving a
 		 * pair or list dangling by mistake
+		 *
+		 * Note: old schema values are fine
+		 * (they are in the key_to_schema_name table)
 		 */
 		if (get_value_id_in_directory (ss, dir, name, &existing_id)) {
 			if (!delete_old_list (ss, existing_id)) {
@@ -465,11 +588,37 @@ set_value_in_directory (SqliteSource *ss
 				break;
 			}
 		}
-		/*
-		if (!insert_or_update (ss, value)) {
+		/* whatever type we're inserting, we need to have a row in the keys
+		 * table. if we're inserting a GCONF_VALUE_LIST,  GCONF_VALUE_PAIR,
+		 * or GCONF_VALUE_SCHEMA another row in a seperate table will be
+		 * needed. this row will reference the row in keys.
+		 */
+		if (!insert_or_update_value (ss, dir, name, value)) {
 			rv = FALSE;
 			break;
-		} */
+		}
+		if (value->type == GCONF_VALUE_LIST) {
+			long long int last_rowid;
+			last_rowid = sqlite3_last_insert_rowid (ss->db);
+			if (!insert_list_for_key (ss, value, last_rowid)) {
+				rv = FALSE;
+				break;
+			}
+		} else if (value->type == GCONF_VALUE_PAIR) {
+			long long int last_rowid;
+			last_rowid = sqlite3_last_insert_rowid (ss->db);
+			if (!insert_pair_for_key (ss, value, last_rowid)) {
+				rv = FALSE;
+				break;
+			}
+		} else if (value->type == GCONF_VALUE_SCHEMA) {
+			long long int last_rowid;
+			last_rowid = sqlite3_last_insert_rowid (ss->db);
+			if (!insert_schema_for_key (ss, value, last_rowid)) {
+				rv = FALSE;
+				break;
+			}
+		}
 	} while (0);

 	if (rv) {
@@ -478,31 +627,6 @@ set_value_in_directory (SqliteSource *ss
 		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;