@@ -216,63 +216,112 @@ makeTSQuerySign(TSQuery a)
216216 return sign ;
217217}
218218
219- Datum
220- tsq_mcontains ( PG_FUNCTION_ARGS )
219+ static char * *
220+ collectTSQueryValues ( TSQuery a , int * nvalues_p )
221221{
222- TSQuery query = PG_GETARG_TSQUERY (0 );
223- TSQuery ex = PG_GETARG_TSQUERY (1 );
224- TSQuerySign sq ,
225- se ;
226- int i ,
227- j ;
228- QueryItem * iq ,
229- * ie ;
230-
231- if (query -> size < ex -> size )
222+ QueryItem * ptr = GETQUERY (a );
223+ char * operand = GETOPERAND (a );
224+ char * * values ;
225+ int nvalues = 0 ;
226+ int i ;
227+
228+ values = (char * * ) palloc (sizeof (char * ) * a -> size );
229+
230+ for (i = 0 ; i < a -> size ; i ++ )
232231 {
233- PG_FREE_IF_COPY (query , 0 );
234- PG_FREE_IF_COPY (ex , 1 );
232+ if (ptr -> type == QI_VAL )
233+ {
234+ int len = ptr -> qoperand .length ;
235+ char * val ;
236+
237+ val = palloc (len + 1 );
238+ memcpy (val , operand + ptr -> qoperand .distance , len );
239+ val [len ] = '\0' ;
235240
236- PG_RETURN_BOOL (false);
241+ values [nvalues ++ ] = val ;
242+ }
243+ ptr ++ ;
237244 }
238245
239- sq = makeTSQuerySign (query );
240- se = makeTSQuerySign (ex );
246+ * nvalues_p = nvalues ;
247+ return values ;
248+ }
249+
250+ static int
251+ cmp_string (const void * a , const void * b )
252+ {
253+ const char * sa = * ((const char * * ) a );
254+ const char * sb = * ((const char * * ) b );
255+ return strcmp (sa , sb );
256+ }
241257
242- if ((sq & se ) != se )
258+ static int
259+ remove_duplicates (char * * strings , int n )
260+ {
261+ if (n <= 1 )
262+ return n ;
263+ else
243264 {
244- PG_FREE_IF_COPY (query , 0 );
245- PG_FREE_IF_COPY (ex , 1 );
265+ int i ;
266+ char * prev = strings [0 ];
267+ int new_n = 1 ;
246268
247- PG_RETURN_BOOL (false);
269+ for (i = 1 ; i < n ; i ++ )
270+ {
271+ if (strcmp (strings [i ], prev ) != 0 )
272+ {
273+ strings [new_n ++ ] = strings [i ];
274+ prev = strings [i ];
275+ }
276+ }
277+ return new_n ;
248278 }
279+ }
249280
250- iq = GETQUERY (query );
251- ie = GETQUERY (ex );
252-
253- for (i = 0 ; i < ex -> size ; i ++ )
281+ Datum
282+ tsq_mcontains (PG_FUNCTION_ARGS )
283+ {
284+ TSQuery query = PG_GETARG_TSQUERY (0 );
285+ TSQuery ex = PG_GETARG_TSQUERY (1 );
286+ char * * query_values ;
287+ int query_nvalues ;
288+ char * * ex_values ;
289+ int ex_nvalues ;
290+ bool result = true;
291+
292+ /* Extract the query terms into arrays */
293+ query_values = collectTSQueryValues (query , & query_nvalues );
294+ ex_values = collectTSQueryValues (ex , & ex_nvalues );
295+
296+ /* Sort and remove duplicates from both arrays */
297+ qsort (query_values , query_nvalues , sizeof (char * ), cmp_string );
298+ query_nvalues = remove_duplicates (query_values , query_nvalues );
299+ qsort (ex_values , ex_nvalues , sizeof (char * ), cmp_string );
300+ ex_nvalues = remove_duplicates (ex_values , ex_nvalues );
301+
302+ if (ex_nvalues > query_nvalues )
303+ result = false;
304+ else
254305 {
255- if (ie [i ].type != QI_VAL )
256- continue ;
257- for (j = 0 ; j < query -> size ; j ++ )
306+ int i ;
307+ int j = 0 ;
308+
309+ for (i = 0 ; i < ex_nvalues ; i ++ )
258310 {
259- if (iq [j ].type == QI_VAL &&
260- ie [i ].qoperand .valcrc == iq [j ].qoperand .valcrc )
311+ for (; j < query_nvalues ; j ++ )
312+ {
313+ if (strcmp (ex_values [i ], query_values [j ]) == 0 )
314+ break ;
315+ }
316+ if (j == query_nvalues )
317+ {
318+ result = false;
261319 break ;
262- }
263- if (j >= query -> size )
264- {
265- PG_FREE_IF_COPY (query , 0 );
266- PG_FREE_IF_COPY (ex , 1 );
267-
268- PG_RETURN_BOOL (false);
320+ }
269321 }
270322 }
271323
272- PG_FREE_IF_COPY (query , 0 );
273- PG_FREE_IF_COPY (ex , 1 );
274-
275- PG_RETURN_BOOL (true);
324+ PG_RETURN_BOOL (result );
276325}
277326
278327Datum
0 commit comments