return sign;
}
-Datum
-tsq_mcontains(PG_FUNCTION_ARGS)
+static char **
+collectTSQueryValues(TSQuery a, int *nvalues_p)
{
- TSQuery query = PG_GETARG_TSQUERY(0);
- TSQuery ex = PG_GETARG_TSQUERY(1);
- TSQuerySign sq,
- se;
- int i,
- j;
- QueryItem *iq,
- *ie;
-
- if (query->size < ex->size)
+ QueryItem *ptr = GETQUERY(a);
+ char *operand = GETOPERAND(a);
+ char **values;
+ int nvalues = 0;
+ int i;
+
+ values = (char **) palloc(sizeof(char *) * a->size);
+
+ for (i = 0; i < a->size; i++)
{
- PG_FREE_IF_COPY(query, 0);
- PG_FREE_IF_COPY(ex, 1);
+ if (ptr->type == QI_VAL)
+ {
+ int len = ptr->qoperand.length;
+ char *val;
+
+ val = palloc(len + 1);
+ memcpy(val, operand + ptr->qoperand.distance, len);
+ val[len] = '\0';
- PG_RETURN_BOOL(false);
+ values[nvalues++] = val;
+ }
+ ptr++;
}
- sq = makeTSQuerySign(query);
- se = makeTSQuerySign(ex);
+ *nvalues_p = nvalues;
+ return values;
+}
+
+static int
+cmp_string(const void *a, const void *b)
+{
+ const char *sa = *((const char **) a);
+ const char *sb = *((const char **) b);
+ return strcmp(sa, sb);
+}
- if ((sq & se) != se)
+static int
+remove_duplicates(char **strings, int n)
+{
+ if (n <= 1)
+ return n;
+ else
{
- PG_FREE_IF_COPY(query, 0);
- PG_FREE_IF_COPY(ex, 1);
+ int i;
+ char *prev = strings[0];
+ int new_n = 1;
- PG_RETURN_BOOL(false);
+ for (i = 1; i < n; i++)
+ {
+ if (strcmp(strings[i], prev) != 0)
+ {
+ strings[new_n++] = strings[i];
+ prev = strings[i];
+ }
+ }
+ return new_n;
}
+}
- iq = GETQUERY(query);
- ie = GETQUERY(ex);
-
- for (i = 0; i < ex->size; i++)
+Datum
+tsq_mcontains(PG_FUNCTION_ARGS)
+{
+ TSQuery query = PG_GETARG_TSQUERY(0);
+ TSQuery ex = PG_GETARG_TSQUERY(1);
+ char **query_values;
+ int query_nvalues;
+ char **ex_values;
+ int ex_nvalues;
+ bool result = true;
+
+ /* Extract the query terms into arrays */
+ query_values = collectTSQueryValues(query, &query_nvalues);
+ ex_values = collectTSQueryValues(ex, &ex_nvalues);
+
+ /* Sort and remove duplicates from both arrays */
+ qsort(query_values, query_nvalues, sizeof(char *), cmp_string);
+ query_nvalues = remove_duplicates(query_values, query_nvalues);
+ qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string);
+ ex_nvalues = remove_duplicates(ex_values, ex_nvalues);
+
+ if (ex_nvalues > query_nvalues)
+ result = false;
+ else
{
- if (ie[i].type != QI_VAL)
- continue;
- for (j = 0; j < query->size; j++)
+ int i;
+ int j = 0;
+
+ for (i = 0; i < ex_nvalues; i++)
{
- if (iq[j].type == QI_VAL &&
- ie[i].qoperand.valcrc == iq[j].qoperand.valcrc)
+ for (; j < query_nvalues; j++)
+ {
+ if (strcmp(ex_values[i], query_values[j]) == 0)
+ break;
+ }
+ if (j == query_nvalues)
+ {
+ result = false;
break;
- }
- if (j >= query->size)
- {
- PG_FREE_IF_COPY(query, 0);
- PG_FREE_IF_COPY(ex, 1);
-
- PG_RETURN_BOOL(false);
+ }
}
}
- PG_FREE_IF_COPY(query, 0);
- PG_FREE_IF_COPY(ex, 1);
-
- PG_RETURN_BOOL(true);
+ PG_RETURN_BOOL(result);
}
Datum