[tracker/tracker-tag-and-operator-fix] wip



commit 83b631cd9f607d50719f7c2b22d9c9f0e935d284
Author: Martyn Russell <martyn lanedo com>
Date:   Mon Mar 10 13:01:19 2014 +0000

    wip

 docs/manpages/tracker-tag.1     |   21 +++-
 src/tracker-utils/tracker-tag.c |  221 ++++++++++++++++++++++++++++++---------
 2 files changed, 186 insertions(+), 56 deletions(-)
---
diff --git a/docs/manpages/tracker-tag.1 b/docs/manpages/tracker-tag.1
index 73519a4..8b7b8d3 100644
--- a/docs/manpages/tracker-tag.1
+++ b/docs/manpages/tracker-tag.1
@@ -29,8 +29,18 @@ Limit search to N results. The default is 512.
 Offset the search results by N. For example, start at item number 10
 in the results. The default is 0.
 .TP
-.B \-r, \-\-or-operator
-Use OR for search terms instead of AND (the default)
+.B \-r, \-\-and-operator
+Use AND operator for search terms instead of OR(the default). For
+example:
+
+.nf
+$ tracker-tag -s -t sliff sloff
+.fi
+
+Should show files in the database that have both the \fIsliff\fR
+.B AND
+\fIsloff\fR tags.
+
 .TP
 .B \-t, \-\-list
 List all tags. Results include the number of files associated with
@@ -39,10 +49,11 @@ associated with each tag by using --show-files.
 
 The \fITAG\fR arguments are optional. If no \fITAG\fR argument
 is specified, all tags are listed. If one or more \fITAG\fRs are
-given, all matching tags are listed. For example, this will match any
-tags named either \fIfoo\fR, \fIbar\fR or \fIbaz\fR:
+given, either matching tags are listed (OR condition). For example,
+this will match any tags named either \fIfoo\fR, \fIbar\fR or
+\fIbaz\fR:
+
 .nf
-.BR
 $ tracker-tag -t foo bar baz
 .fi
 
diff --git a/src/tracker-utils/tracker-tag.c b/src/tracker-utils/tracker-tag.c
index 42c4b95..ba88792 100644
--- a/src/tracker-utils/tracker-tag.c
+++ b/src/tracker-utils/tracker-tag.c
@@ -42,7 +42,7 @@
 static gint limit = 512;
 static gint offset;
 static gchar **files;
-static gboolean or_operator;
+static gboolean and_operator;
 static gchar *add_tag;
 static gchar *remove_tag;
 static gchar *description;
@@ -59,8 +59,8 @@ static GOptionEntry entries[] = {
          N_("Offset the results"),
          "0"
        },
