[tracker/collation: 7/9] sparql: New 'COLLATE' keyword supported in 'ORDER BY'



commit 4327a630aeffc17fc68e57fc0d913e416dc62df1
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Tue Aug 17 13:47:20 2010 +0200

    sparql: New 'COLLATE' keyword supported in 'ORDER BY'

 src/libtracker-data/tracker-collation.c            |   48 +++++++++++++++++--
 src/libtracker-data/tracker-sparql-expression.vala |    7 ++-
 src/libtracker-data/tracker-sparql-pattern.vala    |   12 ++++-
 src/libtracker-data/tracker-sparql-scanner.vala    |    6 +++
 4 files changed, 62 insertions(+), 11 deletions(-)
---
diff --git a/src/libtracker-data/tracker-collation.c b/src/libtracker-data/tracker-collation.c
index e12007e..af04315 100644
--- a/src/libtracker-data/tracker-collation.c
+++ b/src/libtracker-data/tracker-collation.c
@@ -19,14 +19,15 @@
 
 #include "config.h"
 #include <glib.h>
+#include <string.h>
 
 #include "tracker-collation.h"
 
 /* If defined, will dump some additional logs as prints,
  *  instead of debugs*/
-#define G_INSTEADOF_LOG 1
+#define PRINT_INSTEADOF_LOG 0
 
-#ifdef G_INSTEADOF_LOG
+#ifdef PRINT_INSTEADOF_LOG
 #undef g_debug
 #define g_debug(message, ...) \
 	g_print ("(debug) %s:%d: " message "\n", \
@@ -39,7 +40,7 @@
 #define g_critical(message, ...) \
 	g_print ("(critical) %s:%d: " message "\n", \
 	         __FILE__, __LINE__, ##__VA_ARGS__)
-#endif /* G_INSTEADOF_LOG */
+#endif /* PRINT_INSTEADOF_LOG */
 
 #ifdef HAVE_LIBUNISTRING
 /* libunistring versions prior to 9.1.2 need this hack */
@@ -50,6 +51,9 @@
 #include <unicode/ucol.h>
 #endif
 
+/* If string lenth less than this value, allocating from the stack */
+#define MAX_STACK_STR_SIZE 512
+
 #ifdef HAVE_LIBUNISTRING /* ---- GNU libunistring based collation ---- */
 
 gpointer
@@ -73,7 +77,24 @@ tracker_collation_utf8 (gpointer      collator,
                         gint          len2,
                         gconstpointer str2)
 {
-	return u8_strcoll (str1, str2);
+	gint result;
+	gchar *aux1;
+	gchar *aux2;
+
+	/* Note: str1 and str2 are NOT NUL-terminated */
+	aux1 = (len1 < MAX_STACK_STR_SIZE) ? g_alloca (len1+1) : g_malloc (len1+1);
+	aux2 = (len2 < MAX_STACK_STR_SIZE) ? g_alloca (len2+1) : g_malloc (len2+1);
+
+	memcpy (aux1, str1, len1); aux1[len1] = '\0';
+	memcpy (aux2, str2, len2); aux2[len2] = '\0';
+
+	result = u8_strcoll (aux1, aux2);
+
+	if (len1 >= MAX_STACK_STR_SIZE)
+		g_free (aux1);
+	if (len2 >= MAX_STACK_STR_SIZE)
+		g_free (aux2);
+	return result;
 }
 
 #elif HAVE_LIBICU /* ---- ICU based collation (UTF-16) ----*/
@@ -164,7 +185,24 @@ tracker_collation_utf8 (gpointer      collator,
                         gint          len2,
                         gconstpointer str2)
 {
-	return g_utf8_collate (str1, str2);
+	gint result;
+	gchar *aux1;
+	gchar *aux2;
+
+	/* Note: str1 and str2 are NOT NUL-terminated */
+	aux1 = (len1 < MAX_STACK_STR_SIZE) ? g_alloca (len1+1) : g_malloc (len1+1);
+	aux2 = (len2 < MAX_STACK_STR_SIZE) ? g_alloca (len2+1) : g_malloc (len2+1);
+
+	memcpy (aux1, str1, len1); aux1[len1] = '\0';
+	memcpy (aux2, str2, len2); aux2[len2] = '\0';
+
+	result = g_utf8_collate (aux1, aux2);
+
+	if (len1 >= MAX_STACK_STR_SIZE)
+		g_free (aux1);
+	if (len2 >= MAX_STACK_STR_SIZE)
+		g_free (aux2);
+	return result;
 }
 
 #endif
diff --git a/src/libtracker-data/tracker-sparql-expression.vala b/src/libtracker-data/tracker-sparql-expression.vala
index 064217b..d8760b1 100644
--- a/src/libtracker-data/tracker-sparql-expression.vala
+++ b/src/libtracker-data/tracker-sparql-expression.vala
@@ -180,15 +180,16 @@ class Tracker.Sparql.Expression : Object {
 		}
 	}
 
-	internal void translate_order_condition (StringBuilder sql) throws Sparql.Error {
+	internal string translate_order_condition (StringBuilder sql) throws Sparql.Error {
 		if (accept (SparqlTokenType.ASC)) {
 			translate_expression_as_order_condition (sql);
-			sql.append (" ASC");
+			return (" ASC");
 		} else if (accept (SparqlTokenType.DESC)) {
 			translate_expression_as_order_condition (sql);
-			sql.append (" DESC");
+			return (" DESC");
 		} else {
 			translate_expression_as_order_condition (sql);
+                        return ("");
 		}
 	}
 
diff --git a/src/libtracker-data/tracker-sparql-pattern.vala b/src/libtracker-data/tracker-sparql-pattern.vala
index e030fa3..477eae2 100644
--- a/src/libtracker-data/tracker-sparql-pattern.vala
+++ b/src/libtracker-data/tracker-sparql-pattern.vala
@@ -358,10 +358,16 @@ class Tracker.Sparql.Pattern : Object {
 				if (first_order) {
 					first_order = false;
 				} else {
-					sql.append (" COLLATE TRACKER, ");
+					sql.append (", ");
+				}
+				string order = expression.translate_order_condition (sql);
+
+				if (accept (SparqlTokenType.COLLATE)) {
+					sql.append (" COLLATE TRACKER ");
 				}
-				expression.translate_order_condition (sql);
-			} while (current () != SparqlTokenType.LIMIT && current () != SparqlTokenType.OFFSET && current () != SparqlTokenType.CLOSE_BRACE && current () != SparqlTokenType.CLOSE_PARENS && current () != SparqlTokenType.EOF);
+
+				sql.append (order);
+			} while (current () != SparqlTokenType.LIMIT && current () != SparqlTokenType.OFFSET && current () != SparqlTokenType.COLLATE && current () != SparqlTokenType.CLOSE_BRACE && current () != SparqlTokenType.CLOSE_PARENS && current () != SparqlTokenType.EOF);
 		}
 
 		int limit = -1;
