tracker r2278 - in trunk: . src/libtracker-db src/trackerd tests/libtracker-db



Author: mottela
Date: Tue Sep 30 11:22:02 2008
New Revision: 2278
URL: http://svn.gnome.org/viewvc/tracker?rev=2278&view=rev

Log:
Added multivalued field support to query

Modified:
   trunk/ChangeLog
   trunk/src/libtracker-db/tracker-db-dbus.c
   trunk/src/libtracker-db/tracker-db-dbus.h
   trunk/src/trackerd/tracker-rdf-query.c
   trunk/src/trackerd/tracker-search.c
   trunk/tests/libtracker-db/tracker-db-dbus-test.c

Modified: trunk/src/libtracker-db/tracker-db-dbus.c
==============================================================================
--- trunk/src/libtracker-db/tracker-db-dbus.c	(original)
+++ trunk/src/libtracker-db/tracker-db-dbus.c	Tue Sep 30 11:22:02 2008
@@ -19,10 +19,160 @@
  * Boston, MA  02110-1301, USA.
  */
 
+#include <string.h>
+
 #include <libtracker-common/tracker-dbus.h>
 
 #include "tracker-db-dbus.h"
 
+typedef struct {
+	gint     key;
+	gpointer value;
+} OneRow;
+
+typedef struct {
+	gpointer value;
+} OneElem;
+
+static inline void
+row_add (GPtrArray *row, gchar *value)
+{
+	OneElem *elem = g_slice_new (OneElem);
+	GSList  *list = NULL;
+
+	list = g_slist_prepend (list, value);
+	elem->value = list;
+	g_ptr_array_add (row, elem);
+}
+
+static inline void
+row_insert (GPtrArray *row, gchar *value, guint index)
+{
+	OneElem *elem = g_ptr_array_index (row, index);
+	GSList  *list = elem->value;
+	GSList  *iter;
+
+	/* We check for duplicate values here so that
+	 * we can have several multivalued fields in
+	 * the same query.
+	 */
+
+	for (iter = list; iter; iter=iter->next) {
+		if (strcmp (iter->data, value) == 0) {
+			return;
+		}
+	}
+
+	list = g_slist_prepend (list, value);
+	elem->value = list;
+}
+
+static inline void
+row_destroy (GPtrArray *row)
+{
+	guint i;
+
+	for (i = 0; i < row->len; i++) {
+		OneElem *elem;
+		GSList *list;
+
+		elem = g_ptr_array_index (row, i);
+		list = elem->value;
+		g_slist_foreach (list,
+				 (GFunc) g_free,
+				 NULL);
+		g_slist_free (list);
+		g_slice_free (OneElem, elem);
+	}
+
+	g_ptr_array_free (row, TRUE);
+}
+
+static inline gpointer
+rows_lookup (GPtrArray *rows, gint key)
+{
+	guint	 i;
+	gpointer value = NULL;
+
+	for (i = 0; i < rows->len; i++) {
+		OneRow *row = g_ptr_array_index (rows, i);
+		if (row->key == key) {
+			value = row->value;
+			break;
+		}
+	}
+
+	return value;
+}
+
+static inline void
+rows_destroy (GPtrArray *rows)
+{
+	guint i;
+
+	for (i = 0; i < rows->len; i++) {
+		OneRow *row;
+		row = g_ptr_array_index (rows, i);
+		row_destroy (row->value);
+		g_slice_free (OneRow, row);
+	}
+
+	g_ptr_array_free (rows, TRUE);
+}
+
+static inline void
+rows_add (GPtrArray *rows, gint key, gpointer value)
+{
+	OneRow *row = g_slice_new (OneRow);
+
+	row->key = key;
+	row->value = value;
+
+	g_ptr_array_add (rows, row);
+}
+
+static inline void
+rows_migrate (GPtrArray *rows, GPtrArray *result)
+{
+	guint i,j;
+
+	/* Go thought the lists and join with | separator */
+	for (i = 0; i < rows->len; i++) {
+		OneRow      *row;
+		GPtrArray   *array;
+		gchar      **strv;
+
+		row   = g_ptr_array_index (rows, i);
+		array = row->value;
+
+		strv = g_new0 (gchar*, array->len + 1);
+
+		for (j = 0; j < array->len; j++) {
+			OneElem   *elem;
+			GSList    *list;
+			GSList    *iter;
+			GString   *string;
+
+			elem   = g_ptr_array_index (array, j);
+			list   = elem->value;
+			string = g_string_new((gchar *)list->data);
+
+			for (iter = list->next; iter; iter = iter->next) {
+				g_string_append_printf (string, "|%s", (gchar *)iter->data);
+			}
+
+			strv[j] = string->str;
+
+			g_string_free (string, FALSE);
+		}
+
+		strv[array->len] = NULL;
+
+		g_ptr_array_add (result, strv);
+	}
+}
+
+
 static gchar **
 dbus_query_result_to_strv (TrackerDBResultSet *result_set,
 			   gint		       column,
@@ -234,8 +384,8 @@
 	}
 
 	while (valid) {
-		GSList	*list = NULL;
-		gchar  **p;
+		GSList	              *list = NULL;
+		gchar                **p;
 
 		/* Append fields to the array */
 		for (i = 0; i < columns; i++) {
@@ -281,3 +431,91 @@
 	return ptr_array;
 }
 
+GPtrArray *
+tracker_dbus_query_result_multi_to_ptr_array (TrackerDBResultSet *result_set)
+{
+	GPtrArray  *result;
+	GPtrArray  *rows;
+	gboolean    valid = FALSE;
+	gint	    columns;
+
+	rows = g_ptr_array_new ();
+
+	if (result_set) {
+		valid = TRUE;
+
+		/* Make sure we rewind before iterating the result set */
+		tracker_db_result_set_rewind (result_set);
+
+		/* Find out how many columns to iterate */
+		columns = tracker_db_result_set_get_n_columns (result_set);
+	}
+
+	while (valid) {
+		gint		       key;		
+		GPtrArray             *row;
+
+		gint	               column;
+		gboolean	       add = FALSE;
+		GValue		       value_in = {0, };
+
+		/* Get the key and the matching row if exists */
+		_tracker_db_result_set_get_value (result_set, 0, &value_in);
+		key = g_value_get_int (&value_in);		
+		row = rows_lookup (rows, key);				
+		if (!row) {
+			row = g_ptr_array_new ();
+			add = TRUE;
+		}
+
+		/* Append fields or values to the array */
+		for (column = 1; column < columns; column++) {
+			GValue	   transform = { 0, };
+			GValue	   value = { 0, };
+			gchar     *str;
+
+			g_value_init (&transform, G_TYPE_STRING);
+
+			_tracker_db_result_set_get_value (result_set,
+							  column,
+							  &value);
+
+			if (g_value_transform (&value, &transform)) {
+				str = g_value_dup_string (&transform);
+				
+				if (!str) {
+					str = g_strdup ("");
+				} else if (!g_utf8_validate (str, -1, NULL)) {
+					g_warning ("Could not add string:'%s' to GStrv, invalid UTF-8", str);
+					g_free (str);
+					str = g_strdup ("");
+				}
+			} else {
+				str = g_strdup ("");				
+			}
+
+			if (add) {
+				row_add (row, str);
+			} else {				
+				row_insert (row, str, column-1);
+			}		       
+
+			g_value_unset (&value);
+			g_value_unset (&transform);
+		}
+
+
+		if (add) {
+			rows_add (rows, key, row);
+		}
+
+		valid = tracker_db_result_set_iter_next (result_set);
+	}
+
+	result = g_ptr_array_new();
+
+	rows_migrate (rows, result);
+	rows_destroy (rows);
+	
+	return result;
+}

Modified: trunk/src/libtracker-db/tracker-db-dbus.h
==============================================================================
--- trunk/src/libtracker-db/tracker-db-dbus.h	(original)
+++ trunk/src/libtracker-db/tracker-db-dbus.h	Tue Sep 30 11:22:02 2008
@@ -40,6 +40,8 @@
 						       gboolean rewind);
 GHashTable *tracker_dbus_query_result_to_hash_table (TrackerDBResultSet *result_set);
 GPtrArray * tracker_dbus_query_result_to_ptr_array  (TrackerDBResultSet *result_set);
