[tracker] Add fn:string-join
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker] Add fn:string-join
- Date: Thu, 18 Feb 2010 12:30:39 +0000 (UTC)
commit 855b380b19fd86e708f9f2000ea5c3c5453a1ea8
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]