[rygel] media-db: Implement search on MediaDBContainer



commit 8c24afcfec9e7447d15177609be35ce4a604ef62
Author: Jens Georg <mail jensge org>
Date:   Fri Nov 20 22:26:30 2009 +0100

    media-db: Implement search on MediaDBContainer
    
    This features a first draft of translation from SearchExpression to an SQL
    where clause.

 src/rygel/rygel-media-db-container.vala |  146 +++++++++++++++++++++++++++++++
 src/rygel/rygel-media-db.vala           |   51 +++++++++++
 2 files changed, 197 insertions(+), 0 deletions(-)
---
diff --git a/src/rygel/rygel-media-db-container.vala b/src/rygel/rygel-media-db-container.vala
index a27f01c..02511ac 100644
--- a/src/rygel/rygel-media-db-container.vala
+++ b/src/rygel/rygel-media-db-container.vala
@@ -19,6 +19,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
+using GUPnP;
 
 public class Rygel.MediaDBContainer : MediaContainer {
     protected MediaDB media_db;
@@ -63,6 +64,151 @@ public class Rygel.MediaDBContainer : MediaContainer {
 
         return children;
     }
+
+    public override async Gee.List<MediaObject>? search (
+                                        SearchExpression expression,
+                                        uint             offset,
+                                        uint             max_count,
+                                        out uint         total_matches,
+                                        Cancellable?     cancellable)
+                                        throws GLib.Error {
+        var args = new GLib.ValueArray(0);
+        var filter = this.search_expression_to_sql (expression, args);
+
+        debug ("Orignal search: %s", expression.to_string());
+        debug ("Parsed search expression: %s", filter);
+
+        for (int i = 0; i < args.n_values; i++)
+            debug ("Arg %d: %s", i, args.get_nth(i).get_string());
+
+        var children = this.media_db.get_children_with_filter (filter,
+                                                               args,
+                                                               this.id,
+                                                               offset,
+                                                               max_count);
+        foreach (var child in children) {
+            child.parent = this;
+        }
+
+        return children;
+    }
+
+    private string? search_expression_to_sql (SearchExpression? expression,
+                                              GLib.ValueArray args) {
+        string result = null;
+
+        if (expression == null)
+            return result;
+
+        if (expression is LogicalExpression) {
+            var exp = (LogicalExpression) expression;
+            string left = search_expression_to_sql (exp.operand1, args);
+            string right = search_expression_to_sql (exp.operand2, args);
+            result = "(%s %s %s)".printf (left,
+                          expression.op == LogicalOperator.AND ? "AND" : "OR",
+                          right);
+        } else {
+            var exp = (RelationalExpression) expression;
+            string column = null;
+            string func = null;
+            switch (exp.operand1)
+            {
+                case "@id":
+                    column = "o.upnp_id";
+                    break;
+                case "@parentID":
+                    column = "o.parent";
+                    break;
+                case "upnp:class":
+                    column = "m.class";
+                    break;
+                case "dc:title":
+                    column = "o.title";
+                    break;
+                case "dc:creator":
+                    column = "m.author";
+                    break;
+                case "dc:date":
+                    column = "m.date";
+                    break;
+                default:
+                    warning("Unsupported thing");
+                    break;
+            }
+            if (column == null)
+                return result;
+
+            switch (exp.op) {
+/*                case SearchCriteriaOp.EXISTS:
+                    if (op.operand2 == "true")
+                        func = "=";
+                    else
+                        func = "!=";
+                    break; */
+                case SearchCriteriaOp.EQ:
+                    func = "=";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.NEQ:
+                    func = "=";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.LESS:
+                    func = "<";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.LEQ:
+                    func = "<=";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.GREATER:
+                    func = ">";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.GEQ:
+                    func = ">=";
+                    GLib.Value v;
+                    v = exp.operand2;
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.CONTAINS:
+                    func = "LIKE";
+                    GLib.Value v;
+                    v = "%%%s%%".printf(exp.operand2);
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.DOES_NOT_CONTAIN:
+                    func = "NOT LIKE";
+                    GLib.Value v;
+                    v = "%%%s%%".printf(exp.operand2);
+                    args.append (v);
+                    break;
+                case SearchCriteriaOp.DERIVED_FROM:
+                    func = "LIKE";
+                    GLib.Value v;
+                    v = "%s%%".printf(exp.operand2);
+                    args.append (v);
+                    break;
+                default:
+                    warning ("Unsupported op %d", exp.op);
+                    break;
+            }
+
+            result = "%s %s ?".printf(column, func);
+        }
+
+        return result;
+    }
 }
 
 
diff --git a/src/rygel/rygel-media-db.vala b/src/rygel/rygel-media-db.vala
index 632bebc..1481c89 100644
--- a/src/rygel/rygel-media-db.vala
+++ b/src/rygel/rygel-media-db.vala
@@ -190,6 +190,24 @@ public class Rygel.MediaDB : Object {
                  "o.title ASC " +
     "LIMIT ?,?";
 
+    private const string GET_CHILDREN_STRING_WITH_FILTER =
+    "SELECT o.type_fk, o.title, m.size, m.mime_type, " +
+            "m.width, m.height, m.class, m.author, m.album, " +
+            "m.date, m.bitrate, m.sample_freq, m.bits_per_sample, " +
+            "m.channels, m.track, m.color_depth, m.duration, " +
+            "o.upnp_id, o.parent, o.timestamp " +
+    "FROM Object o " +
+        "JOIN Closure c ON o.upnp_id = c.descendant AND c.ancestor = ? " +
+        "LEFT OUTER JOIN meta_data m " +
+            "ON o.upnp_id = m.object_fk " +
+    "WHERE %s " +
+        "ORDER BY o.type_fk ASC, " +
+                 "m.class ASC, " +
+                 "m.track ASC, " +
+                 "o.title ASC " +
+    "LIMIT ?,?";
+
+
     private const string URI_GET_STRING =
     "SELECT uri FROM Uri WHERE Uri.object_fk = ?";
 
@@ -706,4 +724,37 @@ public class Rygel.MediaDB : Object {
         this.db.exec (GET_CHILDREN_STRING, values, cb);
         return children;
     }
+
+    public Gee.ArrayList<MediaObject> get_children_with_filter (
+                                                 string filter,
+                                                 GLib.ValueArray args,
+                                                 string container_id,
+                                                 long offset,
+                                                 long max_count) throws Error {
+        ArrayList<MediaObject> children = new ArrayList<MediaObject> ();
+        GLib.Value v = container_id;
+        args.prepend (v);
+        v = offset;
+        args.append (v);
+        v = max_count;
+        args.append (v);
+
+        debug ("Parameters to bind: %u", args.n_values);
+
+        Rygel.Database.RowCallback cb = (stmt) => {
+            var child_id = stmt.column_text (17);
+            var parent_id = stmt.column_text (18);
+            var parent = (MediaContainer) get_object (parent_id);
+            children.add (get_object_from_statement (parent,
+                                                     child_id,
+                                                     stmt));
+            children[children.size - 1].parent = parent;
+            children[children.size - 1].parent_ref = parent;
+
+            return true;
+        };
+
+        this.db.exec (GET_CHILDREN_STRING_WITH_FILTER.printf(filter), args.values, cb);
+        return children;
+    }
 }



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