The unified diff between revisions [a3ea8099..] and [b79120d5..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "init.sql"
#  from [98c619d34be3c004009e650df8c5282ec4fce633]
#    to [97c58b5287740e5f5539e1db34a1df5611457c65]
#
# patch "sqlite-backend.c"
#  from [f025f9a3c4d26235cffa218e50380824fd8e2b0c]
#    to [a1dbbb3ce687ef23785310a1476019033fb43a6c]
#
============================================================
--- init.sql	98c619d34be3c004009e650df8c5282ec4fce633
+++ init.sql	97c58b5287740e5f5539e1db34a1df5611457c65
@@ -1,9 +1,20 @@

+--
+-- this SQL file initialises an SQLite database
+-- so that it is in a state suitable to host a
+-- GConf database.
+--
+
+-- just for checking. the SQLite backend looks
+-- for this table and checks the version matches
+-- that in this file
 CREATE TABLE gconf (
 	version integer
 );
 INSERT INTO gconf (version) VALUES (1);

+-- this table represents directories. one row
+-- per directory.
 CREATE TABLE directories (
 	id integer primary key,
 	name text not null,
@@ -11,6 +22,14 @@ CREATE TABLE directories (
 	UNIQUE (name, parent_id)
 );

+-- a key is an entry. it must be in a given directory.
+-- there can only be one key with a given name in a given
+-- directory
+--
+-- value_type indicates the type. in the case of scalar types,
+-- value is the actual value. in the case of a list, 'value'
+-- indicates the type of all values in the list. in all other
+-- cases, value has no meaning.
 CREATE TABLE keys (
 	id integer primary key,
 	name text,
@@ -22,11 +41,18 @@ CREATE TABLE keys (
 	UNIQUE (name, directory_id)
 );

-CREATE TABLE keys_to_schema_name (
+-- the schema associated with a key
+-- (not necessarily set for a given key)
+CREATE TABLE keys_to_schema(
 	key_id integer primary key,
-	schema_name text
+	schematext
 );

+-- represents lists. a list value for a given key has key_id to match
+-- the keys table, and is ordered by increasing values of list_idx
+--
+-- nb: special case; could be a schema default value, iff the type of
+-- key_id in keys is schema and it has a default value which is a list
 CREATE TABLE lists (
 	key_id integer,
 	list_idx integer,
@@ -34,6 +60,11 @@ CREATE TABLE lists (
 	UNIQUE (key_id, list_idx)
 );

+-- represents a pair. a pair has two values, which may be of different
+-- types. these values must be scalar.
+--
+-- nb: special case; could be a schema default value, iff the type of
+-- key_id in keys is schema and it has a default value which is a pair
 CREATE TABLE pairs (
 	key_id integer primary key,
 	car_value_type text,
@@ -42,10 +73,22 @@ CREATE TABLE pairs (
 	cdr_value
 );

+-- represents a schema. match on key_id.
+-- schema_type indicates the type of value required
+-- in the case that this is list or pair, schema_list_type
+-- and schema_car_type,schema_cdr_type apply.
+-- owner, short_desc, long_desc are just text values to be stored.
+--
+-- locale indicates the locale for which this schema is valid
+-- this is the only localised type
+--
+-- default_value_id is an index into schema_defaults, indicating
+-- the value which an entry to which this schema applies should default
+-- to
 CREATE TABLE schemas (
 	key_id integer primary key,
 	schema_type text,
-	scheam_list_type text,
+	schema_list_type text,
 	schema_car_type text,
 	schema_cdr_type text,
 	locale text,
@@ -55,28 +98,11 @@ CREATE TABLE schemas (
 	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 schemas_pairs (
+-- the default value for a given schema
+-- for schema with matching key_id
+CREATE TABLE schemas_defaults (
 	key_id integer primary key,
-	car_value_type text,
-	car_value,
-	cdr_value_type text,
-	cdr_value
+	value_type text,
+	value
 );

============================================================
--- sqlite-backend.c	f025f9a3c4d26235cffa218e50380824fd8e2b0c
+++ sqlite-backend.c	a1dbbb3ce687ef23785310a1476019033fb43a6c
@@ -423,8 +423,9 @@ delete_old_pair (SqliteSource *ss, long
 	return rv;
 }

+/* only returns non-NULL for valid, _scalar_ types */
 static const char *
-get_type_for_column (GConfValueType t)
+get_scalar_type_for_column (GConfValueType t)
 {
 	const char *lt;

@@ -443,8 +444,12 @@ get_type_for_column (GConfValueType t)
 	return lt;
 }

+/* this function inserts (or on conflict, replaces) a row into the keys table.
+ * nothing more, nothing less :-)
+ * returns true if successful
+ */
 static gboolean
-insert_or_update_value (SqliteSource *ss, SqliteDirectory *dir, const char *name, const GConfValue *value)
+insert_or_replace_value (SqliteSource *ss, SqliteDirectory *dir, const char *name, const GConfValue *value)
 {
 	gchar *mod_user;
 	GTime mod_time;
@@ -488,9 +493,9 @@ insert_or_update_value (SqliteSource *ss
 			break;
 		case GCONF_VALUE_LIST:
 			list_type = gconf_value_get_list_type (value);
-			lt = get_type_for_column (list_type);
+			lt = get_scalar_type_for_column (list_type);
 			if (!lt) {
-				gconf_log (GCL_ERR, "(insert_or_update_value) List is of invalid type.");
+				gconf_log (GCL_ERR, "(insert_or_replace_value) List is of invalid type.");
 				rv = FALSE;
 				break;
 			}
@@ -503,7 +508,7 @@ insert_or_update_value (SqliteSource *ss
 			break;
 		case GCONF_VALUE_INVALID:
 		default:
-			gconf_log (GCL_ERR, "(insert_or_update_value) Attempt to insert item with invalid type.");
+			gconf_log (GCL_ERR, "(insert_or_replace_value) Attempt to insert item with invalid type.");
 			rv = FALSE;
 			break;
 	}
@@ -516,7 +521,7 @@ insert_or_update_value (SqliteSource *ss

 	/* 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);
+		gconf_log (GCL_ERR, "(insert_or_replace_value) SQL error: %s", err_mesg);
 		sqlite3_free (err_mesg);
 		rv = FALSE;
 	}
@@ -568,14 +573,14 @@ insert_list_for_key (SqliteSource *ss, c

 	list_type = gconf_value_get_list_type (value);
 	/* overly paranoid perhaps? */
-	g_return_val_if_fail (get_type_for_column (list_type) != NULL, FALSE);
+	g_return_val_if_fail (get_scalar_type_for_column (list_type) != NULL, FALSE);

 	switch (list_type) {
 		case GCONF_VALUE_STRING: list_sql_func = list_sql_string; break;
 		case GCONF_VALUE_INT: list_sql_func = list_sql_int; break;
 		case GCONF_VALUE_FLOAT: list_sql_func = list_sql_float; break;
 		case GCONF_VALUE_BOOL: list_sql_func = list_sql_bool; break;
-		default: list_sql_func= NULL;
+		default: list_sql_func = NULL;
 	}
 	g_return_val_if_fail (list_sql_func != NULL, FALSE);

@@ -601,12 +606,45 @@ insert_list_for_key (SqliteSource *ss, c
 	return rv;
 }

+#define BASIC_PAIR_INSERT	"INSERT INTO pairs (key_id, car_value_type, car_value, cdr_value_type, cdr_value) "
+
+static inline const char *
+get_sqlite3_mprintf_format (GConfValueType v)
+{
+	if (v == GCONF_VALUE_STRING) {
+		return "'%q'";
+	} else if (v == GCONF_VALUE_INT) {
+		return "%d";
+	} else if (v == GCONF_VALUE_FLOAT) {
+		return "%f";
+	} else if (v == GCONF_VALUE_BOOL) {
+		return "%d";
+	} else {
+		return NULL;
+	}
+}
+
 static gboolean
 insert_pair_for_key (SqliteSource *ss, const GConfValue *value, long long int key)
 {
+	GConfValue *car, *cdr;
+	char *query, *format_string;
+
 	g_return_val_if_fail (ss != NULL, FALSE);
 	g_return_val_if_fail (value != NULL, FALSE);

+	car = gconf_value_get_car (value);
+	cdr = gconf_value_get_cdr (value);
+
+	/* overly paranoid perhaps? */
+	g_return_val_if_fail (get_scalar_type_for_column (car->type) != NULL, FALSE);
+	g_return_val_if_fail (get_scalar_type_for_column (cdr->type) != NULL, FALSE);
+
+	/* a bit evil, but not that much */
+	format_string = sqlite3_mprintf (BASIC_PAIR_INSERT "(%%d, %%s, %s, %%s, %s)", get_sqlite3_mprintf_format (car->type), get_sqlite3_mprintf_format (cdr->type));
+	query = NULL; /* heh, FIXME */
+	sqlite3_free (format_string);
+
 	return FALSE;
 }

@@ -674,7 +712,7 @@ set_value_in_directory (SqliteSource *ss
 		 * 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)) {
+		if (!insert_or_replace_value (ss, dir, name, value)) {
 			rv = FALSE;
 			break;
 		}
@@ -693,6 +731,10 @@ set_value_in_directory (SqliteSource *ss
 				break;
 			}
 		} else if (value->type == GCONF_VALUE_SCHEMA) {
+			/* this is an extra-magic type;
+			 * depending whether or not there is a default value we need to do
+			 * some tricky things
+			 */
 			long long int last_rowid;
 			last_rowid = sqlite3_last_insert_rowid (ss->db);
 			if (!insert_schema_for_key (ss, value, last_rowid)) {