@@ -213,63 +213,112 @@ makeTSQuerySign(TSQuery a)
213213 return sign ;
214214}
215215
216- Datum
217- tsq_mcontains ( PG_FUNCTION_ARGS )
216+ static char * *
217+ collectTSQueryValues ( TSQuery a , int * nvalues_p )
218218{
219- TSQuery query = PG_GETARG_TSQUERY (0 );
220- TSQuery ex = PG_GETARG_TSQUERY (1 );
221- TSQuerySign sq ,
222- se ;
223- int i ,
224- j ;
225- QueryItem * iq ,
226- * ie ;
227-
228- if (query -> size < ex -> size )
219+ QueryItem * ptr = GETQUERY (a );
220+ char * operand = GETOPERAND (a );
221+ char * * values ;
222+ int nvalues = 0 ;
223+ int i ;
224+
225+ values = (char * * ) palloc (sizeof (char * ) * a -> size );
226+
227+ for (i = 0 ; i < a -> size ; i ++ )
229228 {
230- PG_FREE_IF_COPY (query , 0 );
231- PG_FREE_IF_COPY (ex , 1 );
229+ if (ptr -> type == QI_VAL )
230+ {
231+ int len = ptr -> qoperand .length ;
232+ char * val ;
233+
234+ val = palloc (len + 1 );
235+ memcpy (val , operand + ptr -> qoperand .distance , len );
236+ val [len ] = '\0' ;
232237
233- PG_RETURN_BOOL (false);
238+ values [nvalues ++ ] = val ;
239+ }
240+ ptr ++ ;
234241 }
235242
236- sq = makeTSQuerySign (query );
237- se = makeTSQuerySign (ex );
243+ * nvalues_p = nvalues ;
244+ return values ;
245+ }
246+
247+ static int
248+ cmp_string (const void * a , const void * b )
249+ {
250+ const char * sa = * ((const char * * ) a );
251+ const char * sb = * ((const char * * ) b );
252+ return strcmp (sa , sb );
253+ }
238254
239- if ((sq & se ) != se )
255+ static int
256+ remove_duplicates (char * * strings , int n )
257+ {
258+ if (n <= 1 )
259+ return n ;
260+ else
240261 {
241- PG_FREE_IF_COPY (query , 0 );
242- PG_FREE_IF_COPY (ex , 1 );
262+ int i ;
263+ char * prev = strings [0 ];
264+ int new_n = 1 ;
243265
244- PG_RETURN_BOOL (false);
266+ for (i = 1 ; i < n ; i ++ )
267+ {
268+ if (strcmp (strings [i ], prev ) != 0 )
269+ {
270+ strings [new_n ++ ] = strings [i ];
271+ prev = strings [i ];
272+ }
273+ }
274+ return new_n ;
245275 }
276+ }
246277
247- iq = GETQUERY (query );
248- ie = GETQUERY (ex );
249-
250- for (i = 0 ; i < ex -> size ; i ++ )
278+ Datum
279+ tsq_mcontains (PG_FUNCTION_ARGS )
280+ {
281+ TSQuery query = PG_GETARG_TSQUERY (0 );
282+ TSQuery ex = PG_GETARG_TSQUERY (1 );
283+ char * * query_values ;
284+ int query_nvalues ;
285+ char * * ex_values ;
286+ int ex_nvalues ;
287+ bool result = true;
288+
289+ /* Extract the query terms into arrays */
290+ query_values = collectTSQueryValues (query , & query_nvalues );
291+ ex_values = collectTSQueryValues (ex , & ex_nvalues );
292+
293+ /* Sort and remove duplicates from both arrays */
294+ qsort (query_values , query_nvalues , sizeof (char * ), cmp_string );
295+ query_nvalues = remove_duplicates (query_values , query_nvalues );
296+ qsort (ex_values , ex_nvalues , sizeof (char * ), cmp_string );
297+ ex_nvalues = remove_duplicates (ex_values , ex_nvalues );
298+
299+ if (ex_nvalues > query_nvalues )
300+ result = false;
301+ else
251302 {
252- if (ie [i ].type != QI_VAL )
253- continue ;
254- for (j = 0 ; j < query -> size ; j ++ )
303+ int i ;
304+ int j = 0 ;
305+
306+ for (i = 0 ; i < ex_nvalues ; i ++ )
255307 {
256- if (iq [j ].type == QI_VAL &&
257- ie [i ].qoperand .valcrc == iq [j ].qoperand .valcrc )
308+ for (; j < query_nvalues ; j ++ )
309+ {
310+ if (strcmp (ex_values [i ], query_values [j ]) == 0 )
311+ break ;
312+ }
313+ if (j == query_nvalues )
314+ {
315+ result = false;
258316 break ;
259- }
260- if (j >= query -> size )
261- {
262- PG_FREE_IF_COPY (query , 0 );
263- PG_FREE_IF_COPY (ex , 1 );
264-
265- PG_RETURN_BOOL (false);
317+ }
266318 }
267319 }
268320
269- PG_FREE_IF_COPY (query , 0 );
270- PG_FREE_IF_COPY (ex , 1 );
271-
272- PG_RETURN_BOOL (true);
321+ PG_RETURN_BOOL (result );
273322}
274323
275324Datum
0 commit comments