X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/37bee317e154b027ff2dcf10ce2ab3fc4f949b5a..7ff57991be57309f4a447351c8b3426532c028ad:/pithos/backends/lib/sqlalchemy/node.py diff --git a/pithos/backends/lib/sqlalchemy/node.py b/pithos/backends/lib/sqlalchemy/node.py index c763ffe..094e8d4 100644 --- a/pithos/backends/lib/sqlalchemy/node.py +++ b/pithos/backends/lib/sqlalchemy/node.py @@ -35,7 +35,7 @@ from time import time from sqlalchemy import Table, Integer, BigInteger, DECIMAL, Column, String, MetaData, ForeignKey from sqlalchemy.types import Text from sqlalchemy.schema import Index, Sequence -from sqlalchemy.sql import func, and_, or_, not_, null, select, bindparam, text +from sqlalchemy.sql import func, and_, or_, not_, null, select, bindparam, text, exists from sqlalchemy.ext.compiler import compiles from sqlalchemy.engine.reflection import Inspector @@ -186,7 +186,7 @@ class Node(DBWorker): indexes = [elem['name'] for elem in insp.get_indexes('nodes')] if 'idx_nodes_path' not in indexes: explicit_length = '(%s)' %path_length if self.engine.name == 'mysql' else '' - s = text('CREATE INDEX idx_nodes_path ON nodes (path%s)' %explicit_length) + s = text('CREATE UNIQUE INDEX idx_nodes_path ON nodes (path%s)' %explicit_length) self.conn.execute(s).close() s = self.nodes.select().where(and_(self.nodes.c.node == ROOTNODE, @@ -768,7 +768,7 @@ class Node(DBWorker): def latest_version_list(self, parent, prefix='', delimiter=None, start='', limit=10000, before=inf, - except_cluster=0, pathq=[], domain=None, filterq=[]): + except_cluster=0, pathq=[], domain=None, filterq=[], sizeq=None): """Return a (list of (path, serial) tuples, list of common prefixes) for the current versions of the paths with the given parent, matching the following criteria. @@ -803,6 +803,8 @@ class Node(DBWorker): key ?op value the attribute with this key satisfies the value where ?op is one of ==, != <=, >=, <, >. + + h. the size is in the range set by sizeq The list of common prefixes includes the prefixes matching up to the first delimiter after prefix, @@ -819,7 +821,6 @@ class Node(DBWorker): start = strprevling(prefix) nextling = strnextling(prefix) - a = self.attributes.alias('a') v = self.versions.alias('v') n = self.nodes.alias('n') s = select([n.c.path, v.c.serial]).distinct() @@ -830,28 +831,43 @@ class Node(DBWorker): s = s.where(v.c.cluster != except_cluster) s = s.where(v.c.node.in_(select([self.nodes.c.node], self.nodes.c.parent == parent))) - if domain and filterq: - s = s.where(a.c.serial == v.c.serial) - s = s.where(a.c.domain == domain) s = s.where(n.c.node == v.c.node) s = s.where(and_(n.c.path > bindparam('start'), n.c.path < nextling)) conj = [] for x in pathq: conj.append(n.c.path.like(self.escape_like(x) + '%', escape='\\')) - if conj: s = s.where(or_(*conj)) + if sizeq and len(sizeq) == 2: + if sizeq[0]: + s = s.where(v.c.size >= sizeq[0]) + if sizeq[1]: + s = s.where(v.c.size < sizeq[1]) + if domain and filterq: + a = self.attributes.alias('a') included, excluded, opers = parse_filters(filterq) if included: - s = s.where(a.c.key.in_(x for x in included)) + subs = select([1]) + subs = subs.where(a.c.serial == v.c.serial).correlate(v) + subs = subs.where(a.c.domain == domain) + subs = subs.where(or_(*[a.c.key.op('=')(x) for x in included])) + s = s.where(exists(subs)) if excluded: - s = s.where(not_(a.c.key.in_(x for x in excluded))) + subs = select([1]) + subs = subs.where(a.c.serial == v.c.serial).correlate(v) + subs = subs.where(a.c.domain == domain) + subs = subs.where(or_(*[a.c.key.op('=')(x) for x in excluded])) + s = s.where(not_(exists(subs))) if opers: - for k, o, v in opers: - s = s.where(or_(a.c.key == k and a.c.value.op(o)(v))) + for k, o, val in opers: + subs = select([1]) + subs = subs.where(a.c.serial == v.c.serial).correlate(v) + subs = subs.where(a.c.domain == domain) + subs = subs.where(and_(a.c.key.op('=')(k), a.c.value.op(o)(val))) + s = s.where(exists(subs)) s = s.order_by(n.c.path)