diff --git a/src/libtracker-data/tracker-sparql-scanner.vala b/src/libtracker-data/tracker-sparql-scanner.vala
index d216ac0..6bf020b 100644
--- a/src/libtracker-data/tracker-sparql-scanner.vala
+++ b/src/libtracker-data/tracker-sparql-scanner.vala
@@ -281,6 +281,10 @@ public class Tracker.SparqlScanner : Object {
 			break;
 		case 7:
 			switch (begin[0]) {
+			case 'c':
+			case 'C':
+				if (matches (begin, "COLLATE")) return SparqlTokenType.COLLATE;
+				break;
 			case 'R':
 			case 'r':
 				if (matches (begin, "REDUCED")) return SparqlTokenType.REDUCED;
@@ -826,6 +830,7 @@ public enum Tracker.SparqlTokenType {
 	CLOSE_BRACE,
 	CLOSE_BRACKET,
 	CLOSE_PARENS,
+	COLLATE,
 	COLON,
 	COMMA,
 	CONSTRUCT,
@@ -919,6 +924,7 @@ public enum Tracker.SparqlTokenType {
 		case CLOSE_BRACE: return "`}'";
 		case CLOSE_BRACKET: return "`]'";
 		case CLOSE_PARENS: return "`)'";
+		case COLLATE: return "`COLLATE'";
 		case COLON: return "`:'";
 		case COMMA: return "`,'";
 		case CONSTRUCT: return "`CONSTRUCT'";



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