def _find_non_wildcards(self, values): """Check if this should be a wildcard match. Further, this will raise an exception if the syntax is improperly defined. :return: The offset of the last value we need to match against. """ if len(values) != len(self._definition): raise errors.InvalidValueForIndex() is_wildcard = False last = 0 for idx, val in enumerate(values): if val.endswith('*'): if val != '*': # We have an 'x*' style wildcard if is_wildcard: # We were already in wildcard mode, so this is invalid raise errors.InvalidGlobbing last = idx + 1 is_wildcard = True else: if is_wildcard: # We were in wildcard mode, we can't follow that with # non-wildcard raise errors.InvalidGlobbing last = idx + 1 if not is_wildcard: return -1 return last
def get_from_index(self, index_name, *key_values): definition = self._get_index_definition(index_name) if len(key_values) != len(definition): raise errors.InvalidValueForIndex() statement, args = self._format_query(definition, key_values) c = self._db_handle.cursor() try: c.execute(statement, tuple(args)) except dbapi2.OperationalError, e: raise dbapi2.OperationalError( str(e) + '\nstatement: %s\nargs: %s\n' % (statement, args))
def get_count_from_index(self, index_name, *key_values): """ Return the count for a given combination of index_name and key values. Extension method made from similar methods in u1db version 13.09 :param index_name: The index to query :type index_name: str :param key_values: values to match. eg, if you have an index with 3 fields then you would have: get_from_index(index_name, val1, val2, val3) :type key_values: tuple :return: count. :rtype: int """ c = self._db_handle.cursor() definition = self._get_index_definition(index_name) if len(key_values) != len(definition): raise u1db_errors.InvalidValueForIndex() tables = ["document_fields d%d" % i for i in range(len(definition))] novalue_where = [ "d.doc_id = d%d.doc_id" " AND d%d.field_name = ?" % (i, i) for i in range(len(definition)) ] exact_where = [ novalue_where[i] + (" AND d%d.value = ?" % (i, )) for i in range(len(definition)) ] args = [] where = [] for idx, (field, value) in enumerate(zip(definition, key_values)): args.append(field) where.append(exact_where[idx]) args.append(value) tables = ["document_fields d%d" % i for i in range(len(definition))] statement = ("SELECT COUNT(*) FROM document d, %s WHERE %s " % ( ', '.join(tables), ' AND '.join(where), )) try: c.execute(statement, tuple(args)) except sqlcipher_dbapi2.OperationalError as e: raise sqlcipher_dbapi2.OperationalError( str(e) + '\nstatement: %s\nargs: %s\n' % (statement, args)) res = c.fetchall() return res[0][0]
def get_from_index(self, index_name, *key_values): definition = self._get_index_definition(index_name) if len(key_values) != len(definition): raise errors.InvalidValueForIndex() statement, args = self._format_query(definition, key_values) c = self._db_handle.cursor() try: c.execute(statement, tuple(args)) except dbapi2.OperationalError as e: raise dbapi2.OperationalError( str(e) + '\nstatement: %s\nargs: %s\n' % (statement, args)) res = c.fetchall() results = [] for row in res: doc = self._factory(row[0], row[1], row[2]) doc.has_conflicts = row[3] > 0 results.append(doc) return results
def _format_range_query(self, definition, start_value, end_value): tables = ["document_fields d%d" % i for i in range(len(definition))] novalue_where = [ "d.doc_id = d%d.doc_id AND d%d.field_name = ?" % (i, i) for i in range(len(definition))] wildcard_where = [ novalue_where[i] + (" AND d%d.value NOT NULL" % (i,)) for i in range(len(definition))] like_where = [ novalue_where[i] + ( " AND (d%d.value < ? OR d%d.value GLOB ?)" % (i, i)) for i in range(len(definition))] range_where_lower = [ novalue_where[i] + (" AND d%d.value >= ?" % (i,)) for i in range(len(definition))] range_where_upper = [ novalue_where[i] + (" AND d%d.value <= ?" % (i,)) for i in range(len(definition))] args = [] where = [] if start_value: if isinstance(start_value, basestring): start_value = (start_value,) if len(start_value) != len(definition): raise errors.InvalidValueForIndex() is_wildcard = False for idx, (field, value) in enumerate(zip(definition, start_value)): args.append(field) if value.endswith('*'): if value == '*': where.append(wildcard_where[idx]) else: # This is a glob match if is_wildcard: # We can't have a partial wildcard following # another wildcard raise errors.InvalidGlobbing where.append(range_where_lower[idx]) args.append(self._strip_glob(value)) is_wildcard = True else: if is_wildcard: raise errors.InvalidGlobbing where.append(range_where_lower[idx]) args.append(value) if end_value: if isinstance(end_value, basestring): end_value = (end_value,) if len(end_value) != len(definition): raise errors.InvalidValueForIndex() is_wildcard = False for idx, (field, value) in enumerate(zip(definition, end_value)): args.append(field) if value.endswith('*'): if value == '*': where.append(wildcard_where[idx]) else: # This is a glob match if is_wildcard: # We can't have a partial wildcard following # another wildcard raise errors.InvalidGlobbing where.append(like_where[idx]) args.append(self._strip_glob(value)) args.append(value) is_wildcard = True else: if is_wildcard: raise errors.InvalidGlobbing where.append(range_where_upper[idx]) args.append(value) statement = ( "SELECT d.doc_id, d.doc_rev, d.content, count(c.doc_rev) FROM " "document d, %s LEFT OUTER JOIN conflicts c ON c.doc_id = " "d.doc_id WHERE %s GROUP BY d.doc_id, d.doc_rev, d.content ORDER " "BY %s;" % (', '.join(tables), ' AND '.join(where), ', '.join( ['d%d.value' % i for i in range(len(definition))]))) return statement, args