-       { "or-operator", 'r', 0, G_OPTION_ARG_NONE, &or_operator,
-         N_("Use OR for search terms instead of AND (the default)"),
+       { "and-operator", 'n', 0, G_OPTION_ARG_NONE, &and_operator,
+         N_("Use AND for search terms instead of OR (the default)"),
          NULL
        },
        { "list", 't', 0, G_OPTION_ARG_NONE, &list,
@@ -150,7 +150,9 @@ get_escaped_sparql_string (const gchar *str)
 
 static gchar *
 get_filter_string (GStrv        files,
+                   const gchar *subject,
                    gboolean     files_are_urns,
+                   gboolean     and_operator,
                    const gchar *tag)
 {
        GString *filter;
@@ -176,13 +178,17 @@ get_filter_string (GStrv        files,
 
        for (i = 0; i < len; i++) {
                if (files_are_urns) {
-                       g_string_append_printf (filter, "?urn = <%s>", files[i]);
+                       g_string_append_printf (filter, "%s = <%s>", subject, files[i]);
                } else {
-                       g_string_append_printf (filter, "?f = \"%s\"", files[i]);
+                       g_string_append_printf (filter, "%s = \"%s\"", subject, files[i]);
                }
 
                if (i < len - 1) {
-                       g_string_append (filter, " || ");
+                       if (G_UNLIKELY (and_operator)) {
+                               g_string_append (filter, " && ");
+                       } else {
+                               g_string_append (filter, " || ");
+                       }
                }
        }
 
@@ -233,7 +239,7 @@ get_file_urns (TrackerSparqlConnection *connection,
        gchar *query, *filter;
        GError *error = NULL;
 
-       filter = get_filter_string (uris, FALSE, tag);
+       filter = get_filter_string (uris, "?f", FALSE, FALSE, tag);
        query = g_strdup_printf ("SELECT ?urn ?f "
                                 "WHERE { "
                                 "  ?urn "
@@ -337,61 +343,170 @@ get_all_tags_show_tag_id (TrackerSparqlConnection *connection,
        g_object_unref (cursor);
 }
 
+static inline gchar *
+get_filter_in_for_strv (GStrv        files,
+                        const gchar *subject)
+{
+       gchar *filter, *filter_in;
+
+       /* e.g. '?label IN ("foo", "bar")' */
+       filter_in = g_strjoinv ("\",\"", files);
+       filter = g_strdup_printf ("FILTER (%s IN (\"%s\"))", subject, filter_in);
+       g_free (filter_in);
+
+       return filter;
+}
+
+static gboolean
+get_all_files (TrackerSparqlConnection *connection,
+               GStrv                    files,
+               gint                     search_offset,
+               gint                     search_limit)
+{
+       TrackerSparqlCursor *cursor;
+       GError *error = NULL;
+       GStrv tags;
+       gchar *filter, *query;
+
+       /* First, get matching tags */
+       filter = get_filter_in_for_strv (files, "?label");
+       query = g_strdup_printf ("SELECT ?t"
+                                "WHERE { "
+                                "  ?t a nao:Tag ;"
+                                "     nao:prefLabel ?label ."
+                                "  %s"
+                                "}",
+                                filter);
+       g_free (filter);
+
+       cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
+       g_free (query);
+
+       if (error) {
+               g_printerr ("%s, %s\n",
+                           _("Could not get all tags in the database"),
+                           error->message);
+               g_error_free (error);
+
+               return FALSE;
+       }
+
+       tags = result_to_strv (cursor, 0);
+       if (!tags) {
+               g_print ("%s\n",
+                        _("No files have been tagged"));
+
+               if (cursor) {
+                       g_object_uref (cursor);
+               }
+
+               return TRUE;
+       } 
+
+       filter = get_filter_in_for_strv (tags, "?t")
+       g_strv_free (tags);
+
+       query = g_strdup_printf ("SELECT DISTINCT nie:url(?f) "
+                                "WHERE {"
+                                "  ?r a rdfs:Resource ;"
+                                "     nao:hasTag ?t ."
+                                "  %s"
+                                "}"
+                                "OFFSET %d "
+                                "LIMIT %d",
+                                filter,
+                                search_offset,
+                                search_limit);
+       g_free (filter);
+ 
+       cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
+       g_free (query);
+
+       if (error) {
+               g_printerr ("%s, %s\n",
+                           _("Could not get files for matching tags"),
+                           error->message);
+               g_error_free (error);
+
+               return FALSE;
+       }
+
+       if (!cursor) {
+               g_print ("%s\n",
+                        _("No files were found matching ALL of those tags"));
+       } else {
+               gint count = 0;
+
+               g_print ("%s:\n", _("Files"));
+
+               while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
+                       g_print ("  %s\n",
+                                tracker_sparql_cursor_get_string (cursor, 0, NULL));
+                       count++;
+               }
+
+               if (count == 0) {
+                       /* To translators: This is to say there are no
+                        * files found associated with multiple tags, e.g.:
+                        *
+                        *   Files:
+                        *     None
+                        *
+                        */
+                       g_print ("  %s\n", _("None"));
+               }
+
+               g_print ("\n");
+
+               if (count >= search_limit) {
+                       show_limit_warning ();
+               }
+
+               g_object_unref (cursor);
+       }
+
+       return TRUE;
+}
+
+
 static gboolean
 get_all_tags (TrackerSparqlConnection *connection,
               GStrv                    files,
               gint                     search_offset,
               gint                     search_limit,
-              gboolean                 use_or_operator,
               gboolean                 show_files)
 {
        TrackerSparqlCursor *cursor;
        GError *error = NULL;
        gchar *query;
+       gchar *filter = NULL;
 
        if (files && g_strv_length (files) > 0) {
-               gchar *filter;
+               filter = get_filter_in_for_label (files);
+       }
 
-               /* e.g. '?label IN ("foo", "bar")' */
-               filter = g_strjoinv ("\",\"", files);
 
-               /* You might be asking, why not logical AND here, why
-                * logical OR for FILTER, well, tags can't have
-                * multiple labels is the simple answer.
-                */
-               query = g_strdup_printf ("SELECT ?tag ?label nao:description(?tag) COUNT(?urns) AS urns "
-                                        "WHERE {"
-                                        "  ?tag a nao:Tag ;"
-                                        "  nao:prefLabel ?label ."
-                                        "  OPTIONAL {"
-                                        "     ?urns nao:hasTag ?tag"
-                                        "  } ."
-                                        "  FILTER (?label IN (\"%s\"))"
-                                        "} "
-                                        "GROUP BY ?tag "
-                                        "ORDER BY ASC(?label) "
-                                        "OFFSET %d "
-                                        "LIMIT %d",
-                                        filter,
-                                        search_offset,
-                                        search_limit);
-               g_free (filter);
-       } else {
-               query = g_strdup_printf ("SELECT ?tag ?label nao:description(?tag) COUNT(?urns) AS urns "
-                                        "WHERE {"
-                                        "  ?tag a nao:Tag ;"
-                                        "  nao:prefLabel ?label ."
-                                        "  OPTIONAL {"
-                                        "     ?urns nao:hasTag ?tag"
-                                        "  }"
-                                        "} "
-                                        "GROUP BY ?tag "
-                                        "ORDER BY ASC(?label) "
-                                        "OFFSET %d "
-                                        "LIMIT %d",
-                                        search_offset,
-                                        search_limit);
-       }
+       /* You might be asking, why not logical AND here, why
+        * logical OR for FILTER, well, tags can't have
+        * multiple labels is the simple answer.
+        */
+       query = g_strdup_printf ("SELECT ?tag ?label nao:description(?tag) COUNT(?urns) AS urns "
+                                "WHERE {"
+                                "  ?tag a nao:Tag ;"
+                                "  nao:prefLabel ?label ."
+                                "  OPTIONAL {"
+                                "     ?urns nao:hasTag ?tag"
+                                "  } ."
+                                "  %s"
+                                "} "
+                                "GROUP BY ?tag "
+                                "ORDER BY ASC(?label) "
+                                "OFFSET %d "
+                                "LIMIT %d",
+                                filter ? filter : "",
+                                search_offset,
+                                search_limit);
+       g_free (filter);
 
        cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
        g_free (query);
@@ -618,7 +733,7 @@ add_tag_for_urns (TrackerSparqlConnection *connection,
        if (urns_strv) {
                gchar *filter;
 
-               filter = get_filter_string (urns_strv, TRUE, NULL);
+               filter = get_filter_string (urns_strv, "?urn", TRUE, FALSE, NULL);
 
                /* Add tag to specific urns */
                query = g_strdup_printf ("INSERT { "
@@ -738,7 +853,7 @@ remove_tag_for_urns (TrackerSparqlConnection *connection,
                }
 
                urns_strv = result_to_strv (urns_cursor, 0);
-               filter = get_filter_string (urns_strv, TRUE, urn);
+               filter = get_filter_string (urns_strv, "?urn", TRUE, FALSE, urn);
                g_strfreev (urns_strv);
 
                query = g_strdup_printf ("DELETE { "
@@ -921,7 +1036,11 @@ main (int argc, char **argv)
        if (list) {
                gboolean success;
 
-               success = get_all_tags (connection, files, offset, limit, or_operator, show_files);
+               if (G_UNLIKELY (and_operator)) {
+                       success = get_all_files (connection, files, offset, limit);
+               } else {
+                       success = get_all_tags (connection, files, offset, limit, show_files);
+               }
                g_object_unref (connection);
 
                return success ? EXIT_SUCCESS : EXIT_FAILURE;


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