Fix metadata search.
[pithos] / pithos / backends / lib / sqlite / node.py
index 3952327..87d3dce 100644 (file)
@@ -40,7 +40,7 @@ from pithos.lib.filter import parse_filters
 
 ROOTNODE  = 0
 
-( SERIAL, NODE, HASH, SIZE, SOURCE, MTIME, MUSER, CLUSTER ) = range(8)
+( SERIAL, NODE, HASH, SIZE, SOURCE, MTIME, MUSER, UUID, CLUSTER ) = range(9)
 
 inf = float('inf')
 
@@ -88,7 +88,8 @@ _propnames = {
     'source'    : 4,
     'mtime'     : 5,
     'muser'     : 6,
-    'cluster'   : 7,
+    'uuid'      : 7,
+    'cluster'   : 8
 }
 
 
@@ -147,6 +148,7 @@ class Node(DBWorker):
                             source     integer,
                             mtime      integer,
                             muser      text    not null default '',
+                            uuid       text    not null default '',
                             cluster    integer not null default 0,
                             foreign key (node)
                             references nodes(node)
@@ -154,6 +156,8 @@ class Node(DBWorker):
                             on delete cascade ) """)
         execute(""" create index if not exists idx_versions_node_mtime
                     on versions(node, mtime) """)
+        execute(""" create index if not exists idx_versions_node_uuid
+                    on versions(uuid) """)
         
         execute(""" create table if not exists attributes
                           ( serial integer,
@@ -203,10 +207,10 @@ class Node(DBWorker):
     def node_get_versions(self, node, keys=(), propnames=_propnames):
         """Return the properties of all versions at node.
            If keys is empty, return all properties in the order
-           (serial, node, size, source, mtime, muser, cluster).
+           (serial, node, hash, size, source, mtime, muser, uuid, cluster).
         """
         
-        q = ("select serial, node, hash, size, source, mtime, muser, cluster "
+        q = ("select serial, node, hash, size, source, mtime, muser, uuid, cluster "
              "from versions "
              "where node = ?")
         self.execute(q, (node,))
@@ -409,7 +413,7 @@ class Node(DBWorker):
         parent, path = props
         
         # The latest version.
-        q = ("select serial, node, hash, size, source, mtime, muser, cluster "
+        q = ("select serial, node, hash, size, source, mtime, muser, uuid, cluster "
              "from versions "
              "where serial = (select max(serial) "
                              "from versions "
@@ -459,15 +463,15 @@ class Node(DBWorker):
         mtime = max(mtime, r[2])
         return (count, size, mtime)
     
-    def version_create(self, node, hash, size, source, muser, cluster=0):
+    def version_create(self, node, hash, size, source, muser, uuid, cluster=0):
         """Create a new version from the given properties.
            Return the (serial, mtime) of the new version.
         """
         
-        q = ("insert into versions (node, hash, size, source, mtime, muser, cluster) "
-             "values (?, ?, ?, ?, ?, ?, ?)")
+        q = ("insert into versions (node, hash, size, source, mtime, muser, uuid, cluster) "
+             "values (?, ?, ?, ?, ?, ?, ?, ?)")
         mtime = time()
-        props = (node, hash, size, source, mtime, muser, cluster)
+        props = (node, hash, size, source, mtime, muser, uuid, cluster)
         serial = self.execute(q, props).lastrowid
         self.statistics_update_ancestors(node, 1, size, mtime, cluster)
         return serial, mtime
@@ -475,11 +479,11 @@ class Node(DBWorker):
     def version_lookup(self, node, before=inf, cluster=0):
         """Lookup the current version of the given node.
            Return a list with its properties:
-           (serial, node, hash, size, source, mtime, muser, cluster)
+           (serial, node, hash, size, source, mtime, muser, uuid, cluster)
            or None if the current version is not found in the given cluster.
         """
         
-        q = ("select serial, node, hash, size, source, mtime, muser, cluster "
+        q = ("select serial, node, hash, size, source, mtime, muser, uuid, cluster "
              "from versions "
              "where serial = (select max(serial) "
                              "from versions "
@@ -495,10 +499,10 @@ class Node(DBWorker):
         """Return a sequence of values for the properties of
            the version specified by serial and the keys, in the order given.
            If keys is empty, return all properties in the order
-           (serial, node, hash, size, source, mtime, muser, cluster).
+           (serial, node, hash, size, source, mtime, muser, uuid, cluster).
         """
         
-        q = ("select serial, node, hash, size, source, mtime, muser, cluster "
+        q = ("select serial, node, hash, size, source, mtime, muser, uuid, cluster "
              "from versions "
              "where serial = ?")
         self.execute(q, (serial,))
@@ -602,29 +606,33 @@ class Node(DBWorker):
         args = []
         
         if included:
-            subq = "a.key in ("
-            subq += ','.join(('?' for x in included)) + ")"
+            subq = "exists (select 1 from attributes where serial = v.serial and domain = ? and "
+            subq += "(" + ' or '.join(('key = ?' for x in included)) + ")"
+            subq += ")"
+            args += [domain]
             args += included
             append(subq)
         
         if excluded:
-            subq = "a.key not in ("
-            subq += ','.join(('?' for x in excluded)) + ")"
+            subq = "not exists (select 1 from attributes where serial = v.serial and domain = ? and "
+            subq += "(" + ' or '.join(('key = ?' for x in excluded)) + ")"
+            subq += ")"
+            args += [domain]
             args += excluded
             append(subq)
         
         if opers:
-            t = (("(a.key = ? and a.value %s ?)" % (o,)) for k, o, v in opers)
-            subq = "(" + ' or '.join(t) + ")"
             for k, o, v in opers:
-                args += [k, v]
-            append(subq)
+                subq = "exists (select 1 from attributes where serial = v.serial and domain = ? and "
+                subq += "key = ? and value %s ?" % (o,)
+                subq += ")"
+                args += [domain, k, v]
+                append(subq)
         
         if not subqlist:
             return None, None
         
-        subq = ' and a.domain = ? and ' + ' and '.join(subqlist)
-        args = [domain] + args
+        subq = ' and ' + ' and '.join(subqlist)
         
         return subq, args
     
@@ -649,12 +657,12 @@ class Node(DBWorker):
         q = ("select distinct a.key "
              "from attributes a, versions v, nodes n "
              "where v.serial = (select max(serial) "
-                              "from versions "
-                              "where node = v.node and mtime < ?) "
+                               "from versions "
+                               "where node = v.node and mtime < ?) "
              "and v.cluster != ? "
              "and v.node in (select node "
-                           "from nodes "
-                           "where parent = ?) "
+                            "from nodes "
+                            "where parent = ?) "
              "and a.serial = v.serial "
              "and a.domain = ? "
              "and n.node = v.node")
@@ -722,15 +730,14 @@ class Node(DBWorker):
         nextling = strnextling(prefix)
         
         q = ("select distinct n.path, v.serial "
-             "from attributes a, versions v, nodes n "
+             "from versions v, nodes n "
              "where v.serial = (select max(serial) "
-                              "from versions "
-                              "where node = v.node and mtime < ?) "
+                               "from versions "
+                               "where node = v.node and mtime < ?) "
              "and v.cluster != ? "
              "and v.node in (select node "
-                           "from nodes "
-                           "where parent = ?) "
-             "and a.serial = v.serial "
+                            "from nodes "
+                            "where parent = ?) "
              "and n.node = v.node "
              "and n.path > ? and n.path < ?")
         args = [before, except_cluster, parent, start, nextling]
@@ -791,3 +798,15 @@ class Node(DBWorker):
             execute(q, args)
         
         return matches, prefixes
+    
+    def latest_uuid(self, uuid):
+        """Return a (path, serial) tuple, for the latest version of the given uuid."""
+        
+        q = ("select n.path, v.serial "
+             "from versions v, nodes n "
+             "where v.serial = (select max(serial) "
+                               "from versions "
+                               "where uuid = ?) "
+             "and n.node = v.node")
+        self.execute(q, (uuid,))
+        return self.fetchone()