Header And Logo

PostgreSQL
| The world's most advanced open source database.

tsquery_op.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * tsquery_op.c
00004  *    Various operations with tsquery
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  *
00008  *
00009  * IDENTIFICATION
00010  *    src/backend/utils/adt/tsquery_op.c
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 /* keep compiler quiet - no extra ; */          \
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 }