diff options
author | Sascha Silbe <sascha@silbe.org> | 2009-07-19 11:22:54 (GMT) |
---|---|---|
committer | Sascha Silbe <sascha@silbe.org> | 2009-07-19 11:22:54 (GMT) |
commit | dfda7fe0ddce178b8a7da1c7414a721fad445f3c (patch) | |
tree | 476375d98c00d811631aaf7a6c075802436b8051 | |
parent | a5f12b6805c7554871e566b702a1b995340f664b (diff) |
add support for list- and range-queries
-rw-r--r-- | src/carquinyol/indexstore.py | 77 |
1 files changed, 54 insertions, 23 deletions
diff --git a/src/carquinyol/indexstore.py b/src/carquinyol/indexstore.py index 2aa90c3..a612950 100644 --- a/src/carquinyol/indexstore.py +++ b/src/carquinyol/indexstore.py @@ -21,11 +21,13 @@ import gobject import xapian from xapian import WritableDatabase, Document, Enquire, Query, QueryParser +import sugar.datastore + from carquinyol import layoutmanager from carquinyol.layoutmanager import MAX_QUERY_LIMIT _VALUE_TID = 0 -_VALUE_TIMESTAMP = 1 +_VALUE_CTIME = 1 _VALUE_VID = 2 _PREFIX_TID = 'Q' @@ -41,7 +43,7 @@ _FLUSH_THRESHOLD = 20 # Force a flush after _n_ seconds since the last change to the db _FLUSH_TIMEOUT = 60 -_PROPERTIES_NOT_TO_INDEX = ['timestamp', 'activity_id', 'keep', 'preview'] +_PROPERTIES_NOT_TO_INDEX = ['ctime', 'activity_id', 'keep', 'preview'] _MAX_RESULTS = int(2 ** 31 - 1) @@ -89,7 +91,7 @@ class IndexStore(object): document.add_value(_VALUE_TID, tree_id) document.add_value(_VALUE_VID, version_id) - document.add_value(_VALUE_TIMESTAMP, str(properties['timestamp'])) + document.add_value(_VALUE_CTIME, str(properties['ctime'])) term_generator = xapian.TermGenerator() @@ -139,7 +141,7 @@ class IndexStore(object): # This will assure that the results count is exact. check_at_least = offset + limit + 1 - enquire.set_sort_by_value(_VALUE_TIMESTAMP, True) + enquire.set_sort_by_value(_VALUE_CTIME, True) if not all_versions : # only select newest entry (sort order) for each tree_id @@ -161,6 +163,43 @@ class IndexStore(object): 'activity_id': _PREFIX_ACTIVITY_ID, 'keep': _PREFIX_KEEP, } + _queryValueMap = { + 'ctime': _VALUE_CTIME, + } + def _parse_query_term(self, m_name, prefix, m_value) : + if isinstance(m_value, list) : + # list -> multiple terms joined by OR + return Query(Query.OP_OR, + [self._parse_query_term(m_name, prefix, word) for word in m_value]) + + else : + # simple query on regular term + return Query(prefix+str(m_value)) + + def _parse_query_value(self, m_name, value_no, m_value) : + if isinstance(m_value, list) : + # list -> multiple values joined by OR + return Query(Query.OP_OR, + [self._parse_query_value(m_name, value_no, word) for word in m_value]) + + elif isinstance(m_value, tuple) : + # 2-tuple -> range query + if m_name not in self._valueQueryMap : + raise NotImplementedError("range queries for %r currently not supported") + + if len(m_value) != 2 : + raise sugar.datastore.InvalidArgumentError("Only tuples of size 2 have a defined meaning. Did you mean to pass a list instead?") + + start, end = m_value + return Query(Query.OP_VALUE_RANGE, + self._queryValueMap[m_name], str(start), str(end)) + + else : + # simple query on value-stored metadata + return Query(Query.OP_VALUE_RANGE, + self._queryValueMap[m_name], str(m_value), str(m_value)) + + def _parse_query(self, query_dict, query_str): logging.debug('_parse_query %r' % query_dict) queries = [] @@ -184,32 +223,24 @@ class IndexStore(object): queries.append(query) - # metadata -> term for simple datatypes (string, bool) - for (m_name, term_prefix) in self._queryTermMap.items() : - m_value = query_dict.pop(m_name, None) - if m_value is not None: - queries.append(Query(term_prefix+str(m_value))) - - timestamp = query_dict.pop('timestamp', None) - if timestamp is not None: - start = str(timestamp.pop('start', 0)) - end = str(timestamp.pop('end', _MAX_RESULTS)) - query = Query(Query.OP_VALUE_RANGE, _VALUE_TIMESTAMP, start, end) - queries.append(query) + # construct queries for term-stored metadata + queries += [ + self._parse_query_term(m_name, prefix, query_dict.pop(m_name)) + for (m_name, prefix) in self._queryTermMap.items() + if m_name in query_dict] - mime_type = query_dict.pop('mime_type', None) - if mime_type is not None: - mime_queries = [] - for mime_type in mime_type: - mime_queries.append(Query(_PREFIX_MIME_TYPE + mime_type)) - queries.append(Query(Query.OP_OR, mime_queries)) + # construct queries for value-stored metadata + queries += [ + self._parse_query_value(m_name, value_no, query_dict.pop(m_name)) + for (m_name, value_no) in self._queryValueMap.items() + if m_name in query_dict] if not queries: queries.append(Query('')) if query_dict: logging.warning('Unknown term(s): %r' % query_dict) - + return Query(Query.OP_AND, queries) def delete(self, tree_id, version_id): |