def _query_parser(self): query_parser = QueryParser() query_parser.set_database(self.database) query_parser.set_default_op(Query.OP_AND) query_parser.set_stemmer(Stem("none")) query_parser.add_boolean_prefix('model', 'M:') query_parser.add_boolean_prefix('modelid', 'I:') if self.prefixes is not None: for name, prefix in self.prefixes.items(): if prefix == 'M:' or prefix == 'I:': continue query_parser.add_boolean_prefix(name, prefix) query_parser.set_stemming_strategy(self.stem) return query_parser
def _query2xquery(self, query): """take a "itools" query and return a "xapian" query """ query_class = type(query) fields = self._fields metadata = self._metadata # All Query if query_class is AllQuery: return Query('') # PhraseQuery, the field must be indexed if query_class is PhraseQuery: name = query.name if type(name) is not str: raise TypeError, "unexpected '%s'" % type(name) # If there is a problem => an empty result if name not in metadata: warn_not_indexed(name) return Query() info = metadata[name] try: prefix = info['prefix'] except KeyError: raise ValueError, 'the field "%s" must be indexed' % name field_cls = _get_field_cls(name, fields, info) return _make_PhraseQuery(field_cls, query.value, prefix) # RangeQuery, the field must be stored if query_class is RangeQuery: name = query.name if type(name) is not str: raise TypeError, "unexpected '%s'" % type(name) # If there is a problem => an empty result if name not in metadata: warn_not_indexed(name) return Query() info = metadata[name] value = info.get('value') if value is None: raise AttributeError, MSG_NOT_STORED.format(name=name) field_cls = _get_field_cls(name, fields, info) if field_cls.multiple: error = 'range-query not supported on multiple fields' raise ValueError, error left = query.left if left is not None: left = _encode_simple_value(field_cls, left) right = query.right if right is not None: right = _encode_simple_value(field_cls, right) # Case 1: no limits, return everything if left is None and right is None: return Query('') # Case 2: left limit only if right is None: return Query(OP_VALUE_GE, value, left) # Case 3: right limit only if left is None: return Query(OP_VALUE_LE, value, right) # Case 4: left and right return Query(OP_VALUE_RANGE, value, left, right) # StartQuery, the field must be stored if query_class is StartQuery: name = query.name if type(name) is not str: raise TypeError, "unexpected '%s'" % type(name) # If there is a problem => an empty result if name not in metadata: warn_not_indexed(name) return Query() info = metadata[name] value_nb = info.get('value') if value_nb is None: raise AttributeError, MSG_NOT_STORED.format(name=name) field_cls = _get_field_cls(name, fields, info) value = query.value value = _encode(field_cls, value) if value: # good = {x / x >= value} good = Query(OP_VALUE_GE, value_nb, value) # Construct the variable end_value: # end_value = the word "after" value: toto => totp # Delete the '\xff' at the end of value end_value = value while end_value and ord(end_value[-1]) == 255: end_value = end_value[:-1] # Normal case: end_value is not empty if end_value: # The world after end_value = end_value[:-1] + chr(ord(end_value[-1]) + 1) # bad = {x / x >= end_value} bad = Query(OP_VALUE_GE, value_nb, end_value) # Return {x / x in good but x not in bad} return Query(OP_AND_NOT, good, bad) # If end_value is empty else: # Return {x / x in good} return good else: # If value == '', we return everything return Query('') # TextQuery, the field must be indexed if query_class is TextQuery: name = query.name if type(name) is not str: raise TypeError, "unexpected %s for 'name'" % type(name) # If there is a problem => an empty result if name not in metadata: warn_not_indexed(name) return Query() info = metadata[name] field_cls = _get_field_cls(name, fields, info) try: prefix = info['prefix'] except KeyError: raise ValueError, 'the field "%s" must be indexed' % name # Remove accents from the value value = query.value if type(value) is not unicode: raise TypeError, "unexpected %s for 'value'" % type(value) value = value.translate(TRANSLATE_MAP) qp = QueryParser() qp.set_database(self._db) return qp.parse_query(_encode(field_cls, value), TQ_FLAGS, prefix) i2x = self._query2xquery # Multiple query with single atom if isinstance(query, _MultipleQuery) and len(query.atoms) == 1: return i2x(query.atoms[0]) # And if query_class is _AndQuery: return Query(OP_AND, [ i2x(q) for q in query.atoms ]) # Or if query_class is _OrQuery: return Query(OP_OR, [ i2x(q) for q in query.atoms ]) # Not if query_class is NotQuery: return Query(OP_AND_NOT, Query(''), i2x(query.query))