tracker r2985 - in trunk: . src/libtracker-data src/libtracker-db



Author: mottela
Date: Fri Feb 27 02:18:00 2009
New Revision: 2985
URL: http://svn.gnome.org/viewvc/tracker?rev=2985&view=rev

Log:
Abstraction layer to sqlite aggregate function-creation, new version of GROUP_CONCAT and some minor fixes

Modified:
   trunk/ChangeLog
   trunk/src/libtracker-data/tracker-data-backup.c
   trunk/src/libtracker-data/tracker-data-search.c
   trunk/src/libtracker-db/tracker-db-interface-sqlite.c
   trunk/src/libtracker-db/tracker-db-interface-sqlite.h
   trunk/src/libtracker-db/tracker-db-manager.c

Modified: trunk/src/libtracker-data/tracker-data-backup.c
==============================================================================
--- trunk/src/libtracker-data/tracker-data-backup.c	(original)
+++ trunk/src/libtracker-data/tracker-data-backup.c	Fri Feb 27 02:18:00 2009
@@ -98,10 +98,10 @@
 		 (gchar *)triple->predicate,
 		 (gchar *)triple->object);
 
-	(data.func) ((const gchar *) triple->subject,
-		     (const gchar *) triple->predicate,
-		     (const gchar *) triple->object,
-		     data->user_data);
+	(data->func) ((const gchar *) triple->subject,
+		      (const gchar *) triple->predicate,
+		      (const gchar *) triple->object,
+		      data->user_data);
 }
 
 #endif /* HAVE_RAPTOR */
@@ -160,10 +160,10 @@
 	if (!g_file_test (turtle_filename, G_FILE_TEST_EXISTS)) {
 		g_set_error (error, 0, 0,
 			     "Turtle file does not exist");
-		return;
+		return FALSE;
 	}
 
-	tracker_turtle_process (backup_file,
+	tracker_turtle_process (turtle_filename,
 				"/",
 				(TurtleTripleCallback) restore_backup_triple,
 				&data);

Modified: trunk/src/libtracker-data/tracker-data-search.c
==============================================================================
--- trunk/src/libtracker-data/tracker-data-search.c	(original)
+++ trunk/src/libtracker-data/tracker-data-search.c	Fri Feb 27 02:18:00 2009
@@ -1315,7 +1315,7 @@
 			g_string_free (sql_group, TRUE);
 
 			g_set_error (error, TRACKER_DBUS_ERROR, 0,
-				     "Cannot sum '%s': this metadata type is not text",
+				     "Cannot concatenate '%s': this metadata type is not text",
 				     sum_field);
 			return NULL;
 		}