+GPtrArray * tracker_dbus_query_result_multi_to_ptr_array  (TrackerDBResultSet *result_set);
+
 
 G_END_DECLS
 

Modified: trunk/src/trackerd/tracker-rdf-query.c
==============================================================================
--- trunk/src/trackerd/tracker-rdf-query.c	(original)
+++ trunk/src/trackerd/tracker-rdf-query.c	Tue Sep 30 11:22:02 2008
@@ -1116,11 +1116,11 @@
 		case 6:
 		case 7:
 		case 8:
-			g_string_append_printf (result, " Select DISTINCT (S.Path || '%s' || S.Name) as uri, GetServiceName(S.ServiceTypeID) as stype ", G_DIR_SEPARATOR_S);
+			g_string_append_printf (result, " Select DISTINCT S.ID, (S.Path || '%s' || S.Name) as uri, GetServiceName(S.ServiceTypeID) as stype ", G_DIR_SEPARATOR_S);
 			break;
 
 		default :
-			g_string_append_printf (result, " Select DISTINCT (S.Path || '%s' || S.Name) as uri, GetServiceName(S.ServiceTypeID) as stype ", G_DIR_SEPARATOR_S);
+			g_string_append_printf (result, " Select DISTINCT S.ID, (S.Path || '%s' || S.Name) as uri, GetServiceName(S.ServiceTypeID) as stype ", G_DIR_SEPARATOR_S);
 			break;
 	}
 

