tracker r1929 - in branches/xesam-support: . data/services src/trackerd
- From: mottela svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r1929 - in branches/xesam-support: . data/services src/trackerd
- Date: Thu, 24 Jul 2008 15:01:58 +0000 (UTC)
Author: mottela
Date: Thu Jul 24 15:01:58 2008
New Revision: 1929
URL: http://svn.gnome.org/viewvc/tracker?rev=1929&view=rev
Log:
Initial version of the xesam user query parser
Added:
branches/xesam-support/src/trackerd/tracker-xesam-user-query.c
branches/xesam-support/src/trackerd/tracker-xesam-user-query.h
Modified:
branches/xesam-support/ChangeLog
branches/xesam-support/data/services/xesam-metadata.mmapping
branches/xesam-support/src/trackerd/Makefile.am
branches/xesam-support/src/trackerd/tracker-xesam-query.c
Modified: branches/xesam-support/data/services/xesam-metadata.mmapping
==============================================================================
--- branches/xesam-support/data/services/xesam-metadata.mmapping (original)
+++ branches/xesam-support/data/services/xesam-metadata.mmapping Thu Jul 24 15:01:58 2008
@@ -765,7 +765,7 @@
[xesam:url]
-MetaName=File:Name
+MetaName=File:Name;File:Path
[xesam:useCount]
Modified: branches/xesam-support/src/trackerd/Makefile.am
==============================================================================
--- branches/xesam-support/src/trackerd/Makefile.am (original)
+++ branches/xesam-support/src/trackerd/Makefile.am Thu Jul 24 15:01:58 2008
@@ -63,6 +63,8 @@
tracker-xesam-manager.h \
tracker-xesam-query.c \
tracker-xesam-query.h \
+ tracker-xesam-user-query.c \
+ tracker-xesam-user-query.h \
tracker-xesam-session.c \
tracker-xesam-session.h \
tracker-xesam-live-search.c \
Modified: branches/xesam-support/src/trackerd/tracker-xesam-query.c
==============================================================================
--- branches/xesam-support/src/trackerd/tracker-xesam-query.c (original)
+++ branches/xesam-support/src/trackerd/tracker-xesam-query.c Thu Jul 24 15:01:58 2008
@@ -48,6 +48,7 @@
#include <libtracker-common/tracker-utils.h>
#include "tracker-xesam-query.h"
+#include "tracker-xesam-user-query.h"
#include "tracker-db.h"
/* XESAM Query Condition
@@ -394,7 +395,6 @@
field_data = NULL;
valid = TRUE;
- /* Do the xesam mapping */
if (!strcmp(xesam_name,FIELD_NAME_FULL_TEXT_FIELDS)) {
result_set = tracker_db_xesam_get_all_text_metadata_names (data->iface);
} else {
@@ -548,6 +548,48 @@
data->current_field = g_strdup (name);
push_stack (data, STATE_FIELD);
}
+ } else if (ELEMENT_IS (ELEMENT_XESAM_USER_QUERY)) {
+
+ if (set_error_on_fail (state == STATE_START,
+ context,
+ "UserQuery element not expected here",
+ error)) {
+ return;
+ }
+
+ push_stack (data, STATE_USER_QUERY);
+ } else if (ELEMENT_IS (ELEMENT_XESAM_FIELD)) {
+ const gchar *name;
+
+ if (set_error_on_fail (is_operator (state),
+ context,
+ "Field element not expected here",
+ error)) {
+ return;
+ }
+
+ name = get_attribute_value_required (context,
+ "<field>",
+ "name",
+ attribute_names,
+ attribute_values,
+ error);
+
+ if (!name) {
+ return;
+ } else {
+ if (data->current_operator == OP_NONE) {
+ set_error (error,
+ context,
+ PARSE_ERROR,
+ "no operator found for field \"%s\"",
+ name);
+ return;
+ }
+
+ data->current_field = g_strdup (name);
+ push_stack (data, STATE_FIELD);
+ }
} else if (ELEMENT_IS (ELEMENT_XESAM_FULL_TEXT_FIELDS)) {
if (set_error_on_fail (is_operator (state),
@@ -1192,6 +1234,26 @@
push_stack (data, STATE_END_QUERY);
data->query_okay = TRUE;
+ } else if (ELEMENT_IS (ELEMENT_XESAM_USER_QUERY)) {
+ TrackerXesamUserQuery *uq;
+ GError *parse_error = NULL;
+ gchar *sql_where;
+
+ uq = tracker_xesam_user_query_new (data->current_value);
+
+ tracker_xesam_user_query_get_sql (uq, data->iface, &data->fields, &sql_where, &parse_error);
+
+ if (parse_error) {
+ g_propagate_error(error, parse_error);
+ return;
+ }
+
+ g_string_append (data->sql_where, sql_where);
+ g_free (sql_where);
+
+ push_stack (data, STATE_END_USER_QUERY);
+ data->query_okay = TRUE;
+
} else if (ELEMENT_IS (ELEMENT_XESAM_AND)) {
data->sql_where = g_string_append (data->sql_where, " ) ");
@@ -1357,6 +1419,7 @@
case STATE_DATE:
case STATE_FLOAT:
case STATE_BOOLEAN:
+ case STATE_USER_QUERY:
data->current_value = g_strstrip (g_strndup (text, text_len));
break;
Added: branches/xesam-support/src/trackerd/tracker-xesam-user-query.c
==============================================================================
--- (empty file)
+++ branches/xesam-support/src/trackerd/tracker-xesam-user-query.c Thu Jul 24 15:01:58 2008
@@ -0,0 +1,994 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Tracker - indexer and metadata database engine
+ * Copyright (C) 2007-2008 Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#include <glib-object.h>
+
+#include <trackerd/tracker-db.h>
+
+#include "tracker-xesam-user-query.h"
+
+#define TRACKER_XESAM_USER_QUERY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_XESAM_USER_QUERY, TrackerXesamUserQueryPrivate))
+
+typedef enum CollectorType CollectorType;
+typedef enum RelationType RelationType;
+typedef enum TreeNodeType TreeNodeType;
+typedef struct TreeNode TreeNode;
+typedef struct TrackerXesamUserQueryPrivate TrackerXesamUserQueryPrivate;
+typedef struct ComposeHitsData ComposeHitsData;
+typedef struct SearchHitData SearchHitData;
+
+enum CollectorType {
+ COLLECTOR_UNDEF,
+ COLLECTOR_NONE,
+ COLLECTOR_RELATION,
+ COLLECTOR_IGNORE,
+ COLLECTOR_AND,
+ COLLECTOR_OR
+};
+
+enum RelationType {
+ REL_NONE,
+ REL_EQUAL,
+ REL_KEYWORD,
+ REL_LESS_OR_EQUAL,
+ REL_GREATER_OR_EQUAL,
+ REL_LESS,
+ REL_GREATER
+};
+
+struct TreeNode {
+ TreeNode *left;
+ TreeNode *right;
+ CollectorType collector;
+
+ gchar *keyword;
+ RelationType relation;
+ gchar *value;
+
+ /* operator modifiers */
+ gboolean negate;
+
+ /* phrase modifiers */
+ gboolean boost;
+ gboolean case_sensitive;
+ gboolean diacritic_sensitive;
+ gboolean stemming;
+ gboolean ordered;
+ gboolean proximity;
+ gboolean regular;
+ gboolean sloppy;
+ gboolean word_based;
+};
+
+struct TrackerXesamUserQueryPrivate {
+ gchar *query_str;
+ TreeNode *tree;
+ GQuark error_quark;
+};
+
+enum {
+ PROP_0,
+ PROP_QUERY
+};
+
+
+
+static void tracker_xesam_user_query_class_init (TrackerXesamUserQueryClass *class);
+static void tracker_xesam_user_query_init (TrackerXesamUserQuery *uq);
+static void tracker_xesam_user_query_finalize (GObject *object);
+static void tracker_xesam_user_query_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void tracker_xesam_user_query_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE (TrackerXesamUserQuery, tracker_xesam_user_query, G_TYPE_OBJECT)
+
+static void
+tracker_xesam_user_query_class_init (TrackerXesamUserQueryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_xesam_user_query_finalize;
+ object_class->set_property = tracker_xesam_user_query_set_property;
+ object_class->get_property = tracker_xesam_user_query_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_QUERY,
+ g_param_spec_string ("query",
+ "Query",
+ "Query",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (object_class,
+ sizeof (TrackerXesamUserQueryPrivate));
+}
+
+static void
+tracker_xesam_user_query_init (TrackerXesamUserQuery *uq)
+{
+ TrackerXesamUserQueryPrivate *priv;
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+
+ priv->error_quark = g_quark_from_static_string ("XESAM-user-parser-error-quark");
+}
+
+static TreeNode *
+tree_node_term_new (gchar *value)
+{
+ TreeNode *node;
+
+ node = g_slice_new0 (TreeNode);
+ node->value = g_strdup(value);
+ node->collector = COLLECTOR_NONE;
+
+ return node;
+}
+
+static TreeNode *
+tree_node_relation_new (const gchar *keyword)
+{
+ TreeNode *node;
+
+ node = g_slice_new0 (TreeNode);
+ node->keyword = g_strdup (keyword);
+ node->collector = COLLECTOR_RELATION;
+
+ return node;
+}
+
+static TreeNode *
+tree_node_collector_new (CollectorType collector)
+{
+ TreeNode *node;
+
+ node = g_slice_new0 (TreeNode);
+ node->collector = collector;
+
+ return node;
+}
+
+static void
+tree_node_free (TreeNode *node)
+{
+ if (!node)
+ return;
+
+ g_free (node->keyword);
+
+ tree_node_free (node->left);
+ tree_node_free (node->right);
+
+ g_slice_free (TreeNode, node);
+}
+
+void
+tree_node_set_value (TreeNode *node, gchar *value)
+{
+ /* FIXME Add checks */
+ node->value = g_strdup(value);
+}
+
+void
+tree_node_set_relation (TreeNode *node, RelationType relation)
+{
+ /* FIXME Add checks */
+ node->relation = relation;
+}
+
+void
+tree_node_set_modifiers (TreeNode *node, const gchar *modifiers)
+{
+ /* FIXME Add checks */
+
+ /* FIXME Implement */
+}
+
+
+static void
+tracker_xesam_user_query_finalize (GObject *object)
+{
+ TrackerXesamUserQueryPrivate *priv;
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (object);
+
+ tree_node_free (priv->tree);
+ g_free (priv->query_str);
+
+ G_OBJECT_CLASS (tracker_xesam_user_query_parent_class)->finalize (object);
+}
+
+static void
+tracker_xesam_user_query_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id) {
+ case PROP_QUERY:
+ tracker_xesam_user_query_set_query (TRACKER_XESAM_USER_QUERY (object),
+ g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+tracker_xesam_user_query_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TrackerXesamUserQueryPrivate *priv;
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_QUERY:
+ g_value_set_string (value, priv->query_str);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+TrackerXesamUserQuery *
+tracker_xesam_user_query_new (const gchar *query_str)
+{
+ g_return_val_if_fail (query_str != NULL, NULL);
+
+ return g_object_new (TRACKER_TYPE_XESAM_USER_QUERY,
+ "query", query_str,
+ NULL);
+}
+
+static void
+dump_tree (TreeNode *node)
+{
+ if (!node) {
+ g_print ("NULL ");
+ return;
+ }
+
+ switch (node->collector) {
+ case COLLECTOR_AND:
+ g_print ("AND \n(\n");
+ dump_tree (node->left);
+ dump_tree (node->right);
+ g_print ("\n)\n");
+ break;
+ case COLLECTOR_OR:
+ g_print ("OR \n(\n");
+ dump_tree (node->left);
+ dump_tree (node->right);
+ g_print ("\n)\n");
+ break;
+ default:
+ if (node->keyword) {
+ g_print ("%s ", node->keyword);
+ }
+
+ if (node->relation) {
+ g_print ("relation %d ", node->relation);
+ }
+
+ if (node->value) {
+ g_print ("And we have a value");
+ }
+ }
+}
+
+static void
+create_query_tree (TrackerXesamUserQuery *uq)
+{
+ TrackerXesamUserQueryPrivate *priv;
+ TreeNode *node, *stack_node;
+ GQueue *queue, *stack;
+ CollectorType collector;
+
+ gboolean last_was_collector = TRUE;
+ gboolean negate = FALSE;
+
+ gchar *string;
+ gchar value[100];
+
+ GScannerConfig config = {
+ "\t\r\n", /* characters to skip */
+ G_CSET_a_2_z "_" G_CSET_A_2_Z, /* identifier start */
+ G_CSET_a_2_z "_." G_CSET_A_2_Z G_CSET_DIGITS,/* identifier cont. */
+ "#\n", /* single line comment */
+ TRUE, /* case_sensitive */
+ TRUE, /* skip multi-line comments */
+ TRUE, /* skip single line comments */
+ FALSE, /* scan multi-line comments */
+ TRUE, /* scan identifiers */
+ TRUE, /* scan 1-char identifiers */
+ FALSE, /* scan NULL identifiers */
+ FALSE, /* scan symbols */
+ FALSE, /* scan binary */
+ FALSE, /* scan octal */
+ TRUE, /* scan float */
+ TRUE, /* scan hex */
+ FALSE, /* scan hex dollar */
+ TRUE, /* scan single quote strings */
+ TRUE, /* scan double quite strings */
+ TRUE, /* numbers to int */
+ FALSE, /* int to float */
+ TRUE, /* identifier to string */
+ TRUE, /* char to token */
+ FALSE, /* symbol to token */
+ FALSE, /* scope 0 fallback */
+ FALSE /* store int64 */
+ };
+
+ GScanner *scanner;
+ GTokenType ttype;
+ GTokenType peek_ttype;
+ const gchar *query;
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+
+ queue = g_queue_new ();
+ stack = g_queue_new ();
+
+ scanner = g_scanner_new (&config);
+ query = tracker_xesam_user_query_get_query (uq);
+ g_scanner_input_text (scanner, query, strlen (query));
+
+ g_message ("Parsing xesam userQuery: %s", query);
+
+ for (peek_ttype = g_scanner_peek_next_token (scanner);
+ peek_ttype != G_TOKEN_EOF;
+ peek_ttype = g_scanner_peek_next_token (scanner)) {
+
+ collector = COLLECTOR_UNDEF;
+ node = NULL;
+
+ switch (peek_ttype) {
+
+ case G_TOKEN_STRING:
+
+ if (strcmp (scanner->next_value.v_string, "AND") == 0 ||
+ strcmp (scanner->next_value.v_string, "and") == 0) {
+
+ collector = COLLECTOR_AND;
+ ttype = g_scanner_get_next_token(scanner);
+ g_print ("\nAND\n");
+
+ } else if (strcmp (scanner->next_value.v_string, "OR") == 0 ||
+ strcmp (scanner->next_value.v_string, "or") == 0) {
+
+ collector = COLLECTOR_OR;
+ ttype = g_scanner_get_next_token(scanner);
+ g_print ("\nOR\n");
+
+ } else {
+
+ if (last_was_collector) {
+ collector = COLLECTOR_NONE;
+ g_print ("Term:");
+ ttype = g_scanner_get_next_token(scanner);
+ } else {
+ collector = COLLECTOR_AND;
+ g_print ("\nAssumed AND\n");
+ }
+ }
+ break;
+
+ case '+':
+ if (last_was_collector) {
+ collector = COLLECTOR_IGNORE;
+ ttype = g_scanner_get_next_token(scanner);
+
+ g_print ("Ignored (+)");
+ } else {
+ collector = COLLECTOR_AND;
+ ttype = g_scanner_get_next_token(scanner);
+
+ g_print ("\nAND (+)\n");
+ }
+ break;
+
+ case '-':
+ if (last_was_collector) {
+ collector = COLLECTOR_IGNORE;
+ /* FIXME negate the last collector */
+ ttype = g_scanner_get_next_token(scanner);
+ } else {
+ collector = COLLECTOR_AND;
+ negate = TRUE;
+ }
+ break;
+
+ case '&':
+ ttype = g_scanner_get_next_token(scanner);
+ if (g_scanner_peek_next_token (scanner) == '&') {
+ collector = COLLECTOR_AND;
+ ttype = g_scanner_get_next_token(scanner);
+ } else {
+ g_error ("Single '&' encountered.");
+ }
+ break;
+
+ case '|':
+ ttype = g_scanner_get_next_token(scanner);
+ if (g_scanner_peek_next_token (scanner) == '|') {
+ collector = COLLECTOR_OR;
+ ttype = g_scanner_get_next_token(scanner);
+ } else {
+ g_error ("Single '|' encountered.");
+ }
+ break;
+
+ case ' ':
+ collector = COLLECTOR_IGNORE;
+ ttype = g_scanner_get_next_token (scanner);
+ break;
+
+ default:
+ g_error ("Parse error. Unexpected type");
+ }
+
+ switch (collector) {
+ case COLLECTOR_AND :
+ node = tree_node_collector_new (COLLECTOR_AND);
+ last_was_collector = TRUE;
+
+ g_queue_push_head (stack, node);
+ break;
+
+ case COLLECTOR_OR:
+ node = tree_node_collector_new (COLLECTOR_OR);
+ last_was_collector = TRUE;
+
+ stack_node = g_queue_peek_head (stack);
+
+ while (stack_node && stack_node->collector == COLLECTOR_AND) {
+ stack_node = g_queue_pop_head (stack);
+ g_queue_push_head (queue, stack_node);
+
+ stack_node = g_queue_peek_head (stack);
+ }
+
+ g_queue_push_head (stack, node);
+ break;
+
+ case COLLECTOR_IGNORE:
+ /* Ignore */
+ break;
+
+ case COLLECTOR_NONE:
+
+ string = g_strdup(scanner->value.v_string);
+ last_was_collector = FALSE;
+
+ g_print ("String (%s) ", string);
+ peek_ttype = g_scanner_peek_next_token (scanner);
+
+ if (peek_ttype == G_TOKEN_STRING) {
+ g_print ("for text search ");
+ node = tree_node_term_new (scanner->value.v_string);
+
+ ttype = g_scanner_get_next_token (scanner);
+ g_print ("with modifiers (%s)", scanner->value.v_string);
+ tree_node_set_modifiers (node, scanner->value.v_string);
+
+ } else {
+ while ((peek_ttype = g_scanner_peek_next_token (scanner)) == ' ') {
+ ttype = g_scanner_get_next_token (scanner);
+ }
+
+ switch (peek_ttype) {
+ case '<' :
+ case '>' :
+ node = tree_node_relation_new (string);
+ ttype = g_scanner_get_next_token (scanner);
+
+ if ((peek_ttype = g_scanner_peek_next_token (scanner)) == '=') {
+ g_print ("relation (%c%c) ", ttype, peek_ttype);
+ if (ttype == '>') {
+ tree_node_set_relation (node, REL_GREATER_OR_EQUAL);
+ } else {
+ tree_node_set_relation (node, REL_LESS_OR_EQUAL);
+ }
+
+ ttype = g_scanner_peek_next_token (scanner);
+ } else {
+ g_print ("relation (%c) ", ttype);
+ if (ttype == '>') {
+ tree_node_set_relation (node, REL_GREATER);
+ } else {
+ tree_node_set_relation (node, REL_LESS);
+ }
+
+ ttype = g_scanner_peek_next_token (scanner);
+ }
+
+ while ((ttype = g_scanner_get_next_token (scanner)) == ' ');
+
+ switch (ttype) {
+ case G_TOKEN_STRING :
+ g_error ("Strings not expected for given relation");
+ break;
+
+ case G_TOKEN_INT :
+ g_print ("int (%lu)", scanner->value.v_int);
+ sprintf (value, "%lu", scanner->value.v_int);
+ tree_node_set_value (node, value);
+ break;
+
+ case G_TOKEN_FLOAT :
+ g_print ("float (%lf)",scanner->value.v_float);
+ sprintf (value, "%lf", scanner->value.v_float);
+ tree_node_set_value (node, value);
+ break;
+
+ default:
+ g_error ("Value type expected, not '%c'", (char) ttype);
+ break;
+ }
+ break;
+
+ case ':' :
+ case '=' :
+ node = tree_node_relation_new (string);
+ ttype = g_scanner_get_next_token (scanner);
+
+ g_print ("relation (%c) ", ttype);
+ if (ttype == ':') {
+ tree_node_set_relation (node, REL_KEYWORD);
+ } else {
+ tree_node_set_relation (node, REL_EQUAL);
+ }
+ while ((ttype = g_scanner_get_next_token (scanner)) == ' ');
+
+ switch (ttype) {
+ case G_TOKEN_STRING :
+ g_print ("string (%s)",scanner->value.v_string);
+ tree_node_set_value (node, scanner->value.v_string);
+ if ((peek_ttype = g_scanner_peek_next_token(scanner)) == G_TOKEN_STRING) {
+ ttype = g_scanner_get_next_token (scanner);
+ g_print ("with modifiers (%s)", scanner->value.v_string);
+ tree_node_set_modifiers (node, scanner->value.v_string);
+ }
+ break;
+
+ case G_TOKEN_INT :
+ g_print ("int (%lu)",scanner->value.v_int);
+ sprintf (value, "%lu", scanner->value.v_int);
+ tree_node_set_value (node, value);
+ break;
+
+ case G_TOKEN_FLOAT :
+ g_print ("float (%lf)",scanner->value.v_float);
+ sprintf (value, "%lf", scanner->value.v_float);
+ tree_node_set_value (node, value);
+ break;
+
+ default:
+ g_error ("Value type expected, not '%c'", (char) ttype);
+ break;
+ }
+ break;
+
+ default:
+ g_print ("which is a full text search.");
+ node = tree_node_term_new (string);
+ break;
+ }
+ }
+ g_free (string);
+
+ g_queue_push_head (queue, node);
+ break;
+
+ default:
+ g_error ("Undefined operation");
+ }
+ }
+
+ g_print ("\nDone parsing. Processing.\n");
+
+ while ((stack_node = g_queue_pop_head (stack)) != NULL) {
+ g_queue_push_head (queue, stack_node);
+ }
+
+ while ((node = g_queue_pop_tail (queue)) != NULL) {
+ switch (node->collector) {
+ case COLLECTOR_AND:
+ case COLLECTOR_OR:
+ node->left = g_queue_pop_head (stack);
+ node->right = g_queue_pop_head (stack);
+ g_queue_push_head (stack, node);
+ break;
+ default:
+ g_queue_push_head (stack, node);
+ break;
+ }
+
+ priv->tree = node;
+ }
+
+
+ g_scanner_destroy (scanner);
+ g_queue_free (stack);
+ g_queue_free (queue);
+}
+
+static GList *
+add_metadata_field (TrackerDBInterface *iface,
+ GSList **fields,
+ const gchar *xesam_name)
+{
+ TrackerDBResultSet *result_set;
+ TrackerFieldData *field_data;
+ gboolean field_exists;
+ const GSList *l;
+ GList *reply;
+ gboolean valid;
+ GString *full_name;
+
+ reply = NULL;
+ field_exists = FALSE;
+ field_data = NULL;
+ valid = TRUE;
+
+ full_name = g_string_new (xesam_name);
+
+ full_name = g_string_prepend (full_name, "xesam:");
+
+ /* Do the xesam mapping */
+ result_set = tracker_db_xesam_get_metadata_names (iface, full_name->str);
+
+ if (!result_set) {
+ return NULL;
+ }
+
+ while (valid) {
+ gchar *field_name;
+
+ tracker_db_result_set_get (result_set, 0, &field_name, -1);
+
+ /* Check if field is already in list */
+ for (l = *fields; l; l = l->next) {
+ const gchar *this_field_name;
+
+ this_field_name = tracker_field_data_get_field_name (l->data);
+
+ if (!this_field_name) {
+ continue;
+ }
+
+ if (strcasecmp (this_field_name, field_name) == 0) {
+ field_data = l->data;
+ field_exists = TRUE;
+
+ break;
+ }
+ }
+
+ if (!field_exists) {
+ field_data = tracker_db_get_metadata_field (iface,
+ "Files", // FIXME This is a bogus value. Should we really need this?
+ field_name,
+ g_slist_length (*fields),
+ FALSE,
+ TRUE);
+ if (field_data) {
+ *fields = g_slist_prepend (*fields, field_data);
+ }
+ }
+
+ if (field_data) {
+ reply = g_list_append (reply, field_data);
+ }
+
+ valid = tracker_db_result_set_iter_next (result_set);
+ g_free (field_name);
+ }
+
+ g_string_free (full_name, TRUE);
+
+ return reply;
+}
+
+
+gboolean
+create_sql (TrackerXesamUserQuery *uq, TreeNode *node, TrackerDBInterface *iface, GSList **fields, GString **sql, GError **error)
+{
+ GList *field_data_list = NULL;
+ GList *field_data = NULL;
+ const gchar *where_field;
+ TrackerXesamUserQueryPrivate *priv;
+
+ g_return_val_if_fail (TRACKER_IS_XESAM_USER_QUERY (uq), FALSE);
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+
+ if (!node) {
+ g_print ("NULL ");
+ return TRUE;
+ }
+
+ switch (node->collector) {
+ case COLLECTOR_AND:
+ g_print (" AND (");
+
+ g_string_append_printf (*sql, "(");
+ g_print (" (call 1st)");
+ if (!create_sql (uq, node->left, iface, fields, sql, error)) {
+ g_print (" (failed) ");
+ return FALSE;
+ }
+ g_string_append_printf (*sql, " AND ");
+ g_print (" (call 2nd)");
+ if (!create_sql (uq, node->right, iface, fields, sql, error)) {
+ g_print (" (failed) ");
+ return FALSE;
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+ case COLLECTOR_OR:
+ g_print (" OR ");
+
+ g_string_append_printf (*sql, "(");
+ g_print (" (call 1st)");
+ if (!create_sql (uq, node->left, iface, fields, sql, error)) {
+ g_print (" (failed) ");
+ return FALSE;
+ }
+ g_string_append_printf (*sql, " OR ");
+ g_print (" (call 2nd)");
+ if (!create_sql (uq, node->right, iface, fields, sql, error)) {
+ g_print (" (failed) ");
+ return FALSE;
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+ case COLLECTOR_RELATION:
+ g_print (" RELATION ");
+
+ switch (node->relation) {
+ case REL_KEYWORD:
+
+ if (strcmp(node->keyword, "type") == 0) {
+
+ } else {
+
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s : %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ }
+ break;
+
+ case REL_EQUAL:
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s = %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+
+ case REL_LESS_OR_EQUAL:
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s <= %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+
+ case REL_GREATER_OR_EQUAL:
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s >= %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+
+ case REL_LESS:
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s < %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+
+ case REL_GREATER:
+ field_data_list = add_metadata_field (iface, fields, node->keyword);
+
+ if (!field_data_list) {
+ g_set_error (error, priv->error_quark, 1, "No such field: %s", node->keyword);
+ return FALSE;
+ }
+
+ g_string_append_printf (*sql, "(");
+ for (field_data = field_data_list;field_data;field_data = g_list_next (field_data)) {
+
+ if (field_data != field_data_list) {
+ g_string_append_printf (*sql, " OR ");
+ }
+ where_field = tracker_field_data_get_where_field (field_data->data);
+ g_string_append_printf (*sql, "(%s > %s)", where_field, node->value);
+ }
+ g_string_append_printf (*sql, ")");
+ break;
+
+ default:
+ g_set_error (error, priv->error_quark, 1, "Unexpected relation type");
+ return FALSE;
+
+ }
+ break;
+ case COLLECTOR_NONE:
+ g_print (" NONE ");
+
+ g_set_error (error, priv->error_quark, 1, "Full text search is not implemented yet");
+
+ return FALSE;
+
+ break;
+ default:
+ g_set_error (error, priv->error_quark, 1, "Undefined operation");
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+
+
+void
+tracker_xesam_user_query_set_query (TrackerXesamUserQuery *uq,
+ const gchar *query_str)
+{
+ TrackerXesamUserQueryPrivate *priv;
+ gchar *str;
+
+ g_return_if_fail (TRACKER_IS_XESAM_USER_QUERY (uq));
+ g_return_if_fail (query_str != NULL);
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+
+ str = g_strdup (query_str);
+ g_free (priv->query_str);
+ priv->query_str = str;
+
+ /* construct the parse tree */
+ create_query_tree (uq);
+
+ g_object_notify (G_OBJECT (uq), "query");
+}
+
+G_CONST_RETURN gchar *
+tracker_xesam_user_query_get_query (TrackerXesamUserQuery *uq)
+{
+ TrackerXesamUserQueryPrivate *priv;
+
+ g_return_val_if_fail (TRACKER_IS_XESAM_USER_QUERY (uq), NULL);
+
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+ return priv->query_str;
+}
+
+gboolean
+tracker_xesam_user_query_get_sql (TrackerXesamUserQuery *uq, TrackerDBInterface *iface,
+ GSList **fields, gchar **sql_where, GError **error)
+{
+ TrackerXesamUserQueryPrivate *priv;
+ GString *sql;
+
+ g_return_val_if_fail (sql_where != NULL, FALSE);
+
+ sql = g_string_new ("");
+
+ g_return_val_if_fail (TRACKER_IS_XESAM_USER_QUERY (uq), FALSE);
+ priv = TRACKER_XESAM_USER_QUERY_GET_PRIVATE (uq);
+
+ g_return_val_if_fail (TRACKER_IS_DB_INTERFACE (iface), FALSE);
+
+ g_return_val_if_fail (priv->tree != NULL, FALSE);
+
+ if (!create_sql (uq, priv->tree, iface, fields, &sql, error)) {
+ *sql_where = NULL;
+ return FALSE;
+ }
+
+ g_print ("\nWe got:%s\n", sql->str);
+
+ g_string_prepend (sql, "WHERE ");
+
+ *sql_where = g_strdup (sql->str);
+ g_string_free (sql, TRUE);
+ return TRUE;
+
+}
Added: branches/xesam-support/src/trackerd/tracker-xesam-user-query.h
==============================================================================
--- (empty file)
+++ branches/xesam-support/src/trackerd/tracker-xesam-user-query.h Thu Jul 24 15:01:58 2008
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __TRACKERD_XESAM_USER_QUERY_H__
+#define __TRACKERD_XESAM_USER_QUERY_H__
+
+#include <glib.h>
+
+#include <libtracker-db/tracker-db-interface.h>
+#include <libtracker-common/tracker-field-data.h>
+
+G_BEGIN_DECLS
+
+#include <glib-object.h>
+
+#define TRACKER_TYPE_XESAM_USER_QUERY (tracker_xesam_user_query_get_type())
+#define TRACKER_XESAM_USER_QUERY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_XESAM_USER_QUERY, TrackerXesamUserQuery))
+#define TRACKER_XESAM_USER_QUERY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_XESAM_USER_QUERY, TrackerXesamUserQueryClass))
+#define TRACKER_IS_XESAM_USER_QUERY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_XESAM_USER_QUERY))
+#define TRACKER_IS_XESAM_USER_QUERY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_XESAM_USER_QUERY))
+#define TRACKER_XESAM_USER_QUERY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_XESAM_USER_QUERY, TrackerXesamUserQueryClass))
+
+typedef struct TrackerXesamUserQuery TrackerXesamUserQuery;
+typedef struct TrackerXesamUserQueryClass TrackerXesamUserQueryClass;
+typedef struct TrackerSearchHit TrackerSearchHit;
+typedef struct TrackerHitCount TrackerHitCount;
+
+struct TrackerXesamUserQuery {
+ GObject parent;
+};
+
+struct TrackerXesamUserQueryClass {
+ GObjectClass parent_class;
+};
+
+
+GType tracker_xesam_user_query_get_type (void);
+TrackerXesamUserQuery * tracker_xesam_user_query_new (const gchar *query_str);
+
+
+
+G_CONST_RETURN gchar *tracker_xesam_user_query_get_query (TrackerXesamUserQuery *tree);
+void tracker_xesam_user_query_set_query (TrackerXesamUserQuery *tree,
+ const gchar *query_str);
+
+G_CONST_RETURN TrackerDBInterface * tracker_xesam_user_query_get_iface (TrackerXesamUserQuery *tree);
+void tracker_xesam_user_query_set_iface (TrackerXesamUserQuery *tree,
+ TrackerDBInterface *query_str);
+
+gboolean tracker_xesam_user_query_get_sql (TrackerXesamUserQuery *tree,
+ TrackerDBInterface *iface,
+ GSList **fields,
+ gchar **sql_where,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __TRACKERD_XESAM_USER_QUERY_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]