Modified: trunk/src/libtracker-db/tracker-db-interface-sqlite.c
==============================================================================
--- trunk/src/libtracker-db/tracker-db-interface-sqlite.c	(original)
+++ trunk/src/libtracker-db/tracker-db-interface-sqlite.c	Fri Feb 27 02:18:00 2009
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /* Tracker - Sqlite implementation
  * Copyright (C) 2008 Nokia
  *
@@ -24,6 +25,7 @@
 
 typedef struct TrackerDBInterfaceSqlitePrivate TrackerDBInterfaceSqlitePrivate;
 typedef struct SqliteFunctionData SqliteFunctionData;
+typedef struct SqliteAggregateData SqliteAggregateData;
 
 struct TrackerDBInterfaceSqlitePrivate {
 	gchar *filename;
@@ -33,6 +35,7 @@
 	GHashTable *procedures;
 
 	GSList *function_data;
+	GSList *aggregate_data;
 
 	guint in_transaction : 1;
 	guint ro : 1;
@@ -43,6 +46,14 @@
 	TrackerDBFunc func;
 };
 
+struct SqliteAggregateData {
+	TrackerDBInterface *interface;
+	guint               context_size;
+	TrackerDBFuncStep   step;
+	TrackerDBFuncFinal  final;
+	
+};
+
 static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
 
 enum {
@@ -59,7 +70,7 @@
 void 
 tracker_db_interface_sqlite_enable_shared_cache (void) 
 {
-	sqlite3_enable_shared_cache (1);
+  sqlite3_enable_shared_cache (1);
 }
 
 static GObject *
@@ -162,6 +173,9 @@
 	g_slist_foreach (priv->function_data, (GFunc) g_free, NULL);
 	g_slist_free (priv->function_data);
 
+	g_slist_foreach (priv->aggregate_data, (GFunc) g_free, NULL);
+	g_slist_free (priv->aggregate_data);
+
 	sqlite3_close (priv->db);
 	g_message ("Closed sqlite3 database:'%s'", priv->filename);
 
@@ -347,6 +361,114 @@
 }
 
 static void
+internal_sqlite3_aggregate_step (sqlite3_context *context,
+				 int		    argc,
+				 sqlite3_value   *argv[])
+{
+	SqliteAggregateData *data;
+	void *aggregate_context;
+	GValue *values;
+	GByteArray *blob_array;
+	gint i;
+
+	data = (SqliteAggregateData *) sqlite3_user_data (context);
+	values = g_new0 (GValue, argc);
+
+	/* Transform the arguments */
+	for (i = 0; i < argc; i++) {
+		switch (sqlite3_value_type (argv[i])) {
+		case SQLITE_TEXT:
+			g_value_init (&values[i], G_TYPE_STRING);
+			g_value_set_string (&values[i], (gchar *) sqlite3_value_text (argv[i]));
+			break;
+		case SQLITE_INTEGER:
+			g_value_init (&values[i], G_TYPE_INT);
+			g_value_set_int (&values[i], sqlite3_value_int (argv[i]));
+			break;
+		case SQLITE_FLOAT:
+			g_value_init (&values[i], G_TYPE_DOUBLE);
+			g_value_set_double (&values[i], sqlite3_value_double (argv[i]));
+			break;
+		case SQLITE_BLOB: {
+			gconstpointer blob;
+			gint size;
+
+			blob = sqlite3_value_blob (argv[i]);
+			size = sqlite3_value_bytes (argv[i]);
+
+			blob_array = g_byte_array_sized_new (size);
+			g_byte_array_append (blob_array, blob, size);
+
+			g_value_init (&values[i], TRACKER_TYPE_DB_BLOB);
+			g_value_take_boxed (&values[i], blob_array);
+
+			break;
+		}
+		default:
+			g_critical ("Unknown sqlite3 database value type:%d",
+				    sqlite3_value_type (argv[i]));
+		}
+	}
+
+	aggregate_context = sqlite3_aggregate_context(context, data->context_size);
+
+	/* Call the function */
+	data->step (data->interface, aggregate_context, argc, values);
+
+	/* Now free all this mess */
+	for (i = 0; i < argc; i++) {
+		g_value_unset (&values[i]);
+	}
+
+	g_free (values);
+}
+
+static void
+internal_sqlite3_aggregate_final (sqlite3_context *context)
+{
+	SqliteAggregateData *data;
+	void *aggregate_context;
+	GValue result;
+	GByteArray *blob_array;
+
+	data = (SqliteAggregateData *) sqlite3_user_data (context);
+
+	aggregate_context = sqlite3_aggregate_context(context, 0);	
+
+	/* Call the function */
+	result = data->final (data->interface, aggregate_context);
+
+	/* And return something appropriate to the context */
+	if (G_VALUE_HOLDS_INT (&result)) {
+		sqlite3_result_int (context, g_value_get_int (&result));
+	} else if (G_VALUE_HOLDS_DOUBLE (&result)) {
+		sqlite3_result_double (context, g_value_get_double (&result));
+	} else if (G_VALUE_HOLDS_STRING (&result)) {
+		sqlite3_result_text (context,
+				     g_value_dup_string (&result),
+				     -1, g_free);
+	} else if (G_VALUE_HOLDS (&result, TRACKER_TYPE_DB_BLOB)) {
+		blob_array = g_value_get_boxed (&result);
+		sqlite3_result_blob (context,
+				     g_memdup (blob_array->data, blob_array->len),
+				     blob_array->len,
+				     g_free);
+	} else if (G_VALUE_HOLDS (&result, G_TYPE_INVALID)) {
+		sqlite3_result_null (context);
+	} else {
+		g_critical ("Sqlite3 returned type not managed:'%s'",
+			    G_VALUE_TYPE_NAME (&result));
+		sqlite3_result_null (context);
+	}
+
+	/* Now free all this mess */
+
+	if (! G_VALUE_HOLDS (&result, G_TYPE_INVALID)) {
+		g_value_unset (&result);
+	}
+}
+
+static void
 tracker_db_interface_sqlite_set_procedure_table (TrackerDBInterface *db_interface,
 						 GHashTable	    *procedure_table)
 {
@@ -642,6 +764,32 @@
 	sqlite3_create_function (priv->db, name, n_args, SQLITE_ANY, data, &internal_sqlite3_function, NULL, NULL);
 }
 
