[tracker/wip/carlosg/sparql-parser-ng: 29/43] libtracker-data: Append literals directly past the variable limit
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql-parser-ng: 29/43] libtracker-data: Append literals directly past the variable limit
- Date: Sat, 3 Nov 2018 13:09:58 +0000 (UTC)
commit b292e4b321852ad69405b22b540baf2cdd643f08
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Oct 7 23:27:33 2018 +0200
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.
src/libtracker-data/tracker-sparql.c | 82 ++++++++++++++++++++++++++++++++++--
1 file 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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]