[tracker/string-functions: 1/2] Add fn:string-join



commit 20b37a1df801feb766bfbbab985cf7ffd01fd274
Author: Mikael Ottela <mikael ottela ixonos com>
Date:   Tue Feb 16 23:29:49 2010 +0200

    Add fn:string-join
    
    Add the implementation for the xpath function string-join and
    unit-tests. Support NULL values in functions.

 src/libtracker-data/tracker-sparql-query.vala      |   20 ++++++++
 src/libtracker-db/tracker-db-interface-sqlite.c    |    7 ++-
 src/libtracker-db/tracker-db-manager.c             |   51 ++++++++++++++++++--
 tests/libtracker-data/functions/Makefile.am        |    4 +-
 .../functions/functions-xpath-3.out                |    6 ++
 .../libtracker-data/functions/functions-xpath-3.rq |    8 +++
 tests/libtracker-data/tracker-sparql-test.c        |    4 +-
 7 files changed, 93 insertions(+), 7 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index 064ba66..0b1f662 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -1427,6 +1427,26 @@ public class Tracker.SparqlQuery : Object {
 			sql.append (")");
 
 			return PropertyType.BOOLEAN;
+		} else if (uri == FN_NS + "string-join") {
+			sql.append ("SparqlStringJoin(");
+			expect (SparqlTokenType.OPEN_PARENS);
+
+			translate_expression_as_string (sql);
+			sql.append (", ");
+			expect (SparqlTokenType.COMMA);
+			translate_expression_as_string (sql);
+			while (accept (SparqlTokenType.COMMA)) {
+			      sql.append (", ");
+			      translate_expression_as_string (sql);
+			}
+
+			expect (SparqlTokenType.CLOSE_PARENS);
+			sql.append (",");
+			expect (SparqlTokenType.COMMA);
+			translate_expression (sql);
+			sql.append (")");
+
+			return PropertyType.STRING;
 		} else if (uri == FTS_NS + "rank") {
 			bool is_var;
 			string v = parse_var_or_term (null, out is_var);
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index be4cb2b..ca85f77 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.c
+++ b/src/libtracker-db/tracker-db-interface-sqlite.c
@@ -432,6 +432,9 @@ internal_sqlite3_function (sqlite3_context *context,
 
 			break;
 		}
+		case SQLITE_NULL:
+			/* Unset GValues as NULLs */
+			break;
 		default:
 			g_critical ("Unknown sqlite3 database value type:%d",
 			            sqlite3_value_type (argv[i]));
@@ -466,7 +469,9 @@ internal_sqlite3_function (sqlite3_context *context,
 
 	/* Now free all this mess */
 	for (i = 0; i < argc; i++) {
-		g_value_unset (&values[i]);
+		if (G_IS_VALUE (&values[i])) {
+			g_value_unset (&values[i]);
+		}
 	}
 
 	if (! G_VALUE_HOLDS (&result, G_TYPE_INVALID)) {
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index 3e95913..a1bae21 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -308,6 +308,45 @@ tracker_db_manager_get_flags (void)
 	return old_flags;
 }
 
+static GValue
+function_sparql_string_join (TrackerDBInterface *interface,
+			     gint                argc,
+			     GValue              values[])
+{
+	GValue result = { 0, };
+	GString *str = NULL;
+	const gchar *separator;
+	gint i;
+
+	/* fn:string-join (str1, str2, ..., separator) */
+
+	if (!G_VALUE_HOLDS_STRING (&values[argc-1])) {
+		/* Fail */
+		return result;
+	}
+
+	separator = g_value_get_string (&values[argc-1]);
+
+	for (i = 0;i < argc-1; i++) {
+		if (G_VALUE_HOLDS_STRING (&values[i])) {
+			if (!str) {
+				str = g_string_new (g_value_get_string (&values[i]));
+			} else {
+				g_string_append_printf (str, "%s%s",
+							separator,
+							g_value_get_string (&values[i]));
+			}
+		}
+	}
+
+	g_value_init (&result, G_TYPE_STRING);
+	g_value_set_string (&result, str->str);
+
+	g_string_free (str, TRUE);
+
+	return result;
+}
+
 /* Create a title-type string from the filename for replacing missing ones */
 static GValue
 function_sparql_string_from_filename (TrackerDBInterface *interface,
@@ -416,9 +455,9 @@ function_sparql_haversine_distance (TrackerDBInterface *interface,
 
 	R = 6371000;
 	dLat = (lat2-lat1);
-	dLon = (lon2-lon1); 
-	a = sin(dLat/2) * sin(dLat/2) + cos(lat1) * cos(lat2) *  sin(dLon/2) * sin(dLon/2); 
-	c = 2 * atan2(sqrt(a), sqrt(1-a)); 
+	dLon = (lon2-lon1);
+	a = sin(dLat/2) * sin(dLat/2) + cos(lat1) * cos(lat2) *  sin(dLon/2) * sin(dLon/2);
+	c = 2 * atan2(sqrt(a), sqrt(1-a));
 	d = R * c;
 
 	g_value_init (&result, G_TYPE_DOUBLE);
@@ -817,6 +856,10 @@ db_set_params (TrackerDBInterface *iface,
 		                                             function_sparql_regex,
 		                                             3);
 		tracker_db_interface_sqlite_create_function (iface,
+		                                             "SparqlStringJoin",
+		                                             function_sparql_string_join,
+		                                             -1);
+		tracker_db_interface_sqlite_create_function (iface,
 		                                             "SparqlStringFromFilename",
 		                                             function_sparql_string_from_filename,
 		                                             1);
@@ -1480,7 +1523,7 @@ tracker_db_manager_init (TrackerDBManagerFlags  flags,
 		}
 	}
 
-	in_use_file = g_open (in_use_filename, 
+	in_use_file = g_open (in_use_filename,
 	                      O_WRONLY | O_APPEND | O_CREAT | O_SYNC,
 	                      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 	fsync (in_use_file);
diff --git a/tests/libtracker-data/functions/Makefile.am b/tests/libtracker-data/functions/Makefile.am
index 89c86ac..377d20e 100644
--- a/tests/libtracker-data/functions/Makefile.am
+++ b/tests/libtracker-data/functions/Makefile.am
@@ -18,4 +18,6 @@ EXTRA_DIST = 				\
 	functions-xpath-1.out		\
 	functions-xpath-1.rq		\
 	functions-xpath-2.out		\
-	functions-xpath-2.rq
+	functions-xpath-2.rq		\
+	functions-xpath-3.out		\
+	functions-xpath-3.rq
diff --git a/tests/libtracker-data/functions/functions-xpath-3.out b/tests/libtracker-data/functions/functions-xpath-3.out
new file mode 100644
index 0000000..76fb988
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-xpath-3.out
@@ -0,0 +1,6 @@
+"other"
+"fourth|testing"
+"fifth|purposes"
+"first|Test|optional"
+"second|Text"
+"third|for|optional for third"
diff --git a/tests/libtracker-data/functions/functions-xpath-3.rq b/tests/libtracker-data/functions/functions-xpath-3.rq
new file mode 100644
index 0000000..ea5155c
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-xpath-3.rq
@@ -0,0 +1,8 @@
+PREFIX ex: <http://example/>
+PREFIX ns: <http://www.w3.org/2005/xpath-functions#>
+
+SELECT fn:string-join((?s,?t,?u),"|")
+{ OPTIONAL { ?_x ex:s ?s . }
+  OPTIONAL { ?_x ex:t ?t . }
+  OPTIONAL { ?_x ex:u ?u . }
+}
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index 9aa6fc1..659c19d 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -69,9 +69,11 @@ const TestInfo tests[] = {
 	{ "functions/functions-tracker-loc-1", "functions/data-3", FALSE },
 	{ "functions/functions-xpath-1", "functions/data-1", FALSE },
 	{ "functions/functions-xpath-2", "functions/data-1", FALSE },
+	{ "functions/functions-xpath-3", "functions/data-1", FALSE },
 	{ "graph/graph-1", "graph/data-1", FALSE },
 	{ "graph/graph-2", "graph/data-2", FALSE },
 	{ "graph/graph-3", "graph/data-3", FALSE },
+	{ "functions/functions-xpath-3", "functions/data-1", FALSE },
 	{ "optional/q-opt-complex-1", "optional/complex-data-1", FALSE },
 	{ "regex/regex-query-001", "regex/regex-data-01", FALSE },
 	{ "regex/regex-query-002", "regex/regex-data-01", FALSE },
@@ -79,7 +81,7 @@ const TestInfo tests[] = {
 	{ "sort/query-sort-2", "sort/data-sort-1", FALSE },
 	{ "sort/query-sort-3", "sort/data-sort-3", FALSE },
 	{ "sort/query-sort-4", "sort/data-sort-4", FALSE },
-	{ "sort/query-sort-5", "sort/data-sort-4", FALSE }, 
+	{ "sort/query-sort-5", "sort/data-sort-4", FALSE },
 	{ "subqueries/subqueries-1", "subqueries/data-1", FALSE },
 	/* Bracket error after WHERE */
 	{ "error/query-error-1", "error/query-error-1", TRUE },



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