00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "tsearch/ts_utils.h"
00018
00019 Datum
00020 tsquery_numnode(PG_FUNCTION_ARGS)
00021 {
00022 TSQuery query = PG_GETARG_TSQUERY(0);
00023 int nnode = query->size;
00024
00025 PG_FREE_IF_COPY(query, 0);
00026 PG_RETURN_INT32(nnode);
00027 }
00028
00029 static QTNode *
00030 join_tsqueries(TSQuery a, TSQuery b, int8 operator)
00031 {
00032 QTNode *res = (QTNode *) palloc0(sizeof(QTNode));
00033
00034 res->flags |= QTN_NEEDFREE;
00035
00036 res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
00037 res->valnode->type = QI_OPR;
00038 res->valnode->qoperator.oper = operator;
00039
00040 res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
00041 res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
00042 res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
00043 res->nchild = 2;
00044
00045 return res;
00046 }
00047
00048 Datum
00049 tsquery_and(PG_FUNCTION_ARGS)
00050 {
00051 TSQuery a = PG_GETARG_TSQUERY_COPY(0);
00052 TSQuery b = PG_GETARG_TSQUERY_COPY(1);
00053 QTNode *res;
00054 TSQuery query;
00055
00056 if (a->size == 0)
00057 {
00058 PG_FREE_IF_COPY(a, 1);
00059 PG_RETURN_POINTER(b);
00060 }
00061 else if (b->size == 0)
00062 {
00063 PG_FREE_IF_COPY(b, 1);
00064 PG_RETURN_POINTER(a);
00065 }
00066
00067 res = join_tsqueries(a, b, OP_AND);
00068
00069 query = QTN2QT(res);
00070
00071 QTNFree(res);
00072 PG_FREE_IF_COPY(a, 0);
00073 PG_FREE_IF_COPY(b, 1);
00074
00075 PG_RETURN_TSQUERY(query);
00076 }
00077
00078 Datum
00079 tsquery_or(PG_FUNCTION_ARGS)
00080 {
00081 TSQuery a = PG_GETARG_TSQUERY_COPY(0);
00082 TSQuery b = PG_GETARG_TSQUERY_COPY(1);
00083 QTNode *res;
00084 TSQuery query;
00085
00086 if (a->size == 0)
00087 {
00088 PG_FREE_IF_COPY(a, 1);
00089 PG_RETURN_POINTER(b);
00090 }
00091 else if (b->size == 0)
00092 {
00093 PG_FREE_IF_COPY(b, 1);
00094 PG_RETURN_POINTER(a);
00095 }
00096
00097 res = join_tsqueries(a, b, OP_OR);
00098
00099 query = QTN2QT(res);
00100
00101 QTNFree(res);
00102 PG_FREE_IF_COPY(a, 0);
00103 PG_FREE_IF_COPY(b, 1);
00104
00105 PG_RETURN_POINTER(query);
00106 }
00107
00108 Datum
00109 tsquery_not(PG_FUNCTION_ARGS)
00110 {
00111 TSQuery a = PG_GETARG_TSQUERY_COPY(0);
00112 QTNode *res;
00113 TSQuery query;
00114
00115 if (a->size == 0)
00116 PG_RETURN_POINTER(a);
00117
00118 res = (QTNode *) palloc0(sizeof(QTNode));
00119
00120 res->flags |= QTN_NEEDFREE;
00121
00122 res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
00123 res->valnode->type = QI_OPR;
00124 res->valnode->qoperator.oper = OP_NOT;
00125
00126 res->child = (QTNode **) palloc0(sizeof(QTNode *));
00127 res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
00128 res->nchild = 1;
00129
00130 query = QTN2QT(res);
00131
00132 QTNFree(res);
00133 PG_FREE_IF_COPY(a, 0);
00134
00135 PG_RETURN_POINTER(query);
00136 }
00137
00138 static int
00139 CompareTSQ(TSQuery a, TSQuery b)
00140 {
00141 if (a->size != b->size)
00142 {
00143 return (a->size < b->size) ? -1 : 1;
00144 }
00145 else if (VARSIZE(a) != VARSIZE(b))
00146 {
00147 return (VARSIZE(a) < VARSIZE(b)) ? -1 : 1;
00148 }
00149 else if (a->size != 0)
00150 {
00151 QTNode *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
00152 QTNode *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
00153 int res = QTNodeCompare(an, bn);
00154
00155 QTNFree(an);
00156 QTNFree(bn);
00157
00158 return res;
00159 }
00160
00161 return 0;
00162 }
00163
00164 Datum
00165 tsquery_cmp(PG_FUNCTION_ARGS)
00166 {
00167 TSQuery a = PG_GETARG_TSQUERY_COPY(0);
00168 TSQuery b = PG_GETARG_TSQUERY_COPY(1);
00169 int res = CompareTSQ(a, b);
00170
00171 PG_FREE_IF_COPY(a, 0);
00172 PG_FREE_IF_COPY(b, 1);
00173
00174 PG_RETURN_INT32(res);
00175 }
00176
00177 #define CMPFUNC( NAME, CONDITION ) \
00178 Datum \
00179 NAME(PG_FUNCTION_ARGS) { \
00180 TSQuery a = PG_GETARG_TSQUERY_COPY(0); \
00181 TSQuery b = PG_GETARG_TSQUERY_COPY(1); \
00182 int res = CompareTSQ(a,b); \
00183 \
00184 PG_FREE_IF_COPY(a,0); \
00185 PG_FREE_IF_COPY(b,1); \
00186 \
00187 PG_RETURN_BOOL( CONDITION ); \
00188 } \
00189 \
00190 extern int no_such_variable
00191
00192 CMPFUNC(tsquery_lt, res < 0);
00193 CMPFUNC(tsquery_le, res <= 0);
00194 CMPFUNC(tsquery_eq, res == 0);
00195 CMPFUNC(tsquery_ge, res >= 0);
00196 CMPFUNC(tsquery_gt, res > 0);
00197 CMPFUNC(tsquery_ne, res != 0);
00198
00199 TSQuerySign
00200 makeTSQuerySign(TSQuery a)
00201 {
00202 int i;
00203 QueryItem *ptr = GETQUERY(a);
00204 TSQuerySign sign = 0;
00205
00206 for (i = 0; i < a->size; i++)
00207 {
00208 if (ptr->type == QI_VAL)
00209 sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
00210 ptr++;
00211 }
00212
00213 return sign;
00214 }
00215
00216 Datum
00217 tsq_mcontains(PG_FUNCTION_ARGS)
00218 {
00219 TSQuery query = PG_GETARG_TSQUERY(0);
00220 TSQuery ex = PG_GETARG_TSQUERY(1);
00221 TSQuerySign sq,
00222 se;
00223 int i,
00224 j;
00225 QueryItem *iq,
00226 *ie;
00227
00228 if (query->size < ex->size)
00229 {
00230 PG_FREE_IF_COPY(query, 0);
00231 PG_FREE_IF_COPY(ex, 1);
00232
00233 PG_RETURN_BOOL(false);
00234 }
00235
00236 sq = makeTSQuerySign(query);
00237 se = makeTSQuerySign(ex);
00238
00239 if ((sq & se) != se)
00240 {
00241 PG_FREE_IF_COPY(query, 0);
00242 PG_FREE_IF_COPY(ex, 1);
00243
00244 PG_RETURN_BOOL(false);
00245 }
00246
00247 iq = GETQUERY(query);
00248 ie = GETQUERY(ex);
00249
00250 for (i = 0; i < ex->size; i++)
00251 {
00252 if (ie[i].type != QI_VAL)
00253 continue;
00254 for (j = 0; j < query->size; j++)
00255 {
00256 if (iq[j].type == QI_VAL &&
00257 ie[i].qoperand.valcrc == iq[j].qoperand.valcrc)
00258 break;
00259 }
00260 if (j >= query->size)
00261 {
00262 PG_FREE_IF_COPY(query, 0);
00263 PG_FREE_IF_COPY(ex, 1);
00264
00265 PG_RETURN_BOOL(false);
00266 }
00267 }
00268
00269 PG_FREE_IF_COPY(query, 0);
00270 PG_FREE_IF_COPY(ex, 1);
00271
00272 PG_RETURN_BOOL(true);
00273 }
00274
00275 Datum
00276 tsq_mcontained(PG_FUNCTION_ARGS)
00277 {
00278 PG_RETURN_DATUM(
00279 DirectFunctionCall2(
00280 tsq_mcontains,
00281 PG_GETARG_DATUM(1),
00282 PG_GETARG_DATUM(0)
00283 )
00284 );
00285 }