diff options
-rw-r--r-- | src/libtracker-data/tracker-db-interface-sqlite.c | 125 | ||||
-rw-r--r-- | src/libtracker-data/tracker-sparql-expression.vala | 8 |
2 files changed, 132 insertions, 1 deletions
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c b/src/libtracker-data/tracker-db-interface-sqlite.c index 298a3c5b8..c435d4fb5 100644 --- a/src/libtracker-data/tracker-db-interface-sqlite.c +++ b/src/libtracker-data/tracker-db-interface-sqlite.c @@ -34,6 +34,18 @@ #include <libtracker-fts/tracker-fts.h> #endif +#ifdef HAVE_LIBUNISTRING +/* libunistring versions prior to 9.1.2 need this hack */ +#define _UNUSED_PARAMETER_ +#include <unistr.h> +#include <unicase.h> +#elif HAVE_LIBICU +#include <unicode/utypes.h> +#include <unicode/uregex.h> +#include <unicode/ustring.h> +#include <unicode/ucol.h> +#endif + #include "tracker-collation.h" #include "tracker-db-interface-sqlite.h" @@ -521,6 +533,115 @@ function_sparql_regex (sqlite3_context *context, sqlite3_result_int (context, ret); } +#ifdef HAVE_LIBUNISTRING + +static void +function_sparql_lower_case (sqlite3_context *context, + int argc, + sqlite3_value *argv[]) +{ + const uint16_t *zInput; + uint16_t *zOutput; + size_t written = 0; + int nInput; + int nOutput; + + g_assert (argc == 1); + + zInput = sqlite3_value_text16 (argv[0]); + + if (!zInput) { + return; + } + + nInput = sqlite3_value_bytes16 (argv[0]); + + zOutput = u16_tolower (zInput, nInput/2, NULL, NULL, NULL, &written); + + sqlite3_result_text16 (context, zOutput, -1, free); +} + +#elif HAVE_LIBICU + +static void +function_sparql_lower_case (sqlite3_context *context, + int argc, + sqlite3_value *argv[]) +{ + const UChar *zInput; + UChar *zOutput; + int nInput; + int nOutput; + UErrorCode status = U_ZERO_ERROR; + + g_assert (argc == 1); + + zInput = sqlite3_value_text16 (argv[0]); + + if (!zInput) { + return; + } + + nInput = sqlite3_value_bytes16 (argv[0]); + + nOutput = nInput * 2 + 2; + zOutput = sqlite3_malloc (nOutput); + + if (!zOutput) { + return; + } + + u_strToLower (zOutput, nOutput/2, zInput, nInput/2, NULL, &status); + + if (!U_SUCCESS (status)){ + char zBuf[128]; + sqlite3_snprintf (128, zBuf, "ICU error: u_strToLower()/u_strToUpper(): %s", u_errorName (status)); + zBuf[127] = '\0'; + sqlite3_free (zOutput); + sqlite3_result_error (context, zBuf, -1); + return; + } + + sqlite3_result_text16 (context, zOutput, -1, sqlite3_free); +} + +#else /* GLib based */ + +static void +function_sparql_lower_case (sqlite3_context *context, + int argc, + sqlite3_value *argv[]) +{ + const gchar *zInput; + gchar *zOutput; + int nInput; + + g_assert (argc == 1); + + /* GLib API works with UTF-8, so use the UTF-8 functions of SQLite too */ + + zInput = (const gchar*) sqlite3_value_text (argv[0]); + + if (!zInput) { + return; + } + + nInput = sqlite3_value_bytes (argv[0]); + + if (!zOutput) { + return; + } + + zOutput = g_utf8_strdown (zInput, nInput); + + /* Unfortunately doesn't the GLib API allow us to pass pre-allocated memory, + * so we can't use sqlite3_malloc and sqlite3_free here */ + + sqlite3_result_text (context, zOutput, -1, g_free); +} + +#endif + static inline int stmt_step (sqlite3_stmt *stmt) { @@ -635,6 +756,10 @@ open_database (TrackerDBInterface *db_interface, db_interface, &function_sparql_uri_is_descendant, NULL, NULL); + sqlite3_create_function (db_interface->db, "SparqlLowerCase", 1, SQLITE_ANY, + db_interface, &function_sparql_lower_case, + NULL, NULL); + sqlite3_extended_result_codes (db_interface->db, 0); sqlite3_busy_timeout (db_interface->db, 100000); } diff --git a/src/libtracker-data/tracker-sparql-expression.vala b/src/libtracker-data/tracker-sparql-expression.vala index fdb0e2a6e..04fdcf31e 100644 --- a/src/libtracker-data/tracker-sparql-expression.vala +++ b/src/libtracker-data/tracker-sparql-expression.vala @@ -411,12 +411,18 @@ class Tracker.Sparql.Expression : Object { sql.append (" AS REAL)"); return PropertyType.DOUBLE; - } else if (uri == FN_NS + "lower-case") { + } else if (uri == TRACKER_NS + "ascii-lower-case") { // conversion to string sql.append ("lower ("); translate_expression_as_string (sql); sql.append (")"); return PropertyType.STRING; + } else if (uri == FN_NS + "lower-case") { + // conversion to string + sql.append ("SparqlLowerCase ("); + translate_expression_as_string (sql); + sql.append (")"); + return PropertyType.STRING; } else if (uri == FN_NS + "contains") { // fn:contains('A','B') => 'A' GLOB '*B*' sql.append ("("); |