diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2018-10-07 23:27:33 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2018-11-13 11:17:31 +0100 |
commit | f046b2bf47ad3f1720c0f95eb33c2e80177417e3 (patch) | |
tree | 7af7ab30740ba1f59475bac06d5140f47dad5092 | |
parent | 3a82afdf607a992a91bc741cfe65d93653977cd7 (diff) | |
download | tracker-f046b2bf47ad3f1720c0f95eb33c2e80177417e3.tar.gz |
libtracker-data: Append literals directly past the variable limit
Once we are past the variable limit (Currently hardcoded to 999, matching
SQLite limits) resort to appending literals in SQL directly. This used to
happen in the older parser, and unbreaks 02-sparql-bugs which tests this.
-rw-r--r-- | src/libtracker-data/tracker-sparql.c | 82 |
1 files changed, 79 insertions, 3 deletions
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c index 011b5ab5e..600d1c776 100644 --- a/src/libtracker-data/tracker-sparql.c +++ b/src/libtracker-data/tracker-sparql.c @@ -37,6 +37,9 @@ #define XSD_NS "http://www.w3.org/2001/XMLSchema#" #define FN_NS "http://www.w3.org/2005/xpath-functions#" +/* FIXME: This should be dependent on SQLITE_LIMIT_VARIABLE_NUMBER */ +#define MAX_VARIABLES 999 + enum { TIME_FORMAT_SECONDS, TIME_FORMAT_MINUTES, @@ -57,6 +60,7 @@ static gboolean helper_translate_time (TrackerSparql *sparql, static TrackerDBStatement * prepare_query (TrackerDBInterface *iface, TrackerStringBuilder *str, GPtrArray *literals, + gboolean cached, GError **error); static inline TrackerVariable * _ensure_variable (TrackerSparql *sparql, const gchar *name); @@ -113,6 +117,7 @@ struct _TrackerSparql GHashTable *solution_var_map; gboolean silent; + gboolean cacheable; struct { TrackerContext *context; @@ -405,6 +410,32 @@ _append_placeholder (TrackerSparql *sparql) return tracker_string_builder_append_placeholder (sparql->current_state.sql); } +static inline gchar * +_escape_sql_string (const gchar *str) +{ + int i, j, len; + gchar *copy; + + len = strlen (str); + copy = g_new (char, (len * 2) + 1); + i = j = 0; + + while (i < len) { + if (str[i] == '\'') { + copy[j] = '\''; + j++; + } + + copy[j] = str[i]; + i++; + j++; + } + + copy[j] = '\0'; + + return copy; +} + static inline void _append_literal_sql (TrackerSparql *sparql, TrackerLiteralBinding *binding) @@ -414,14 +445,53 @@ _append_literal_sql (TrackerSparql *sparql, idx = tracker_select_context_get_literal_binding_index (TRACKER_SELECT_CONTEXT (sparql->context), binding); + if (idx >= MAX_VARIABLES) { + sparql->cacheable = FALSE; + } + if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_RESOURCE) { _append_string_printf (sparql, - "COALESCE ((SELECT ID FROM Resource WHERE Uri = ?%d), 0) ", - idx + 1); + "COALESCE ((SELECT ID FROM Resource WHERE Uri = "); + } + + if (!sparql->cacheable) { + gchar *escaped, *full_str; + + switch (TRACKER_BINDING (binding)->data_type) { + case TRACKER_PROPERTY_TYPE_DATE: + full_str = g_strdup_printf ("%sT00:00:00Z", binding->literal); + escaped = _escape_sql_string (full_str); + _append_string (sparql, escaped); + g_free (escaped); + g_free (full_str); + break; + case TRACKER_PROPERTY_TYPE_DATETIME: + case TRACKER_PROPERTY_TYPE_STRING: + case TRACKER_PROPERTY_TYPE_RESOURCE: + escaped = _escape_sql_string (binding->literal); + _append_string (sparql, escaped); + g_free (escaped); + break; + case TRACKER_PROPERTY_TYPE_BOOLEAN: + if (g_str_equal (binding->literal, "1") || + g_ascii_strcasecmp (binding->literal, "true") == 0) { + _append_string (sparql, "1"); + } else { + _append_string (sparql, "0"); + } + break; + case TRACKER_PROPERTY_TYPE_UNKNOWN: + case TRACKER_PROPERTY_TYPE_INTEGER: + case TRACKER_PROPERTY_TYPE_DOUBLE: + _append_string (sparql, binding->literal); + break; + } } else { _append_string_printf (sparql, "?%d ", idx + 1); } + if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_RESOURCE) + _append_string_printf (sparql, "), 0) "); if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_STRING) _append_string (sparql, "COLLATE " TRACKER_COLLATION_NAME " "); } @@ -2612,6 +2682,7 @@ get_solution_for_pattern (TrackerSparql *sparql, iface = tracker_data_manager_get_writable_db_interface (sparql->data_manager); stmt = prepare_query (iface, sparql->sql, TRACKER_SELECT_CONTEXT (sparql->context)->literal_bindings, + FALSE, error); g_clear_object (&sparql->context); @@ -6222,6 +6293,7 @@ tracker_sparql_init (TrackerSparql *sparql) g_free, g_free); sparql->var_names = g_ptr_array_new_with_free_func (g_free); sparql->var_types = g_array_new (FALSE, FALSE, sizeof (TrackerPropertyType)); + sparql->cacheable = TRUE; } TrackerSparql* @@ -6255,6 +6327,7 @@ static TrackerDBStatement * prepare_query (TrackerDBInterface *iface, TrackerStringBuilder *str, GPtrArray *literals, + gboolean cached, GError **error) { TrackerDBStatement *stmt; @@ -6263,7 +6336,9 @@ prepare_query (TrackerDBInterface *iface, query = tracker_string_builder_to_string (str); stmt = tracker_db_interface_create_statement (iface, - TRACKER_DB_STATEMENT_CACHE_TYPE_SELECT, + cached ? + TRACKER_DB_STATEMENT_CACHE_TYPE_SELECT : + TRACKER_DB_STATEMENT_CACHE_TYPE_NONE, error, query); g_free (query); @@ -6348,6 +6423,7 @@ tracker_sparql_execute_cursor (TrackerSparql *sparql, iface = tracker_data_manager_get_db_interface (sparql->data_manager); stmt = prepare_query (iface, sparql->sql, TRACKER_SELECT_CONTEXT (sparql->context)->literal_bindings, + sparql->cacheable, error); if (!stmt) return NULL; |