+void
+tracker_db_interface_sqlite_create_aggregate (TrackerDBInterface *interface,
+					      const gchar	 *name,
+					      TrackerDBFuncStep   step,
+					      gint		  n_args,
+					      TrackerDBFuncFinal  final,
+					      guint               context_size)
+{
+	SqliteAggregateData *data;
+	TrackerDBInterfaceSqlitePrivate *priv;
+
+	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (interface);
+
+	data = g_new0 (SqliteAggregateData, 1);
+	data->interface = interface;
+	data->context_size = context_size;
+	data->step = step;
+	data->final = final;
+
+	priv->aggregate_data = g_slist_prepend (priv->aggregate_data, data);
+
+	sqlite3_create_function (priv->db, name, n_args, SQLITE_ANY, data, NULL, 
+				 &internal_sqlite3_aggregate_step, 
+				 &internal_sqlite3_aggregate_final);
+}
+
 gboolean
 tracker_db_interface_sqlite_set_collation_function (TrackerDBInterfaceSqlite *interface,
 						    const gchar		     *name,

Modified: trunk/src/libtracker-db/tracker-db-interface-sqlite.h
==============================================================================
--- trunk/src/libtracker-db/tracker-db-interface-sqlite.h	(original)
+++ trunk/src/libtracker-db/tracker-db-interface-sqlite.h	Fri Feb 27 02:18:00 2009
@@ -42,6 +42,14 @@
 				  gint		      argc,
 				  GValue	      argv[]);
 
+typedef void (* TrackerDBFuncStep) (TrackerDBInterface *interface,
+				    void               *aggregate_context,
+				    gint		  argc,
+				    GValue	          argv[]);
+
+typedef GValue (* TrackerDBFuncFinal) (TrackerDBInterface *interface,
+				       void               *aggregate_context);
+
 struct TrackerDBInterfaceSqlite {
 	GObject parent_instance;
 };
@@ -59,6 +67,12 @@
 									 const gchar		  *name,
 									 TrackerDBFunc		   func,
 									 gint			   n_args);
+void                 tracker_db_interface_sqlite_create_aggregate       (TrackerDBInterface       *interface,
+									 const gchar	          *name,
+									 TrackerDBFuncStep         step,
+									 gint		           n_args,
+									 TrackerDBFuncFinal        final,
+									 guint                     context_size);
 gboolean	     tracker_db_interface_sqlite_set_collation_function (TrackerDBInterfaceSqlite *interface,
 									 const gchar		  *name,
 									 TrackerDBCollationFunc    func);

Modified: trunk/src/libtracker-db/tracker-db-manager.c
==============================================================================
--- trunk/src/libtracker-db/tracker-db-manager.c	(original)
+++ trunk/src/libtracker-db/tracker-db-manager.c	Fri Feb 27 02:18:00 2009
@@ -79,6 +79,10 @@
 	guint64             mtime;
 } TrackerDBDefinition;
 
+typedef struct {
+	GString *string;     /* The string we are accumulating */
+} AggregateData;
+
 static TrackerDBDefinition dbs[] = {
 	{ TRACKER_DB_UNKNOWN,
 	  TRACKER_DB_LOCATION_USER_DATA_DIR,
@@ -1325,6 +1329,41 @@
 	return result;
 }
 
+static void
+function_group_concat_step (TrackerDBInterface *interface,
+			    void               *aggregate_context,
+			    gint		argc,
+			    GValue		values[])
+{
+	AggregateData *p = (AggregateData *)aggregate_context;
+	
+	g_assert (argc==1);
+
+	if (!p->string) {
+		p->string = g_string_new ("");
+	} else {
+		p->string = g_string_append (p->string, "|");
+	}
+
+	p->string = g_string_append (p->string, g_value_get_string (&values[0]));
+}
+
+static GValue
+function_group_concat_final (TrackerDBInterface *interface,
+			     void               *aggregate_context)
+{
+	GValue result = { 0, };
+	AggregateData *p = (AggregateData *)aggregate_context;
+
+	g_value_init (&result, G_TYPE_STRING);
+	g_value_set_string (&result, p->string->str);
+
+	g_string_free (p->string, TRUE);
+
+	return result;
+}
+
+
 static GValue
 function_get_service_name (TrackerDBInterface *interface,
 			   gint		       argc,
@@ -1697,6 +1736,14 @@
 							     "replace",
 							     function_replace,
 							     3);
+		
+		tracker_db_interface_sqlite_create_aggregate (iface,
+							      "group_concat",
+							      function_group_concat_step,
+							      1,
+							      function_group_concat_final,
+							      sizeof(AggregateData));
+
 		tracker_db_interface_sqlite_create_function (iface,
 							     "CollateKey",
 							     function_collate_key,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]