99from roundup .backends import back_postgresql , tsearch2_setup , indexer_rdbms
1010from roundup .backends .back_postgresql import db_create , db_nuke , db_command
1111from roundup .backends .back_postgresql import pg_command , db_exists , Class , IssueClass , FileClass
12+ from roundup .backends .indexer_common import _isLink , Indexer
1213
1314# XXX: Should probably be on the Class class.
1415def _indexedProps (spec ):
@@ -24,10 +25,6 @@ def _getQueryDict(spec):
2425 query_dict ['triggername' ] = "%(tablename)s_tsvectorupdate" % query_dict
2526 return query_dict
2627
27- def _isLink (propclass ):
28- return (isinstance (propclass , hyperdb .Link ) or
29- isinstance (propclass , hyperdb .Multilink ))
30-
3128class Database (back_postgresql .Database ):
3229 def __init__ (self , config , journaltag = None ):
3330 back_postgresql .Database .__init__ (self , config , journaltag )
@@ -86,86 +83,16 @@ def determine_all_columns(self, spec):
8683 cols .append (('idxFTI' , 'tsvector' ))
8784 return cols , mls
8885
89- class Indexer :
86+ class Indexer ( Indexer ) :
9087 def __init__ (self , db ):
9188 self .db = db
9289
93- def force_reindex (self ):
94- pass
95-
90+ # This indexer never needs to reindex.
9691 def should_reindex (self ):
97- pass
98-
99- def save_index (self ):
100- pass
101-
102- def add_text (self , identifier , text , mime_type = None ):
103- pass
104-
105- def close (self ):
106- pass
107-
108- def search (self , search_terms , klass , ignore = {},
109- dre = re .compile (r'([^\d]+)(\d+)' )):
110- '''Display search results looking for [search, terms] associated
111- with the hyperdb Class "klass". Ignore hits on {class: property}.
112-
113- "dre" is a helper, not an argument.
114- '''
115- # do the index lookup
116- hits = self .find (search_terms , klass )
117- if not hits :
118- return {}
92+ return False
11993
120- designator_propname = {}
121- for nm , propclass in klass .getprops ().items ():
122- if (isinstance (propclass , hyperdb .Link )
123- or isinstance (propclass , hyperdb .Multilink )):
124- designator_propname [propclass .classname ] = nm
125-
126- # build a dictionary of nodes and their associated messages
127- # and files
128- nodeids = {} # this is the answer
129- propspec = {} # used to do the klass.find
130- for propname in designator_propname .values ():
131- propspec [propname ] = {} # used as a set (value doesn't matter)
132-
133- for classname , nodeid in hits :
134- # if it's a property on klass, it's easy
135- if classname == klass .classname :
136- if not nodeids .has_key (nodeid ):
137- nodeids [nodeid ] = {}
138- continue
139-
140- # make sure the class is a linked one, otherwise ignore
141- if not designator_propname .has_key (classname ):
142- continue
143-
144- # it's a linked class - set up to do the klass.find
145- linkprop = designator_propname [classname ] # eg, msg -> messages
146- propspec [linkprop ][nodeid ] = 1
147-
148- # retain only the meaningful entries
149- for propname , idset in propspec .items ():
150- if not idset :
151- del propspec [propname ]
152-
153- # klass.find tells me the klass nodeids the linked nodes relate to
154- for resid in klass .find (** propspec ):
155- resid = str (resid )
156- if not nodeids .has_key (id ):
157- nodeids [resid ] = {}
158- node_dict = nodeids [resid ]
159- # now figure out where it came from
160- for linkprop in propspec .keys ():
161- for nodeid in klass .get (resid , linkprop ):
162- if propspec [linkprop ].has_key (nodeid ):
163- # OK, this node[propname] has a winner
164- if not node_dict .has_key (linkprop ):
165- node_dict [linkprop ] = [nodeid ]
166- else :
167- node_dict [linkprop ].append (nodeid )
168- return nodeids
94+ def getHits (self , search_terms , klass ):
95+ return self .find (search_terms , klass )
16996
17097 def find (self , search_terms , klass ):
17198 if not search_terms :
@@ -178,7 +105,7 @@ def find(self, search_terms, klass):
178105 if _isLink (propclass ):
179106 nodeids .extend (self .tsearchQuery (propclass .classname , search_terms ))
180107
181- return nodeids
108+ return dict ( enumerate ( nodeids ))
182109
183110 def tsearchQuery (self , classname , search_terms ):
184111 query = """SELECT id FROM _%(classname)s
@@ -196,8 +123,25 @@ def tsearchQuery(self, classname, search_terms):
196123 if 'type' in klass .getprops ():
197124 nodeids = [nodeid for nodeid in nodeids
198125 if klass .get (nodeid , 'type' ) == 'text/plain' ]
199-
200- return [(classname , nodeid ) for nodeid in nodeids ]
126+
127+ # XXX: We haven't implemented property-level search, so I'm just faking
128+ # it here with a property named 'XXX'. We still need to fix the other
129+ # backends and indexer_common.Indexer.search to only want to unpack two
130+ # values.
131+ return [(classname , nodeid , 'XXX' ) for nodeid in nodeids ]
132+
133+ # These only exist to satisfy the interface that's expected from indexers.
134+ def force_reindex (self ):
135+ pass
136+
137+ def save_index (self ):
138+ pass
139+
140+ def add_text (self , identifier , text , mime_type = None ):
141+ pass
142+
143+ def close (self ):
144+ pass
201145
202146class FileClass (hyperdb .FileClass , Class ):
203147 '''This class defines a large chunk of data. To support this, it has a
0 commit comments