LCOV - differential code coverage report
Current view: top level - contrib/ltree - ltxtquery_io.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: 380a8b2ea024c33a35e7abc8628e7c4f52f9f9f9 vs db5ed03217b9c238703df8b4b286115d6e940488 Lines: 78.1 % 297 232 1 64 3 229 1 3
Current Date: 2026-05-29 21:51:00 -0400 Functions: 86.7 % 15 13 1 1 3 10
Baseline: lcov-20260530-034037-baseline Branches: 58.4 % 202 118 84 118
Baseline Date: 2026-05-29 14:39:03 -0700 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 81.8 % 22 18 4 18
(30,360] days: 80.0 % 5 4 1 3 1
(360..) days: 77.8 % 270 210 60 210
Function coverage date bins:
(7,30] days: 100.0 % 1 1 1
(360..) days: 85.7 % 14 12 1 1 3 9
Branch coverage date bins:
(7,30] days: 63.6 % 22 14 8 14
(360..) days: 57.8 % 180 104 76 104

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * txtquery io
                                  3                 :                :  * Teodor Sigaev <teodor@stack.net>
                                  4                 :                :  * contrib/ltree/ltxtquery_io.c
                                  5                 :                :  */
                                  6                 :                : #include "postgres.h"
                                  7                 :                : 
                                  8                 :                : #include <ctype.h>
                                  9                 :                : 
                                 10                 :                : #include "crc32.h"
                                 11                 :                : #include "libpq/pqformat.h"
                                 12                 :                : #include "ltree.h"
                                 13                 :                : #include "miscadmin.h"
                                 14                 :                : #include "nodes/miscnodes.h"
                                 15                 :                : #include "varatt.h"
                                 16                 :                : 
                                 17                 :                : 
                                 18                 :                : /* parser's states */
                                 19                 :                : #define WAITOPERAND 1
                                 20                 :                : #define INOPERAND 2
                                 21                 :                : #define WAITOPERATOR    3
                                 22                 :                : 
                                 23                 :                : /*
                                 24                 :                :  * node of query tree, also used
                                 25                 :                :  * for storing polish notation in parser
                                 26                 :                :  */
                                 27                 :                : typedef struct NODE
                                 28                 :                : {
                                 29                 :                :     int32       type;
                                 30                 :                :     int32       val;
                                 31                 :                :     int16       distance;
                                 32                 :                :     int16       length;
                                 33                 :                :     uint16      flag;
                                 34                 :                :     struct NODE *next;
                                 35                 :                : } NODE;
                                 36                 :                : 
                                 37                 :                : typedef struct
                                 38                 :                : {
                                 39                 :                :     char       *buf;
                                 40                 :                :     int32       state;
                                 41                 :                :     int32       count;
                                 42                 :                :     struct Node *escontext;
                                 43                 :                :     /* reverse polish notation in list (for temporary usage) */
                                 44                 :                :     NODE       *str;
                                 45                 :                :     /* number in str */
                                 46                 :                :     int32       num;
                                 47                 :                : 
                                 48                 :                :     /* user-friendly operand */
                                 49                 :                :     int32       lenop;
                                 50                 :                :     int32       sumlen;
                                 51                 :                :     char       *op;
                                 52                 :                :     char       *curop;
                                 53                 :                : } QPRS_STATE;
                                 54                 :                : 
                                 55                 :                : /*
                                 56                 :                :  * get token from query string
                                 57                 :                :  *
                                 58                 :                :  * caller needs to check if a soft-error was set if the result is ERR.
                                 59                 :                :  */
                                 60                 :                : static int32
 5087 peter_e@gmx.net            61                 :CBC       65644 : gettoken_query(QPRS_STATE *state, int32 *val, int32 *lenval, char **strval, uint16 *flag)
                                 62                 :                : {
                                 63                 :                :     int         charlen;
                                 64                 :                : 
                                 65                 :                :     for (;;)
                                 66                 :                :     {
  143 tmunro@postgresql.or       67                 :          82286 :         charlen = pg_mblen_cstr(state->buf);
                                 68                 :                : 
 8705 bruce@momjian.us           69   [ +  +  +  - ]:          82286 :         switch (state->state)
                                 70                 :                :         {
                                 71                 :          32851 :             case WAITOPERAND:
 1332 tgl@sss.pgh.pa.us          72         [ +  + ]:          32851 :                 if (t_iseq(state->buf, '!'))
                                 73                 :                :                 {
 8705 bruce@momjian.us           74                 :              6 :                     (state->buf)++;
 5087 peter_e@gmx.net            75                 :              6 :                     *val = (int32) '!';
 8705 bruce@momjian.us           76                 :              6 :                     return OPR;
                                 77                 :                :                 }
 1332 tgl@sss.pgh.pa.us          78         [ +  + ]:          32845 :                 else if (t_iseq(state->buf, '('))
                                 79                 :                :                 {
 8705 bruce@momjian.us           80                 :          16383 :                     state->count++;
                                 81                 :          16383 :                     (state->buf)++;
                                 82                 :          16383 :                     return OPEN;
                                 83                 :                :                 }
 1240 andrew@dunslane.net        84   [ +  +  +  -  :          16462 :                 else if (ISLABEL(state->buf))
                                              -  + ]
                                 85                 :                :                 {
 8705 bruce@momjian.us           86                 :          16435 :                     state->state = INOPERAND;
                                 87                 :          16435 :                     *strval = state->buf;
 6543 teodor@sigaev.ru           88                 :          16435 :                     *lenval = charlen;
 8705 bruce@momjian.us           89                 :          16435 :                     *flag = 0;
                                 90                 :                :                 }
  529 peter@eisentraut.org       91         [ +  + ]:             27 :                 else if (!isspace((unsigned char) *state->buf))
 1249 andrew@dunslane.net        92         [ +  + ]:              2 :                     ereturn(state->escontext, ERR,
                                 93                 :                :                             (errcode(ERRCODE_SYNTAX_ERROR),
                                 94                 :                :                              errmsg("operand syntax error")));
 8705 bruce@momjian.us           95                 :          16460 :                 break;
                                 96                 :          16592 :             case INOPERAND:
 1240 andrew@dunslane.net        97   [ +  +  +  +  :          16592 :                 if (ISLABEL(state->buf))
                                              +  + ]
                                 98                 :                :                 {
 8669 bruce@momjian.us           99         [ -  + ]:            127 :                     if (*flag)
 1249 andrew@dunslane.net       100         [ #  # ]:UBC           0 :                         ereturn(state->escontext, ERR,
                                101                 :                :                                 (errcode(ERRCODE_SYNTAX_ERROR),
                                102                 :                :                                  errmsg("modifiers syntax error")));
 6543 teodor@sigaev.ru          103                 :CBC         127 :                     *lenval += charlen;
                                104                 :                :                 }
 1332 tgl@sss.pgh.pa.us         105         [ +  + ]:          16465 :                 else if (t_iseq(state->buf, '%'))
 7395 neilc@samurai.com         106                 :              4 :                     *flag |= LVAR_SUBLEXEME;
 1332 tgl@sss.pgh.pa.us         107         [ +  + ]:          16461 :                 else if (t_iseq(state->buf, '@'))
 8705 bruce@momjian.us          108                 :             12 :                     *flag |= LVAR_INCASE;
 1332 tgl@sss.pgh.pa.us         109         [ +  + ]:          16449 :                 else if (t_iseq(state->buf, '*'))
 8705 bruce@momjian.us          110                 :             14 :                     *flag |= LVAR_ANYEND;
                                111                 :                :                 else
                                112                 :                :                 {
                                113                 :          16435 :                     state->state = WAITOPERATOR;
                                114                 :          16435 :                     return VAL;
                                115                 :                :                 }
                                116                 :            157 :                 break;
                                117                 :          32843 :             case WAITOPERATOR:
 1332 tgl@sss.pgh.pa.us         118   [ +  +  +  + ]:          32843 :                 if (t_iseq(state->buf, '&') || t_iseq(state->buf, '|'))
                                119                 :                :                 {
 8705 bruce@momjian.us          120                 :          16409 :                     state->state = WAITOPERAND;
 5087 peter_e@gmx.net           121                 :          16409 :                     *val = (int32) *(state->buf);
 8705 bruce@momjian.us          122                 :          16409 :                     (state->buf)++;
                                123                 :          16409 :                     return OPR;
                                124                 :                :                 }
 1332 tgl@sss.pgh.pa.us         125         [ +  + ]:          16434 :                 else if (t_iseq(state->buf, ')'))
                                126                 :                :                 {
 8705 bruce@momjian.us          127                 :          16383 :                     (state->buf)++;
                                128                 :          16383 :                     state->count--;
                                129         [ -  + ]:          16383 :                     return (state->count < 0) ? ERR : CLOSE;
                                130                 :                :                 }
                                131         [ +  + ]:             51 :                 else if (*(state->buf) == '\0')
                                132                 :                :                 {
                                133                 :             26 :                     return (state->count) ? ERR : END;
                                134                 :                :                 }
 1332 tgl@sss.pgh.pa.us         135         [ -  + ]:             25 :                 else if (!t_iseq(state->buf, ' '))
                                136                 :                :                 {
 8705 bruce@momjian.us          137                 :UBC           0 :                     return ERR;
                                138                 :                :                 }
 8705 bruce@momjian.us          139                 :CBC          25 :                 break;
 8705 bruce@momjian.us          140                 :UBC           0 :             default:
                                141                 :              0 :                 return ERR;
                                142                 :                :                 break;
                                143                 :                :         }
                                144                 :                : 
 6543 teodor@sigaev.ru          145                 :CBC       16642 :         state->buf += charlen;
                                146                 :                :     }
                                147                 :                : 
                                148                 :                :     /* should not get here */
                                149                 :                : }
                                150                 :                : 
                                151                 :                : /*
                                152                 :                :  * push new one in polish notation reverse view
                                153                 :                :  */
                                154                 :                : static bool
 5087 peter_e@gmx.net           155                 :          32850 : pushquery(QPRS_STATE *state, int32 type, int32 val, int32 distance, int32 lenval, uint16 flag)
                                156                 :                : {
  176 michael@paquier.xyz       157                 :GNC       32850 :     NODE       *tmp = palloc_object(NODE);
                                158                 :                : 
 8705 bruce@momjian.us          159                 :CBC       32850 :     tmp->type = type;
                                160                 :          32850 :     tmp->val = val;
                                161                 :          32850 :     tmp->flag = flag;
                                162         [ -  + ]:          32850 :     if (distance > 0xffff)
 1249 andrew@dunslane.net       163         [ #  # ]:UBC           0 :         ereturn(state->escontext, false,
                                164                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                165                 :                :                  errmsg("value is too big")));
 8705 bruce@momjian.us          166         [ -  + ]:CBC       32850 :     if (lenval > 0xff)
 1249 andrew@dunslane.net       167         [ #  # ]:UBC           0 :         ereturn(state->escontext, false,
                                168                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                169                 :                :                  errmsg("operand is too long")));
 8705 bruce@momjian.us          170                 :CBC       32850 :     tmp->distance = distance;
                                171                 :          32850 :     tmp->length = lenval;
                                172                 :          32850 :     tmp->next = state->str;
                                173                 :          32850 :     state->str = tmp;
                                174                 :          32850 :     state->num++;
 1249 andrew@dunslane.net       175                 :          32850 :     return true;
                                176                 :                : }
                                177                 :                : 
                                178                 :                : /*
                                179                 :                :  * This function is used for query text parsing
                                180                 :                :  */
                                181                 :                : static bool
 6197 bruce@momjian.us          182                 :          16435 : pushval_asis(QPRS_STATE *state, int type, char *strval, int lenval, uint16 flag)
                                183                 :                : {
 8705                           184         [ -  + ]:          16435 :     if (lenval > 0xffff)
 1249 andrew@dunslane.net       185         [ #  # ]:UBC           0 :         ereturn(state->escontext, false,
                                186                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                187                 :                :                  errmsg("word is too long")));
                                188                 :                : 
 1107 tgl@sss.pgh.pa.us         189         [ -  + ]:CBC       16435 :     if (!pushquery(state, type, ltree_crc32_sz(strval, lenval),
                                190                 :          16435 :                    state->curop - state->op, lenval, flag))
 1249 andrew@dunslane.net       191                 :UBC           0 :         return false;
                                192                 :                : 
 8705 bruce@momjian.us          193         [ +  + ]:CBC       16445 :     while (state->curop - state->op + lenval + 1 >= state->lenop)
                                194                 :                :     {
 5087 peter_e@gmx.net           195                 :             10 :         int32       tmp = state->curop - state->op;
                                196                 :                : 
 8705 bruce@momjian.us          197                 :             10 :         state->lenop *= 2;
 1208 peter@eisentraut.org      198                 :             10 :         state->op = (char *) repalloc(state->op, state->lenop);
 8705 bruce@momjian.us          199                 :             10 :         state->curop = state->op + tmp;
                                200                 :                :     }
 1208 peter@eisentraut.org      201                 :          16435 :     memcpy(state->curop, strval, lenval);
 8705 bruce@momjian.us          202                 :          16435 :     state->curop += lenval;
                                203                 :          16435 :     *(state->curop) = '\0';
                                204                 :          16435 :     state->curop++;
                                205                 :          16435 :     state->sumlen += lenval + 1;
 1249 andrew@dunslane.net       206                 :          16435 :     return true;
                                207                 :                : }
                                208                 :                : 
                                209                 :                : #define STACKDEPTH      32
                                210                 :                : /*
                                211                 :                :  * make polish notation of query
                                212                 :                :  */
                                213                 :                : static int32
 6197 bruce@momjian.us          214                 :          16411 : makepol(QPRS_STATE *state)
                                215                 :                : {
 5087 peter_e@gmx.net           216                 :          16411 :     int32       val = 0,
                                217                 :                :                 type;
                                218                 :          16411 :     int32       lenval = 0;
 7553 tgl@sss.pgh.pa.us         219                 :          16411 :     char       *strval = NULL;
                                220                 :                :     int32       stack[STACKDEPTH];
 5087 peter_e@gmx.net           221                 :          16411 :     int32       lenstack = 0;
 7553 tgl@sss.pgh.pa.us         222                 :          16411 :     uint16      flag = 0;
                                223                 :                : 
                                224                 :                :     /* since this function recurses, it could be driven to stack overflow */
 4485 noah@leadboat.com         225                 :          16411 :     check_stack_depth();
                                226                 :                : 
 8669 bruce@momjian.us          227         [ +  + ]:          65644 :     while ((type = gettoken_query(state, &val, &lenval, &strval, &flag)) != END)
                                228                 :                :     {
 8705                           229   [ +  +  +  +  :          65618 :         switch (type)
                                              +  - ]
                                230                 :                :         {
                                231                 :          16435 :             case VAL:
 1249 andrew@dunslane.net       232         [ -  + ]:          16435 :                 if (!pushval_asis(state, VAL, strval, lenval, flag))
 1249 andrew@dunslane.net       233                 :UBC           0 :                     return ERR;
 5087 peter_e@gmx.net           234   [ +  +  +  + ]:CBC       24656 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
                                235         [ +  + ]:              8 :                                     stack[lenstack - 1] == (int32) '!'))
                                236                 :                :                 {
 8705 bruce@momjian.us          237                 :           8221 :                     lenstack--;
 1249 andrew@dunslane.net       238         [ -  + ]:           8221 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
 1249 andrew@dunslane.net       239                 :UBC           0 :                         return ERR;
                                240                 :                :                 }
 8705 bruce@momjian.us          241                 :CBC       16435 :                 break;
                                242                 :          16415 :             case OPR:
 5087 peter_e@gmx.net           243   [ -  +  -  - ]:          16415 :                 if (lenstack && val == (int32) '|')
                                244                 :                :                 {
 1249 andrew@dunslane.net       245         [ #  # ]:UBC           0 :                     if (!pushquery(state, OPR, val, 0, 0, 0))
                                246                 :              0 :                         return ERR;
                                247                 :                :                 }
                                248                 :                :                 else
                                249                 :                :                 {
 8705 bruce@momjian.us          250         [ -  + ]:CBC       16415 :                     if (lenstack == STACKDEPTH)
                                251                 :                :                         /* internal error */
 8346 tgl@sss.pgh.pa.us         252         [ #  # ]:UBC           0 :                         elog(ERROR, "stack too short");
 8705 bruce@momjian.us          253                 :CBC       16415 :                     stack[lenstack] = val;
                                254                 :          16415 :                     lenstack++;
                                255                 :                :                 }
                                256                 :          16415 :                 break;
                                257                 :          16383 :             case OPEN:
                                258         [ -  + ]:          16383 :                 if (makepol(state) == ERR)
 8705 bruce@momjian.us          259                 :UBC           0 :                     return ERR;
 5087 peter_e@gmx.net           260   [ +  +  +  + ]:CBC       24574 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
                                261         [ -  + ]:              1 :                                     stack[lenstack - 1] == (int32) '!'))
                                262                 :                :                 {
 8705 bruce@momjian.us          263                 :           8191 :                     lenstack--;
 1249 andrew@dunslane.net       264         [ -  + ]:           8191 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
 1249 andrew@dunslane.net       265                 :UBC           0 :                         return ERR;
                                266                 :                :                 }
 8705 bruce@momjian.us          267                 :CBC       16383 :                 break;
                                268                 :          16383 :             case CLOSE:
                                269         [ -  + ]:          16383 :                 while (lenstack)
                                270                 :                :                 {
 8705 bruce@momjian.us          271                 :UBC           0 :                     lenstack--;
 1249 andrew@dunslane.net       272         [ #  # ]:              0 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
                                273                 :              0 :                         return ERR;
                                274                 :                :                 };
 8705 bruce@momjian.us          275                 :CBC       16383 :                 return END;
                                276                 :                :                 break;
                                277                 :              2 :             case ERR:
 1249 andrew@dunslane.net       278   [ +  -  +  -  :              2 :                 if (SOFT_ERROR_OCCURRED(state->escontext))
                                              +  - ]
                                279                 :              2 :                     return ERR;
                                280                 :                :                 pg_fallthrough;
                                281                 :                :             default:
 1249 andrew@dunslane.net       282         [ #  # ]:UBC           0 :                 ereturn(state->escontext, ERR,
                                283                 :                :                         (errcode(ERRCODE_SYNTAX_ERROR),
                                284                 :                :                          errmsg("syntax error")));
                                285                 :                : 
                                286                 :                :         }
                                287                 :                :     }
 8669 bruce@momjian.us          288         [ +  + ]:CBC          29 :     while (lenstack)
                                289                 :                :     {
 8705                           290                 :              3 :         lenstack--;
 1249 andrew@dunslane.net       291         [ -  + ]:              3 :         if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
 1249 andrew@dunslane.net       292                 :UBC           0 :             return ERR;
                                293                 :                :     };
 8705 bruce@momjian.us          294                 :CBC          26 :     return END;
                                295                 :                : }
                                296                 :                : 
                                297                 :                : /*
                                298                 :                :  * Recursively fill the "left" fields of an ITEM array that represents
                                299                 :                :  * a valid postfix tree.
                                300                 :                :  *
                                301                 :                :  *  state: only needed for error reporting
                                302                 :                :  *  ptr: starting element of array
                                303                 :                :  *  pos: in/out argument, the array index this call is responsible to fill
                                304                 :                :  *
                                305                 :                :  * At exit, *pos has been incremented to point after the sub-tree whose
                                306                 :                :  * top is the entry-time value of *pos.
                                307                 :                :  *
                                308                 :                :  * Returns true if okay, false if error (the only possible error is
                                309                 :                :  * overflow of a "left" field).
                                310                 :                :  */
                                311                 :                : static bool
   19 tgl@sss.pgh.pa.us         312                 :          32849 : findoprnd(QPRS_STATE *state, ITEM *ptr, int32 *pos)
                                313                 :                : {
                                314                 :                :     int32       mypos;
                                315                 :                : 
                                316                 :                :     /* since this function recurses, it could be driven to stack overflow. */
 4485 noah@leadboat.com         317                 :          32849 :     check_stack_depth();
                                318                 :                : 
                                319                 :                :     /* get the position this call is supposed to update */
   19 tgl@sss.pgh.pa.us         320                 :          32849 :     mypos = *pos;
                                321                 :                : 
                                322                 :                :     /* in all cases, we should increment *pos to advance over this item */
                                323                 :          32849 :     (*pos)++;
                                324                 :                : 
                                325   [ +  +  -  + ]:          32849 :     if (ptr[mypos].type == VAL || ptr[mypos].type == VALTRUE)
                                326                 :                :     {
                                327                 :                :         /* base case: a VAL has no operand, so just set its left to zero */
                                328                 :          16434 :         ptr[mypos].left = 0;
                                329                 :                :     }
                                330         [ +  + ]:          16415 :     else if (ptr[mypos].val == (int32) '!')
                                331                 :                :     {
                                332                 :                :         /* unary operator, likewise easy: operand is just after it */
                                333                 :              6 :         ptr[mypos].left = 1;
                                334                 :                :         /* recurse to scan operand */
                                335         [ -  + ]:              6 :         if (!findoprnd(state, ptr, pos))
   19 tgl@sss.pgh.pa.us         336                 :UBC           0 :             return false;
                                337                 :                :     }
                                338                 :                :     else
                                339                 :                :     {
                                340                 :                :         /* binary operator */
                                341                 :                :         int32       delta;
                                342                 :                : 
                                343                 :                :         /* recurse to scan right operand */
   19 tgl@sss.pgh.pa.us         344         [ -  + ]:CBC       16409 :         if (!findoprnd(state, ptr, pos))
   19 tgl@sss.pgh.pa.us         345                 :UBC           0 :             return false;
                                346                 :                :         /* we must fill left with offset to left operand's top */
                                347                 :                :         /* delta can't overflow, see LTXTQUERY_TOO_BIG ... */
   19 tgl@sss.pgh.pa.us         348                 :CBC       16409 :         delta = *pos - mypos;
                                349                 :                :         /* ... but it might be too large to fit in the 16-bit left field */
                                350         [ -  + ]:          16409 :         Assert(delta > 0);
                                351         [ +  + ]:          16409 :         if (unlikely(delta > PG_INT16_MAX))
                                352         [ +  - ]:              1 :             ereturn(state->escontext, false,
                                353                 :                :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                354                 :                :                      errmsg("ltxtquery is too large")));
                                355                 :          16408 :         ptr[mypos].left = (int16) delta;
                                356                 :                :         /* recurse to scan left operand */
                                357         [ -  + ]:          16408 :         if (!findoprnd(state, ptr, pos))
   19 tgl@sss.pgh.pa.us         358                 :UBC           0 :             return false;
                                359                 :                :     }
                                360                 :                : 
   19 tgl@sss.pgh.pa.us         361                 :CBC       32848 :     return true;
                                362                 :                : }
                                363                 :                : 
                                364                 :                : 
                                365                 :                : /*
                                366                 :                :  * input
                                367                 :                :  */
                                368                 :                : static ltxtquery *
 1249 andrew@dunslane.net       369                 :             28 : queryin(char *buf, struct Node *escontext)
                                370                 :                : {
                                371                 :                :     QPRS_STATE  state;
                                372                 :                :     int32       i;
                                373                 :                :     ltxtquery  *query;
                                374                 :                :     int32       commonlen;
                                375                 :                :     ITEM       *ptr;
                                376                 :                :     NODE       *tmp;
 5087 peter_e@gmx.net           377                 :             28 :     int32       pos = 0;
                                378                 :                : 
                                379                 :                :     /* init state */
 8705 bruce@momjian.us          380                 :             28 :     state.buf = buf;
                                381                 :             28 :     state.state = WAITOPERAND;
                                382                 :             28 :     state.count = 0;
                                383                 :             28 :     state.num = 0;
                                384                 :             28 :     state.str = NULL;
 1249 andrew@dunslane.net       385                 :             28 :     state.escontext = escontext;
                                386                 :                : 
                                387                 :                :     /* init list of operand */
 8705 bruce@momjian.us          388                 :             28 :     state.sumlen = 0;
                                389                 :             28 :     state.lenop = 64;
                                390                 :             28 :     state.curop = state.op = (char *) palloc(state.lenop);
                                391                 :             28 :     *(state.curop) = '\0';
                                392                 :                : 
                                393                 :                :     /* parse query & make polish notation (postfix, but in reverse order) */
 1249 andrew@dunslane.net       394         [ +  + ]:             28 :     if (makepol(&state) == ERR)
                                395                 :              2 :         return NULL;
 8705 bruce@momjian.us          396         [ -  + ]:             26 :     if (!state.num)
 1249 andrew@dunslane.net       397         [ #  # ]:UBC           0 :         ereturn(escontext, NULL,
                                398                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                399                 :                :                  errmsg("syntax error"),
                                400                 :                :                  errdetail("Empty query.")));
                                401                 :                : 
 4485 noah@leadboat.com         402         [ -  + ]:CBC          26 :     if (LTXTQUERY_TOO_BIG(state.num, state.sumlen))
 1249 andrew@dunslane.net       403         [ #  # ]:UBC           0 :         ereturn(escontext, NULL,
                                404                 :                :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                405                 :                :                  errmsg("ltxtquery is too large")));
 8705 bruce@momjian.us          406                 :CBC          26 :     commonlen = COMPUTESIZE(state.num, state.sumlen);
                                407                 :                : 
 3735 andres@anarazel.de        408                 :             26 :     query = (ltxtquery *) palloc0(commonlen);
 7031 tgl@sss.pgh.pa.us         409                 :             26 :     SET_VARSIZE(query, commonlen);
 8705 bruce@momjian.us          410                 :             26 :     query->size = state.num;
                                411                 :             26 :     ptr = GETQUERY(query);
                                412                 :                : 
                                413                 :                :     /* set item in polish notation */
                                414         [ +  + ]:          32876 :     for (i = 0; i < state.num; i++)
                                415                 :                :     {
                                416                 :          32850 :         ptr[i].type = state.str->type;
                                417                 :          32850 :         ptr[i].val = state.str->val;
                                418                 :          32850 :         ptr[i].distance = state.str->distance;
                                419                 :          32850 :         ptr[i].length = state.str->length;
                                420                 :          32850 :         ptr[i].flag = state.str->flag;
                                421                 :          32850 :         tmp = state.str->next;
                                422                 :          32850 :         pfree(state.str);
                                423                 :          32850 :         state.str = tmp;
                                424                 :                :     }
                                425                 :                : 
                                426                 :                :     /* set user-friendly operand view */
 1208 peter@eisentraut.org      427                 :             26 :     memcpy(GETOPERAND(query), state.op, state.sumlen);
 8705 bruce@momjian.us          428                 :             26 :     pfree(state.op);
                                429                 :                : 
                                430                 :                :     /* set left operand's position for every operator */
                                431                 :             26 :     pos = 0;
   19 tgl@sss.pgh.pa.us         432         [ -  + ]:             26 :     if (!findoprnd(&state, ptr, &pos))
   19 tgl@sss.pgh.pa.us         433                 :UBC           0 :         return NULL;
                                434                 :                :     /* if successful, findoprnd should have scanned the whole array */
   19 tgl@sss.pgh.pa.us         435         [ -  + ]:CBC          25 :     Assert(pos == state.num);
                                436                 :                : 
 8705 bruce@momjian.us          437                 :             25 :     return query;
                                438                 :                : }
                                439                 :                : 
                                440                 :                : /*
                                441                 :                :  * in without morphology
                                442                 :                :  */
 2250 tgl@sss.pgh.pa.us         443                 :              3 : PG_FUNCTION_INFO_V1(ltxtq_in);
                                444                 :                : Datum
 8705 bruce@momjian.us          445                 :             28 : ltxtq_in(PG_FUNCTION_ARGS)
                                446                 :                : {
                                447                 :                :     ltxtquery  *res;
                                448                 :                : 
  464 peter@eisentraut.org      449         [ +  + ]:             28 :     if ((res = queryin(PG_GETARG_POINTER(0), fcinfo->context)) == NULL)
 1249 andrew@dunslane.net       450                 :              2 :         PG_RETURN_NULL();
                                451                 :             25 :     PG_RETURN_POINTER(res);
                                452                 :                : }
                                453                 :                : 
                                454                 :                : /*
                                455                 :                :  * ltxtquery type recv function
                                456                 :                :  *
                                457                 :                :  * The type is sent as text in binary mode, so this is almost the same
                                458                 :                :  * as the input function, but it's prefixed with a version number so we
                                459                 :                :  * can change the binary format sent in future if necessary. For now,
                                460                 :                :  * only version 1 is supported.
                                461                 :                :  */
 2250 tgl@sss.pgh.pa.us         462                 :              2 : PG_FUNCTION_INFO_V1(ltxtq_recv);
                                463                 :                : Datum
 2250 tgl@sss.pgh.pa.us         464                 :UBC           0 : ltxtq_recv(PG_FUNCTION_ARGS)
                                465                 :                : {
                                466                 :              0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                                467                 :              0 :     int         version = pq_getmsgint(buf, 1);
                                468                 :                :     char       *str;
                                469                 :                :     int         nbytes;
                                470                 :                :     ltxtquery  *res;
                                471                 :                : 
                                472         [ #  # ]:              0 :     if (version != 1)
                                473         [ #  # ]:              0 :         elog(ERROR, "unsupported ltxtquery version number %d", version);
                                474                 :                : 
                                475                 :              0 :     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
 1249 andrew@dunslane.net       476                 :              0 :     res = queryin(str, NULL);
 2250 tgl@sss.pgh.pa.us         477                 :              0 :     pfree(str);
                                478                 :                : 
                                479                 :              0 :     PG_RETURN_POINTER(res);
                                480                 :                : }
                                481                 :                : 
                                482                 :                : /*
                                483                 :                :  * out function
                                484                 :                :  */
                                485                 :                : typedef struct
                                486                 :                : {
                                487                 :                :     ITEM       *curpol;
                                488                 :                :     char       *buf;
                                489                 :                :     char       *cur;
                                490                 :                :     char       *op;
                                491                 :                :     int32       buflen;
                                492                 :                : } INFIX;
                                493                 :                : 
                                494                 :                : #define RESIZEBUF(inf,addsize) \
                                495                 :                : while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \
                                496                 :                : { \
                                497                 :                :     int32 len = (inf)->cur - (inf)->buf; \
                                498                 :                :     (inf)->buflen *= 2; \
                                499                 :                :     (inf)->buf = (char*) repalloc( (void*)(inf)->buf, (inf)->buflen ); \
                                500                 :                :     (inf)->cur = (inf)->buf + len; \
                                501                 :                : }
                                502                 :                : 
                                503                 :                : /*
                                504                 :                :  * recursive walk on tree and print it in
                                505                 :                :  * infix (human-readable) view
                                506                 :                :  */
                                507                 :                : static void
 6771 bruce@momjian.us          508                 :CBC          10 : infix(INFIX *in, bool first)
                                509                 :                : {
                                510                 :                :     /* since this function recurses, it could be driven to stack overflow. */
 3890 noah@leadboat.com         511                 :             10 :     check_stack_depth();
                                512                 :                : 
 8705 bruce@momjian.us          513         [ +  + ]:             10 :     if (in->curpol->type == VAL)
                                514                 :                :     {
 8669                           515                 :              6 :         char       *op = in->op + in->curpol->distance;
                                516                 :                : 
 8705                           517         [ +  + ]:              8 :         RESIZEBUF(in, in->curpol->length * 2 + 5);
 8669                           518         [ +  + ]:             32 :         while (*op)
                                519                 :                :         {
 8705                           520                 :             26 :             *(in->cur) = *op;
                                521                 :             26 :             op++;
                                522                 :             26 :             in->cur++;
                                523                 :                :         }
 7395 neilc@samurai.com         524         [ +  + ]:              6 :         if (in->curpol->flag & LVAR_SUBLEXEME)
                                525                 :                :         {
 8705 bruce@momjian.us          526                 :              2 :             *(in->cur) = '%';
                                527                 :              2 :             in->cur++;
                                528                 :                :         }
 8669                           529         [ +  + ]:              6 :         if (in->curpol->flag & LVAR_INCASE)
                                530                 :                :         {
 8705                           531                 :              1 :             *(in->cur) = '@';
                                532                 :              1 :             in->cur++;
                                533                 :                :         }
 8669                           534         [ +  + ]:              6 :         if (in->curpol->flag & LVAR_ANYEND)
                                535                 :                :         {
 8705                           536                 :              3 :             *(in->cur) = '*';
                                537                 :              3 :             in->cur++;
                                538                 :                :         }
                                539                 :              6 :         *(in->cur) = '\0';
                                540                 :              6 :         in->curpol++;
                                541                 :                :     }
 5087 peter_e@gmx.net           542         [ +  + ]:              4 :     else if (in->curpol->val == (int32) '!')
                                543                 :                :     {
 8669 bruce@momjian.us          544                 :              1 :         bool        isopr = false;
                                545                 :                : 
 8705                           546         [ -  + ]:              1 :         RESIZEBUF(in, 1);
                                547                 :              1 :         *(in->cur) = '!';
                                548                 :              1 :         in->cur++;
                                549                 :              1 :         *(in->cur) = '\0';
                                550                 :              1 :         in->curpol++;
                                551         [ -  + ]:              1 :         if (in->curpol->type == OPR)
                                552                 :                :         {
 8705 bruce@momjian.us          553                 :UBC           0 :             isopr = true;
                                554         [ #  # ]:              0 :             RESIZEBUF(in, 2);
                                555                 :              0 :             sprintf(in->cur, "( ");
                                556                 :              0 :             in->cur = strchr(in->cur, '\0');
                                557                 :                :         }
 8705 bruce@momjian.us          558                 :CBC           1 :         infix(in, isopr);
                                559         [ -  + ]:              1 :         if (isopr)
                                560                 :                :         {
 8705 bruce@momjian.us          561         [ #  # ]:UBC           0 :             RESIZEBUF(in, 2);
                                562                 :              0 :             sprintf(in->cur, " )");
                                563                 :              0 :             in->cur = strchr(in->cur, '\0');
                                564                 :                :         }
                                565                 :                :     }
                                566                 :                :     else
                                567                 :                :     {
 5087 peter_e@gmx.net           568                 :CBC           3 :         int32       op = in->curpol->val;
                                569                 :                :         INFIX       nrm;
                                570                 :                : 
 8705 bruce@momjian.us          571                 :              3 :         in->curpol++;
 5087 peter_e@gmx.net           572   [ -  +  -  - ]:              3 :         if (op == (int32) '|' && !first)
                                573                 :                :         {
 8705 bruce@momjian.us          574         [ #  # ]:UBC           0 :             RESIZEBUF(in, 2);
                                575                 :              0 :             sprintf(in->cur, "( ");
                                576                 :              0 :             in->cur = strchr(in->cur, '\0');
                                577                 :                :         }
                                578                 :                : 
 8705 bruce@momjian.us          579                 :CBC           3 :         nrm.curpol = in->curpol;
                                580                 :              3 :         nrm.op = in->op;
                                581                 :              3 :         nrm.buflen = 16;
  176 michael@paquier.xyz       582                 :GNC           3 :         nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
                                583                 :                : 
                                584                 :                :         /* get right operand */
 8705 bruce@momjian.us          585                 :CBC           3 :         infix(&nrm, false);
                                586                 :                : 
                                587                 :                :         /* get & print left operand */
                                588                 :              3 :         in->curpol = nrm.curpol;
                                589                 :              3 :         infix(in, false);
                                590                 :                : 
                                591                 :                :         /* print operator & right operand */
                                592         [ -  + ]:              3 :         RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
                                593                 :              3 :         sprintf(in->cur, " %c %s", op, nrm.buf);
                                594                 :              3 :         in->cur = strchr(in->cur, '\0');
                                595                 :              3 :         pfree(nrm.buf);
                                596                 :                : 
 5087 peter_e@gmx.net           597   [ -  +  -  - ]:              3 :         if (op == (int32) '|' && !first)
                                598                 :                :         {
 8705 bruce@momjian.us          599         [ #  # ]:UBC           0 :             RESIZEBUF(in, 2);
                                600                 :              0 :             sprintf(in->cur, " )");
                                601                 :              0 :             in->cur = strchr(in->cur, '\0');
                                602                 :                :         }
                                603                 :                :     }
 8705 bruce@momjian.us          604                 :CBC          10 : }
                                605                 :                : 
 2250 tgl@sss.pgh.pa.us         606                 :              3 : PG_FUNCTION_INFO_V1(ltxtq_out);
                                607                 :                : Datum
 8705 bruce@momjian.us          608                 :              3 : ltxtq_out(PG_FUNCTION_ARGS)
                                609                 :                : {
 3176 tgl@sss.pgh.pa.us         610                 :              3 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(0);
                                611                 :                :     INFIX       nrm;
                                612                 :                : 
 8705 bruce@momjian.us          613         [ -  + ]:              3 :     if (query->size == 0)
 8346 tgl@sss.pgh.pa.us         614         [ #  # ]:UBC           0 :         ereport(ERROR,
                                615                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                616                 :                :                  errmsg("syntax error"),
                                617                 :                :                  errdetail("Empty query.")));
                                618                 :                : 
 8705 bruce@momjian.us          619                 :CBC           3 :     nrm.curpol = GETQUERY(query);
                                620                 :              3 :     nrm.buflen = 32;
  176 michael@paquier.xyz       621                 :GNC           3 :     nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 8705 bruce@momjian.us          622                 :CBC           3 :     *(nrm.cur) = '\0';
                                623                 :              3 :     nrm.op = GETOPERAND(query);
                                624                 :              3 :     infix(&nrm, true);
                                625                 :                : 
                                626                 :              3 :     PG_RETURN_POINTER(nrm.buf);
                                627                 :                : }
                                628                 :                : 
                                629                 :                : /*
                                630                 :                :  * ltxtquery type send function
                                631                 :                :  *
                                632                 :                :  * The type is sent as text in binary mode, so this is almost the same
                                633                 :                :  * as the output function, but it's prefixed with a version number so we
                                634                 :                :  * can change the binary format sent in future if necessary. For now,
                                635                 :                :  * only version 1 is supported.
                                636                 :                :  */
 2250 tgl@sss.pgh.pa.us         637                 :              2 : PG_FUNCTION_INFO_V1(ltxtq_send);
                                638                 :                : Datum
 2250 tgl@sss.pgh.pa.us         639                 :UBC           0 : ltxtq_send(PG_FUNCTION_ARGS)
                                640                 :                : {
                                641                 :              0 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(0);
                                642                 :                :     StringInfoData buf;
                                643                 :              0 :     int         version = 1;
                                644                 :                :     INFIX       nrm;
                                645                 :                : 
                                646         [ #  # ]:              0 :     if (query->size == 0)
                                647         [ #  # ]:              0 :         ereport(ERROR,
                                648                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                649                 :                :                  errmsg("syntax error"),
                                650                 :                :                  errdetail("Empty query.")));
                                651                 :                : 
                                652                 :              0 :     nrm.curpol = GETQUERY(query);
                                653                 :              0 :     nrm.buflen = 32;
  176 michael@paquier.xyz       654                 :UNC           0 :     nrm.cur = nrm.buf = palloc_array(char, nrm.buflen);
 2250 tgl@sss.pgh.pa.us         655                 :UBC           0 :     *(nrm.cur) = '\0';
                                656                 :              0 :     nrm.op = GETOPERAND(query);
                                657                 :              0 :     infix(&nrm, true);
                                658                 :                : 
                                659                 :              0 :     pq_begintypsend(&buf);
                                660                 :              0 :     pq_sendint8(&buf, version);
                                661                 :              0 :     pq_sendtext(&buf, nrm.buf, strlen(nrm.buf));
                                662                 :              0 :     pfree(nrm.buf);
                                663                 :                : 
                                664                 :              0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                                665                 :                : }
        

Generated by: LCOV version 2.5.0-beta