Modified: trunk/src/trackerd/tracker-search.c
==============================================================================
--- trunk/src/trackerd/tracker-search.c	(original)
+++ trunk/src/trackerd/tracker-search.c	Tue Sep 30 11:22:02 2008
@@ -1182,7 +1182,7 @@
 		g_free (query_translated);
 	}
 
-	values = tracker_dbus_query_result_to_ptr_array (result_set);
+	values = tracker_dbus_query_result_multi_to_ptr_array (result_set);
 
 	dbus_g_method_return (context, values);
 

Modified: trunk/tests/libtracker-db/tracker-db-dbus-test.c
==============================================================================
--- trunk/tests/libtracker-db/tracker-db-dbus-test.c	(original)
+++ trunk/tests/libtracker-db/tracker-db-dbus-test.c	Tue Sep 30 11:22:02 2008
@@ -55,6 +55,50 @@
 
 }
 
+static TrackerDBResultSet *
+get_mock_tracker_db_multi_result (gint results, gint columns, gboolean set_null) {
+
+	TrackerDBResultSet *mock;
+	gint i, j, multi;
+
+	mock = _tracker_db_result_set_new (columns+1);
+
+	for (i = 0; i < results; i++) {
+		
+		for (multi = 0; multi < 2 ; multi++) {
+
+			_tracker_db_result_set_append (mock);
+
+			{
+				GValue id_value = {0,};
+			
+				g_value_init (&id_value, G_TYPE_INT);
+				g_value_set_int (&id_value, i);
+				_tracker_db_result_set_set_value (mock, 0, &id_value);
+				
+				g_value_unset (&id_value);
+			}
+
+			for (j = 1; j < columns+1; j++) {
+				
+				GValue value = {0,};
+				gchar * text = g_strdup_printf ("value %d", j+multi*j%2);
+				
+				g_value_init (&value, G_TYPE_STRING);
+				g_value_set_string (&value, (set_null ? NULL : text));
+				_tracker_db_result_set_set_value (mock, j, &value);
+				
+				g_value_unset (&value);
+				g_free (text);
+			}
+		}
+	}
+
+	tracker_db_result_set_rewind (mock);
+
+	return mock;
+
+}
 
 
 static void
@@ -155,6 +199,59 @@
 	g_object_unref (result_set);
 }
 
+
+static void
+test_dbus_query_result_multi_to_ptr_array ()
+{
+	TrackerDBResultSet *result_set = NULL;
+	GPtrArray *result = NULL;
+
+	/* NULL */
+	result = tracker_dbus_query_result_multi_to_ptr_array (result_set);
+	g_assert_cmpint (result->len, ==, 0);
+	free_string_ptr_array (result);
+
+	/* 5 results, 1 column */
+	result_set = get_mock_tracker_db_multi_result (5, 1, FALSE);
+	result = tracker_dbus_query_result_multi_to_ptr_array (result_set);
+
+	g_assert_cmpint (result->len, ==, 5);
+	free_string_ptr_array (result);
+
+	g_object_unref (result_set);
+
+	/* 0 results, 1 columns */
+	result_set = get_mock_tracker_db_multi_result (0, 1, FALSE);
+	if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) {
+		result = tracker_dbus_query_result_multi_to_ptr_array (result_set);
+		free_string_ptr_array (result);
+	}
+	g_test_trap_assert_failed ();
+	/* Should raise g_critical (priv->array...); */
+
+	g_object_unref (result_set);
+
+	/*  1 result ... NULL */
+	result_set = get_mock_tracker_db_multi_result (1, 1, TRUE);
+	result = tracker_dbus_query_result_multi_to_ptr_array (result_set);
+	g_assert_cmpint (result->len, ==, 1);
+	free_string_ptr_array (result);
+
+	g_object_unref (result_set);
+
+
+	/* 5 results, 5 columns */
+	result_set = get_mock_tracker_db_multi_result (5, 5, FALSE);
+	result = tracker_dbus_query_result_multi_to_ptr_array (result_set);
+
+	g_assert_cmpint (result->len, ==, 5);
+	free_string_ptr_array (result);
+
+	g_object_unref (result_set);
+
+}
+
+
 gint
 main (gint argc, gchar **argv)
 {
@@ -170,7 +267,8 @@
 			 test_dbus_query_result_to_hash_table);
 	g_test_add_func ("/libtracker-db/tracker-db-dbus/query_result_to_ptr_array",
 			 test_dbus_query_result_to_ptr_array);
-
+	g_test_add_func ("/libtracker-db/tracker-db-dbus/query_result_multi_to_ptr_array",
+			 test_dbus_query_result_multi_to_ptr_array);
 
 	result = g_test_run ();
 



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