X-Git-Url: https://git.jsancho.org/?p=mojodb.git;a=blobdiff_plain;f=cursor.py;h=eec8b65e71d865e7b0bc6fd1112d11cd4d4f06f1;hp=202c6c78aabb6429a8b8cd012b616e9f921a6169;hb=HEAD;hpb=2758cc7948327b7a0256a7ba3291024afea02552 diff --git a/cursor.py b/cursor.py index 202c6c7..eec8b65 100644 --- a/cursor.py +++ b/cursor.py @@ -19,13 +19,20 @@ # ############################################################################## -import cPickle class Cursor(object): def __init__(self, collection, spec=None, fields=None, **kwargs): if spec and not type(spec) is dict: raise Exception("spec must be an instance of dict") + self.Query = collection.database.connection.Query + self.Field = collection.database.connection.Field + self.Table = collection.database.connection.Table + self.Constraint = collection.database.connection.Constraint + self.Literal = collection.database.connection.Literal + + self.serializer = collection.database.connection.serializer + self.collection = collection self.spec = spec if self.collection.exists(): @@ -74,36 +81,53 @@ class Cursor(object): return res_fields def _get_cursor(self): - query = {} - table_id = '%s$_id' % self.collection.table_name + table_id = self.Table(self.collection.database.db_name, '%s$_id' % self.collection.table_name) - query['select'] = [(table_id, 'id')] + fields = [self.Field(table_id, 'value')] for f in filter(lambda x: x != '_id', self.fields): - table_f = '%s$%s' % (self.collection.table_name, f) - q = self._get_cursor_field(table_id, table_f) - query['select'].append(q) + fields.append(self._get_cursor_field(f)) - query['from'] = [table_id] + tables = [table_id] + constraints = [self.Constraint('=', self.Field(table_id, 'name'), self.Literal('_id'))] if self.spec: - query['where'] = [] for k, v in self.spec.iteritems(): - table_f = '%s$%s' % (self.collection.table_name, k) - if type(v) in (int, float): - field_q = self._get_cursor_field(table_id, table_f, field_name='number') - query['where'].append((field_q, '=', v)) - else: - field_q = self._get_cursor_field(table_id, table_f) - query['where'].append((field_q, '=', cPickle.dumps(v))) - - return self.collection.database.connection._get_cursor(self.collection.database.db_name, query) - - def _get_cursor_field(self, table_id, table_field, field_name='value'): - return { - 'select': [(table_field, field_name)], - 'from': [table_field], - 'where': [((table_field, 'id'), '=', (table_id, 'id'))], - } + constraints.append(self._get_cursor_constraint(k, v)) + + query = self.Query(fields, tables, constraints) + return self.collection.database.connection._get_cursor(query) + + def _get_cursor_field(self, field_name): + table_id = self.Table(self.collection.database.db_name, '%s$_id' % self.collection.table_name) + table_field = self.Table(self.collection.database.db_name, '%s$%s' % (self.collection.table_name, field_name.split(".")[0])) + + fields = [self.Field(table_field, 'value')] + tables = [table_field] + constraints = [ + self.Constraint('=', self.Field(table_field, 'id'), self.Field(table_id, 'id')), + self.Constraint('=', self.Field(table_field, 'name'), self.Literal(field_name)), + ] + return self.Query(fields, tables, constraints) + + def _get_cursor_constraint(self, field_name, field_value): + table_id = self.Table(self.collection.database.db_name, '%s$_id' % self.collection.table_name) + table_field = self.Table(self.collection.database.db_name, '%s$%s' % (self.collection.table_name, field_name.split(".")[0])) + + if type(field_value) in (int, float): + field_type = 'number' + else: + field_type = 'value' + field_value = self.serializer.dumps(field_value) + + fields = [self.Field(table_field, 'id')] + tables = [table_field] + constraints = [ + self.Constraint('or', self.Constraint('=', self.Field(table_field, 'name'), self.Literal(field_name)), + self.Constraint('starts', self.Field(table_field, 'name'), self.Literal('%s..' % field_name))), + self.Constraint('=', self.Field(table_field, field_type), self.Literal(field_value)), + ] + + return self.Constraint('in', self.Field(table_id, 'id'), self.Query(fields, tables, constraints)) def next(self): if self.cursor is None: @@ -116,11 +140,11 @@ class Cursor(object): else: document = {} if '_id' in self.fields: - document['_id'] = res[0] + document['_id'] = self.serializer.loads(res[0]) fields_without_id = filter(lambda x: x != '_id', self.fields) for i in xrange(len(fields_without_id)): if not res[i + 1] is None: - document[fields_without_id[i]] = cPickle.loads(res[i + 1]) + document[fields_without_id[i]] = self.serializer.loads(res[i + 1]) return document else: return None