LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - tsquery_op.c (source / functions) Coverage Total Hit LBC UIC UBC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 90.0 % 160 144 3 7 6 95 1 48 10 93
Current Date: 2023-04-08 15:15:32 Functions: 95.0 % 20 19 1 19 1 19
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * tsquery_op.c
       4                 :  *    Various operations with tsquery
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  *
       8                 :  *
       9                 :  * IDENTIFICATION
      10                 :  *    src/backend/utils/adt/tsquery_op.c
      11                 :  *
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : 
      15                 : #include "postgres.h"
      16                 : 
      17                 : #include "lib/qunique.h"
      18                 : #include "tsearch/ts_utils.h"
      19                 : #include "utils/builtins.h"
      20                 : #include "varatt.h"
      21                 : 
      22                 : Datum
      23 GIC           9 : tsquery_numnode(PG_FUNCTION_ARGS)
      24 ECB             : {
      25 GIC           9 :     TSQuery     query = PG_GETARG_TSQUERY(0);
      26 CBC           9 :     int         nnode = query->size;
      27 ECB             : 
      28 GIC           9 :     PG_FREE_IF_COPY(query, 0);
      29 CBC           9 :     PG_RETURN_INT32(nnode);
      30 ECB             : }
      31                 : 
      32                 : static QTNode *
      33 GIC          54 : join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
      34 ECB             : {
      35 GIC          54 :     QTNode     *res = (QTNode *) palloc0(sizeof(QTNode));
      36 ECB             : 
      37 GIC          54 :     res->flags |= QTN_NEEDFREE;
      38 ECB             : 
      39 GIC          54 :     res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
      40 CBC          54 :     res->valnode->type = QI_OPR;
      41              54 :     res->valnode->qoperator.oper = operator;
      42              54 :     if (operator == OP_PHRASE)
      43              24 :         res->valnode->qoperator.distance = distance;
      44 ECB             : 
      45 GIC          54 :     res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
      46 CBC          54 :     res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
      47              54 :     res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
      48              54 :     res->nchild = 2;
      49 ECB             : 
      50 GIC          54 :     return res;
      51 ECB             : }
      52                 : 
      53                 : Datum
      54 GIC          18 : tsquery_and(PG_FUNCTION_ARGS)
      55 ECB             : {
      56 GIC          18 :     TSQuery     a = PG_GETARG_TSQUERY_COPY(0);
      57 CBC          18 :     TSQuery     b = PG_GETARG_TSQUERY_COPY(1);
      58 ECB             :     QTNode     *res;
      59                 :     TSQuery     query;
      60                 : 
      61 GIC          18 :     if (a->size == 0)
      62 ECB             :     {
      63 UIC           0 :         PG_FREE_IF_COPY(a, 1);
      64 UBC           0 :         PG_RETURN_POINTER(b);
      65 EUB             :     }
      66 GIC          18 :     else if (b->size == 0)
      67 ECB             :     {
      68 UIC           0 :         PG_FREE_IF_COPY(b, 1);
      69 UBC           0 :         PG_RETURN_POINTER(a);
      70 EUB             :     }
      71                 : 
      72 GIC          18 :     res = join_tsqueries(a, b, OP_AND, 0);
      73 ECB             : 
      74 GIC          18 :     query = QTN2QT(res);
      75 ECB             : 
      76 GIC          18 :     QTNFree(res);
      77 CBC          18 :     PG_FREE_IF_COPY(a, 0);
      78              18 :     PG_FREE_IF_COPY(b, 1);
      79 ECB             : 
      80 GIC          18 :     PG_RETURN_TSQUERY(query);
      81 ECB             : }
      82                 : 
      83                 : Datum
      84 GIC          12 : tsquery_or(PG_FUNCTION_ARGS)
      85 ECB             : {
      86 GIC          12 :     TSQuery     a = PG_GETARG_TSQUERY_COPY(0);
      87 CBC          12 :     TSQuery     b = PG_GETARG_TSQUERY_COPY(1);
      88 ECB             :     QTNode     *res;
      89                 :     TSQuery     query;
      90                 : 
      91 GIC          12 :     if (a->size == 0)
      92 ECB             :     {
      93 UIC           0 :         PG_FREE_IF_COPY(a, 1);
      94 UBC           0 :         PG_RETURN_POINTER(b);
      95 EUB             :     }
      96 GIC          12 :     else if (b->size == 0)
      97 ECB             :     {
      98 UIC           0 :         PG_FREE_IF_COPY(b, 1);
      99 UBC           0 :         PG_RETURN_POINTER(a);
     100 EUB             :     }
     101                 : 
     102 GIC          12 :     res = join_tsqueries(a, b, OP_OR, 0);
     103 ECB             : 
     104 GIC          12 :     query = QTN2QT(res);
     105 ECB             : 
     106 GIC          12 :     QTNFree(res);
     107 CBC          12 :     PG_FREE_IF_COPY(a, 0);
     108              12 :     PG_FREE_IF_COPY(b, 1);
     109 ECB             : 
     110 GIC          12 :     PG_RETURN_TSQUERY(query);
     111 ECB             : }
     112                 : 
     113                 : Datum
     114 GIC          24 : tsquery_phrase_distance(PG_FUNCTION_ARGS)
     115 ECB             : {
     116 GIC          24 :     TSQuery     a = PG_GETARG_TSQUERY_COPY(0);
     117 CBC          24 :     TSQuery     b = PG_GETARG_TSQUERY_COPY(1);
     118 ECB             :     QTNode     *res;
     119                 :     TSQuery     query;
     120 GIC          24 :     int32       distance = PG_GETARG_INT32(2);
     121 ECB             : 
     122 GIC          24 :     if (distance < 0 || distance > MAXENTRYPOS)
     123 LBC           0 :         ereport(ERROR,
     124 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     125                 :                  errmsg("distance in phrase operator must be an integer value between zero and %d inclusive",
     126                 :                         MAXENTRYPOS)));
     127 GIC          24 :     if (a->size == 0)
     128 ECB             :     {
     129 UIC           0 :         PG_FREE_IF_COPY(a, 1);
     130 UBC           0 :         PG_RETURN_POINTER(b);
     131 EUB             :     }
     132 GIC          24 :     else if (b->size == 0)
     133 ECB             :     {
     134 UIC           0 :         PG_FREE_IF_COPY(b, 1);
     135 UBC           0 :         PG_RETURN_POINTER(a);
     136 EUB             :     }
     137                 : 
     138 GIC          24 :     res = join_tsqueries(a, b, OP_PHRASE, (uint16) distance);
     139 ECB             : 
     140 GIC          24 :     query = QTN2QT(res);
     141 ECB             : 
     142 GIC          24 :     QTNFree(res);
     143 CBC          24 :     PG_FREE_IF_COPY(a, 0);
     144              24 :     PG_FREE_IF_COPY(b, 1);
     145 ECB             : 
     146 GIC          24 :     PG_RETURN_TSQUERY(query);
     147 ECB             : }
     148                 : 
     149                 : Datum
     150 GIC          21 : tsquery_phrase(PG_FUNCTION_ARGS)
     151 ECB             : {
     152 GNC          21 :     PG_RETURN_DATUM(DirectFunctionCall3(tsquery_phrase_distance,
     153 ECB             :                                           PG_GETARG_DATUM(0),
     154                 :                                           PG_GETARG_DATUM(1),
     155                 :                                           Int32GetDatum(1)));
     156                 : }
     157                 : 
     158                 : Datum
     159 GIC           6 : tsquery_not(PG_FUNCTION_ARGS)
     160 ECB             : {
     161 GIC           6 :     TSQuery     a = PG_GETARG_TSQUERY_COPY(0);
     162 ECB             :     QTNode     *res;
     163                 :     TSQuery     query;
     164                 : 
     165 GIC           6 :     if (a->size == 0)
     166 LBC           0 :         PG_RETURN_POINTER(a);
     167 EUB             : 
     168 GIC           6 :     res = (QTNode *) palloc0(sizeof(QTNode));
     169 ECB             : 
     170 GIC           6 :     res->flags |= QTN_NEEDFREE;
     171 ECB             : 
     172 GIC           6 :     res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
     173 CBC           6 :     res->valnode->type = QI_OPR;
     174               6 :     res->valnode->qoperator.oper = OP_NOT;
     175 ECB             : 
     176 GIC           6 :     res->child = (QTNode **) palloc0(sizeof(QTNode *));
     177 CBC           6 :     res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
     178               6 :     res->nchild = 1;
     179 ECB             : 
     180 GIC           6 :     query = QTN2QT(res);
     181 ECB             : 
     182 GIC           6 :     QTNFree(res);
     183 CBC           6 :     PG_FREE_IF_COPY(a, 0);
     184 ECB             : 
     185 GIC           6 :     PG_RETURN_POINTER(query);
     186 ECB             : }
     187                 : 
     188                 : static int
     189 GIC         211 : CompareTSQ(TSQuery a, TSQuery b)
     190 ECB             : {
     191 GIC         211 :     if (a->size != b->size)
     192 ECB             :     {
     193 GIC          90 :         return (a->size < b->size) ? -1 : 1;
     194 ECB             :     }
     195 GIC         121 :     else if (VARSIZE(a) != VARSIZE(b))
     196 ECB             :     {
     197 GIC          81 :         return (VARSIZE(a) < VARSIZE(b)) ? -1 : 1;
     198 ECB             :     }
     199 GIC          40 :     else if (a->size != 0)
     200 ECB             :     {
     201 GIC          40 :         QTNode     *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
     202 CBC          40 :         QTNode     *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
     203              40 :         int         res = QTNodeCompare(an, bn);
     204 ECB             : 
     205 GIC          40 :         QTNFree(an);
     206 CBC          40 :         QTNFree(bn);
     207 ECB             : 
     208 GIC          40 :         return res;
     209 ECB             :     }
     210                 : 
     211 UIC           0 :     return 0;
     212 EUB             : }
     213                 : 
     214                 : Datum
     215 GIC          57 : tsquery_cmp(PG_FUNCTION_ARGS)
     216 ECB             : {
     217 GIC          57 :     TSQuery     a = PG_GETARG_TSQUERY_COPY(0);
     218 CBC          57 :     TSQuery     b = PG_GETARG_TSQUERY_COPY(1);
     219              57 :     int         res = CompareTSQ(a, b);
     220 ECB             : 
     221 GIC          57 :     PG_FREE_IF_COPY(a, 0);
     222 CBC          57 :     PG_FREE_IF_COPY(b, 1);
     223 ECB             : 
     224 GIC          57 :     PG_RETURN_INT32(res);
     225 ECB             : }
     226                 : 
     227                 : #define CMPFUNC( NAME, CONDITION )              \
     228                 : Datum                                           \
     229                 : NAME(PG_FUNCTION_ARGS) {                        \
     230                 :     TSQuery  a = PG_GETARG_TSQUERY_COPY(0);     \
     231                 :     TSQuery  b = PG_GETARG_TSQUERY_COPY(1);     \
     232                 :     int res = CompareTSQ(a,b);                  \
     233                 :                                                 \
     234                 :     PG_FREE_IF_COPY(a,0);                       \
     235                 :     PG_FREE_IF_COPY(b,1);                       \
     236                 :                                                 \
     237                 :     PG_RETURN_BOOL( CONDITION );                \
     238                 : }   \
     239                 : /* keep compiler quiet - no extra ; */          \
     240                 : extern int no_such_variable
     241                 : 
     242 GIC          39 : CMPFUNC(tsquery_lt, res < 0);
     243 CBC          30 : CMPFUNC(tsquery_le, res <= 0);
     244              25 : CMPFUNC(tsquery_eq, res == 0);
     245              30 : CMPFUNC(tsquery_ge, res >= 0);
     246              30 : CMPFUNC(tsquery_gt, res > 0);
     247 LBC           0 : CMPFUNC(tsquery_ne, res != 0);
     248 EUB             : 
     249                 : TSQuerySign
     250 GIC          90 : makeTSQuerySign(TSQuery a)
     251 ECB             : {
     252                 :     int         i;
     253 GIC          90 :     QueryItem  *ptr = GETQUERY(a);
     254 CBC          90 :     TSQuerySign sign = 0;
     255 ECB             : 
     256 GIC         222 :     for (i = 0; i < a->size; i++)
     257 ECB             :     {
     258 GIC         132 :         if (ptr->type == QI_VAL)
     259 CBC         111 :             sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
     260             132 :         ptr++;
     261 ECB             :     }
     262                 : 
     263 GIC          90 :     return sign;
     264 ECB             : }
     265                 : 
     266                 : static char **
     267 GIC         162 : collectTSQueryValues(TSQuery a, int *nvalues_p)
     268 ECB             : {
     269 GIC         162 :     QueryItem  *ptr = GETQUERY(a);
     270 CBC         162 :     char       *operand = GETOPERAND(a);
     271 ECB             :     char      **values;
     272 GIC         162 :     int         nvalues = 0;
     273 ECB             :     int         i;
     274                 : 
     275 GIC         162 :     values = (char **) palloc(sizeof(char *) * a->size);
     276 ECB             : 
     277 GIC         498 :     for (i = 0; i < a->size; i++)
     278 ECB             :     {
     279 GIC         336 :         if (ptr->type == QI_VAL)
     280 ECB             :         {
     281 GIC         249 :             int         len = ptr->qoperand.length;
     282 ECB             :             char       *val;
     283                 : 
     284 GIC         249 :             val = palloc(len + 1);
     285 CBC         249 :             memcpy(val, operand + ptr->qoperand.distance, len);
     286             249 :             val[len] = '\0';
     287 ECB             : 
     288 GIC         249 :             values[nvalues++] = val;
     289 ECB             :         }
     290 GIC         336 :         ptr++;
     291 ECB             :     }
     292                 : 
     293 GIC         162 :     *nvalues_p = nvalues;
     294 CBC         162 :     return values;
     295 ECB             : }
     296                 : 
     297                 : static int
     298 GIC         198 : cmp_string(const void *a, const void *b)
     299 ECB             : {
     300 GIC         198 :     const char *sa = *((char *const *) a);
     301 CBC         198 :     const char *sb = *((char *const *) b);
     302 ECB             : 
     303 GIC         198 :     return strcmp(sa, sb);
     304 ECB             : }
     305                 : 
     306                 : Datum
     307 GIC          81 : tsq_mcontains(PG_FUNCTION_ARGS)
     308 ECB             : {
     309 GIC          81 :     TSQuery     query = PG_GETARG_TSQUERY(0);
     310 CBC          81 :     TSQuery     ex = PG_GETARG_TSQUERY(1);
     311 ECB             :     char      **query_values;
     312                 :     int         query_nvalues;
     313                 :     char      **ex_values;
     314                 :     int         ex_nvalues;
     315 GIC          81 :     bool        result = true;
     316 ECB             : 
     317                 :     /* Extract the query terms into arrays */
     318 GIC          81 :     query_values = collectTSQueryValues(query, &query_nvalues);
     319 CBC          81 :     ex_values = collectTSQueryValues(ex, &ex_nvalues);
     320 ECB             : 
     321                 :     /* Sort and remove duplicates from both arrays */
     322 GIC          81 :     qsort(query_values, query_nvalues, sizeof(char *), cmp_string);
     323 CBC          81 :     query_nvalues = qunique(query_values, query_nvalues, sizeof(char *),
     324 ECB             :                             cmp_string);
     325 GIC          81 :     qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string);
     326 CBC          81 :     ex_nvalues = qunique(ex_values, ex_nvalues, sizeof(char *), cmp_string);
     327 ECB             : 
     328 GIC          81 :     if (ex_nvalues > query_nvalues)
     329 CBC          30 :         result = false;
     330 ECB             :     else
     331                 :     {
     332                 :         int         i;
     333 GIC          51 :         int         j = 0;
     334 ECB             : 
     335 GIC          69 :         for (i = 0; i < ex_nvalues; i++)
     336 ECB             :         {
     337 GIC         123 :             for (; j < query_nvalues; j++)
     338 ECB             :             {
     339 GIC          90 :                 if (strcmp(ex_values[i], query_values[j]) == 0)
     340 CBC          18 :                     break;
     341 ECB             :             }
     342 GIC          51 :             if (j == query_nvalues)
     343 ECB             :             {
     344 GIC          33 :                 result = false;
     345 CBC          33 :                 break;
     346 ECB             :             }
     347                 :         }
     348                 :     }
     349                 : 
     350 GIC          81 :     PG_RETURN_BOOL(result);
     351 ECB             : }
     352                 : 
     353                 : Datum
     354 GIC          39 : tsq_mcontained(PG_FUNCTION_ARGS)
     355 ECB             : {
     356 GIC          39 :     PG_RETURN_DATUM(DirectFunctionCall2(tsq_mcontains,
     357 ECB             :                                         PG_GETARG_DATUM(1),
     358                 :                                         PG_GETARG_DATUM(0)));
     359                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a