LCOV - differential code coverage report
Current view: top level - contrib/ltree - ltxtquery_io.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 72.2 % 291 210 19 28 31 3 15 95 29 71 56 102 7 9
Current Date: 2023-04-08 17:13:01 Functions: 86.7 % 15 13 2 12 1 2 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 52.5 % 40 21 19 21
Legend: Lines: hit not hit (180,240] days: 100.0 % 8 8 8
(240..) days: 74.5 % 243 181 28 31 3 15 95 71 40 101
Function coverage date bins:
(60,120] days: 100.0 % 1 1 1
(240..) days: 44.4 % 27 12 2 12 1 12

 Age         Owner                  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
 3940 peter_e                    61 GIC         108 : gettoken_query(QPRS_STATE *state, int32 *val, int32 *lenval, char **strval, uint16 *flag)
                                 62                 : {
                                 63                 :     int         charlen;
                                 64                 : 
                                 65                 :     for (;;)
 7558 bruce                      66 ECB             :     {
 5396 teodor                     67 GIC         365 :         charlen = pg_mblen(state->buf);
                                 68                 : 
 7558 bruce                      69             365 :         switch (state->state)
                                 70                 :         {
                                 71              83 :             case WAITOPERAND:
  185 tgl                        72 GNC          83 :                 if (t_iseq(state->buf, '!'))
                                 73                 :                 {
 7558 bruce                      74 CBC           6 :                     (state->buf)++;
 3940 peter_e                    75 GIC           6 :                     *val = (int32) '!';
 7558 bruce                      76 CBC           6 :                     return OPR;
 7558 bruce                      77 ECB             :                 }
  185 tgl                        78 GNC          77 :                 else if (t_iseq(state->buf, '('))
 7558 bruce                      79 ECB             :                 {
 7558 bruce                      80 LBC           0 :                     state->count++;
                                 81               0 :                     (state->buf)++;
 7558 bruce                      82 UIC           0 :                     return OPEN;
 7558 bruce                      83 ECB             :                 }
   93 andrew                     84 GNC          77 :                 else if (ISLABEL(state->buf))
 7558 bruce                      85 EUB             :                 {
 7558 bruce                      86 GBC          50 :                     state->state = INOPERAND;
                                 87              50 :                     *strval = state->buf;
 5396 teodor                     88 GIC          50 :                     *lenval = charlen;
 7558 bruce                      89 CBC          50 :                     *flag = 0;
                                 90                 :                 }
 5396 teodor                     91              27 :                 else if (!t_isspace(state->buf))
  102 andrew                     92 GNC           2 :                     ereturn(state->escontext, ERR,
 7199 tgl                        93 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                                 94                 :                              errmsg("operand syntax error")));
 7558 bruce                      95 GIC          75 :                 break;
 7558 bruce                      96 CBC         207 :             case INOPERAND:
   93 andrew                     97 GNC         207 :                 if (ISLABEL(state->buf))
                                 98                 :                 {
 7522 bruce                      99 GIC         127 :                     if (*flag)
  102 andrew                    100 UNC           0 :                         ereturn(state->escontext, ERR,
 7199 tgl                       101 ECB             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
 2217 peter_e                   102                 :                                  errmsg("modifiers syntax error")));
 5396 teodor                    103 GIC         127 :                     *lenval += charlen;
 7522 bruce                     104 ECB             :                 }
  185 tgl                       105 GNC          80 :                 else if (t_iseq(state->buf, '%'))
 6248 neilc                     106 GIC           4 :                     *flag |= LVAR_SUBLEXEME;
  185 tgl                       107 GNC          76 :                 else if (t_iseq(state->buf, '@'))
 7558 bruce                     108 CBC          12 :                     *flag |= LVAR_INCASE;
  185 tgl                       109 GNC          64 :                 else if (t_iseq(state->buf, '*'))
 7558 bruce                     110 CBC          14 :                     *flag |= LVAR_ANYEND;
 7522 bruce                     111 ECB             :                 else
                                112                 :                 {
 7558 bruce                     113 CBC          50 :                     state->state = WAITOPERATOR;
                                114              50 :                     return VAL;
 7558 bruce                     115 ECB             :                 }
 7558 bruce                     116 GIC         157 :                 break;
                                117              75 :             case WAITOPERATOR:
  185 tgl                       118 GNC          75 :                 if (t_iseq(state->buf, '&') || t_iseq(state->buf, '|'))
 7558 bruce                     119 ECB             :                 {
 7558 bruce                     120 GIC          25 :                     state->state = WAITOPERAND;
 3940 peter_e                   121 CBC          25 :                     *val = (int32) *(state->buf);
 7558 bruce                     122              25 :                     (state->buf)++;
                                123              25 :                     return OPR;
                                124                 :                 }
  185 tgl                       125 GNC          50 :                 else if (t_iseq(state->buf, ')'))
 7558 bruce                     126 ECB             :                 {
 7558 bruce                     127 LBC           0 :                     (state->buf)++;
                                128               0 :                     state->count--;
 7558 bruce                     129 UIC           0 :                     return (state->count < 0) ? ERR : CLOSE;
 7558 bruce                     130 ECB             :                 }
 7558 bruce                     131 GIC          50 :                 else if (*(state->buf) == '\0')
                                132                 :                 {
 7558 bruce                     133 GBC          25 :                     return (state->count) ? ERR : END;
                                134                 :                 }
  185 tgl                       135 GNC          25 :                 else if (!t_iseq(state->buf, ' '))
                                136                 :                 {
 7558 bruce                     137 UBC           0 :                     return ERR;
                                138                 :                 }
 7558 bruce                     139 GIC          25 :                 break;
 7558 bruce                     140 LBC           0 :             default:
 7558 bruce                     141 UIC           0 :                 return ERR;
 7558 bruce                     142 ECB             :                 break;
                                143                 :         }
 5396 teodor                    144                 : 
 5396 teodor                    145 GIC         257 :         state->buf += charlen;
 7558 bruce                     146 EUB             :     }
                                147                 : 
                                148                 :     /* should not get here */
                                149                 : }
 7558 bruce                     150 ECB             : 
 7558 bruce                     151 EUB             : /*
                                152                 :  * push new one in polish notation reverse view
                                153                 :  */
                                154                 : static bool
 3940 peter_e                   155 GIC          81 : pushquery(QPRS_STATE *state, int32 type, int32 val, int32 distance, int32 lenval, uint16 flag)
 7558 bruce                     156 ECB             : {
 7522 bruce                     157 GIC          81 :     NODE       *tmp = (NODE *) palloc(sizeof(NODE));
                                158                 : 
 7558                           159              81 :     tmp->type = type;
                                160              81 :     tmp->val = val;
                                161              81 :     tmp->flag = flag;
                                162              81 :     if (distance > 0xffff)
  102 andrew                    163 UNC           0 :         ereturn(state->escontext, false,
                                164                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                165                 :                  errmsg("value is too big")));
 7558 bruce                     166 CBC          81 :     if (lenval > 0xff)
  102 andrew                    167 UNC           0 :         ereturn(state->escontext, false,
 7199 tgl                       168 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                169                 :                  errmsg("operand is too long")));
 7558 bruce                     170 CBC          81 :     tmp->distance = distance;
                                171              81 :     tmp->length = lenval;
                                172              81 :     tmp->next = state->str;
                                173              81 :     state->str = tmp;
 7558 bruce                     174 GBC          81 :     state->num++;
  102 andrew                    175 GNC          81 :     return true;
                                176                 : }
                                177                 : 
 7558 bruce                     178 ECB             : /*
 1335 michael                   179 EUB             :  * This function is used for query text parsing
                                180                 :  */
                                181                 : static bool
 5050 bruce                     182 CBC          50 : pushval_asis(QPRS_STATE *state, int type, char *strval, int lenval, uint16 flag)
 7558 bruce                     183 ECB             : {
 7558 bruce                     184 CBC          50 :     if (lenval > 0xffff)
  102 andrew                    185 UNC           0 :         ereturn(state->escontext, false,
 7199 tgl                       186 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                187                 :                  errmsg("word is too long")));
                                188                 : 
  102 andrew                    189 GNC          50 :     if (! pushquery(state, type, ltree_crc32_sz(strval, lenval),
                                190              50 :                     state->curop - state->op, lenval, flag))
  102 andrew                    191 UNC           0 :         return false;
                                192                 : 
 7558 bruce                     193 GIC          50 :     while (state->curop - state->op + lenval + 1 >= state->lenop)
                                194                 :     {
 3940 peter_e                   195 LBC           0 :         int32       tmp = state->curop - state->op;
                                196                 : 
 7558 bruce                     197               0 :         state->lenop *= 2;
   61 peter                     198 UNC           0 :         state->op = (char *) repalloc(state->op, state->lenop);
 7558 bruce                     199 UIC           0 :         state->curop = state->op + tmp;
                                200                 :     }
   61 peter                     201 GNC          50 :     memcpy(state->curop, strval, lenval);
 7558 bruce                     202 CBC          50 :     state->curop += lenval;
                                203              50 :     *(state->curop) = '\0';
 7558 bruce                     204 GBC          50 :     state->curop++;
 7558 bruce                     205 GIC          50 :     state->sumlen += lenval + 1;
  102 andrew                    206 GNC          50 :     return true;
 7558 bruce                     207 ECB             : }
                                208                 : 
 7522 bruce                     209 EUB             : #define STACKDEPTH      32
                                210                 : /*
 2253 heikki.linnakangas        211                 :  * make polish notation of query
 7558 bruce                     212                 :  */
 3940 peter_e                   213                 : static int32
 5050 bruce                     214 GIC          27 : makepol(QPRS_STATE *state)
 7558 bruce                     215 ECB             : {
 3940 peter_e                   216 CBC          27 :     int32       val = 0,
 7558 bruce                     217 ECB             :                 type;
 3940 peter_e                   218 CBC          27 :     int32       lenval = 0;
 6406 tgl                       219              27 :     char       *strval = NULL;
 3940 peter_e                   220 ECB             :     int32       stack[STACKDEPTH];
 3940 peter_e                   221 GIC          27 :     int32       lenstack = 0;
 6406 tgl                       222              27 :     uint16      flag = 0;
                                223                 : 
                                224                 :     /* since this function recurses, it could be driven to stack overflow */
 3338 noah                      225              27 :     check_stack_depth();
                                226                 : 
 7522 bruce                     227             108 :     while ((type = gettoken_query(state, &val, &lenval, &strval, &flag)) != END)
 7522 bruce                     228 ECB             :     {
 7558 bruce                     229 GIC          83 :         switch (type)
 7558 bruce                     230 ECB             :         {
 7558 bruce                     231 GIC          50 :             case VAL:
  102 andrew                    232 GNC          50 :                 if (!pushval_asis(state, VAL, strval, lenval, flag))
  102 andrew                    233 UNC           0 :                     return ERR;
 3940 peter_e                   234 CBC          79 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
 3940 peter_e                   235 GIC           8 :                                     stack[lenstack - 1] == (int32) '!'))
 7558 bruce                     236 ECB             :                 {
 7558 bruce                     237 CBC          29 :                     lenstack--;
  102 andrew                    238 GNC          29 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
  102 andrew                    239 UNC           0 :                         return ERR;
                                240                 :                 }
 7558 bruce                     241 CBC          50 :                 break;
 7558 bruce                     242 GIC          31 :             case OPR:
 3940 peter_e                   243 CBC          31 :                 if (lenstack && val == (int32) '|')
                                244                 :                 {
  102 andrew                    245 UNC           0 :                     if (!pushquery(state, OPR, val, 0, 0, 0))
                                246               0 :                         return ERR;
                                247                 :                 }
 7558 bruce                     248 ECB             :                 else
                                249                 :                 {
 7558 bruce                     250 CBC          31 :                     if (lenstack == STACKDEPTH)
 7199 tgl                       251 ECB             :                         /* internal error */
 7199 tgl                       252 UBC           0 :                         elog(ERROR, "stack too short");
 7558 bruce                     253 CBC          31 :                     stack[lenstack] = val;
                                254              31 :                     lenstack++;
                                255                 :                 }
                                256              31 :                 break;
 7558 bruce                     257 LBC           0 :             case OPEN:
 7558 bruce                     258 UBC           0 :                 if (makepol(state) == ERR)
 7558 bruce                     259 UIC           0 :                     return ERR;
 3940 peter_e                   260 LBC           0 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
                                261               0 :                                     stack[lenstack - 1] == (int32) '!'))
 7558 bruce                     262 ECB             :                 {
 7558 bruce                     263 UIC           0 :                     lenstack--;
  102 andrew                    264 UNC           0 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
                                265               0 :                         return ERR;
 7558 bruce                     266 EUB             :                 }
 7558 bruce                     267 UIC           0 :                 break;
                                268               0 :             case CLOSE:
                                269               0 :                 while (lenstack)
 7558 bruce                     270 ECB             :                 {
 7558 bruce                     271 UIC           0 :                     lenstack--;
  102 andrew                    272 UNC           0 :                     if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
                                273               0 :                         return ERR;
 7558 bruce                     274 ECB             :                 };
 7558 bruce                     275 LBC           0 :                 return END;
                                276                 :                 break;
 7558 bruce                     277 CBC           2 :             case ERR:
  102 andrew                    278 GNC           2 :                 if (SOFT_ERROR_OCCURRED(state->escontext))
                                279               2 :                     return ERR;
                                280                 :                 /* fall through */
 7558 bruce                     281 EUB             :             default:
  102 andrew                    282 UNC           0 :                 ereturn(state->escontext, ERR,
 7199 tgl                       283 EUB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
                                284                 :                          errmsg("syntax error")));
                                285                 : 
 7558 bruce                     286                 :         }
                                287                 :     }
 7522 bruce                     288 GBC          27 :     while (lenstack)
                                289                 :     {
 7558                           290               2 :         lenstack--;
  102 andrew                    291 GNC           2 :         if (!pushquery(state, OPR, stack[lenstack], 0, 0, 0))
  102 andrew                    292 UNC           0 :             return ERR;
 7558 bruce                     293 EUB             :     };
 7558 bruce                     294 GIC          25 :     return END;
 7558 bruce                     295 EUB             : }
                                296                 : 
                                297                 : static void
 3940 peter_e                   298 GIC          81 : findoprnd(ITEM *ptr, int32 *pos)
 7558 bruce                     299 EUB             : {
                                300                 :     /* since this function recurses, it could be driven to stack overflow. */
 3338 noah                      301 CBC          81 :     check_stack_depth();
 3338 noah                      302 ECB             : 
 7558 bruce                     303 CBC          81 :     if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE)
                                304                 :     {
 7558 bruce                     305 GIC          50 :         ptr[*pos].left = 0;
 7558 bruce                     306 GBC          50 :         (*pos)++;
                                307                 :     }
 3940 peter_e                   308 GIC          31 :     else if (ptr[*pos].val == (int32) '!')
                                309                 :     {
 7558 bruce                     310               6 :         ptr[*pos].left = 1;
                                311               6 :         (*pos)++;
 7558 bruce                     312 CBC           6 :         findoprnd(ptr, pos);
                                313                 :     }
 7558 bruce                     314 ECB             :     else
                                315                 :     {
 7522 bruce                     316 GBC          25 :         ITEM       *curitem = &ptr[*pos];
 3940 peter_e                   317 GIC          25 :         int32       tmp = *pos;
 7558 bruce                     318 ECB             : 
 7558 bruce                     319 GIC          25 :         (*pos)++;
                                320              25 :         findoprnd(ptr, pos);
                                321              25 :         curitem->left = *pos - tmp;
 7558 bruce                     322 CBC          25 :         findoprnd(ptr, pos);
                                323                 :     }
 7558 bruce                     324 GIC          81 : }
 7558 bruce                     325 ECB             : 
                                326                 : 
                                327                 : /*
                                328                 :  * input
                                329                 :  */
                                330                 : static ltxtquery *
  102 andrew                    331 GNC          27 : queryin(char *buf, struct Node *escontext)
 7558 bruce                     332 ECB             : {
                                333                 :     QPRS_STATE  state;
 3940 peter_e                   334                 :     int32       i;
 7558 bruce                     335                 :     ltxtquery  *query;
 3940 peter_e                   336                 :     int32       commonlen;
                                337                 :     ITEM       *ptr;
                                338                 :     NODE       *tmp;
 3940 peter_e                   339 GIC          27 :     int32       pos = 0;
 7558 bruce                     340 ECB             : 
                                341                 : #ifdef BS_DEBUG
                                342                 :     char        pbuf[16384],
                                343                 :                *cur;
                                344                 : #endif
                                345                 : 
                                346                 :     /* init state */
 7558 bruce                     347 GIC          27 :     state.buf = buf;
 7558 bruce                     348 CBC          27 :     state.state = WAITOPERAND;
 7558 bruce                     349 GIC          27 :     state.count = 0;
                                350              27 :     state.num = 0;
                                351              27 :     state.str = NULL;
  102 andrew                    352 GNC          27 :     state.escontext = escontext;
                                353                 : 
                                354                 :     /* init list of operand */
 7558 bruce                     355 GIC          27 :     state.sumlen = 0;
 7558 bruce                     356 CBC          27 :     state.lenop = 64;
 7558 bruce                     357 GIC          27 :     state.curop = state.op = (char *) palloc(state.lenop);
                                358              27 :     *(state.curop) = '\0';
                                359                 : 
                                360                 :     /* parse query & make polish notation (postfix, but in reverse order) */
  102 andrew                    361 GNC          27 :     if (makepol(&state) == ERR)
                                362               2 :         return NULL;
 7558 bruce                     363 GIC          25 :     if (!state.num)
  102 andrew                    364 UNC           0 :         ereturn(escontext, NULL,
 7199 tgl                       365 ECB             :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                366                 :                  errmsg("syntax error"),
                                367                 :                  errdetail("Empty query.")));
                                368                 : 
 3338 noah                      369 GIC          25 :     if (LTXTQUERY_TOO_BIG(state.num, state.sumlen))
  102 andrew                    370 UNC           0 :         ereturn(escontext, NULL,
                                371                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                372                 :                  errmsg("ltxtquery is too large")));
 7558 bruce                     373 CBC          25 :     commonlen = COMPUTESIZE(state.num, state.sumlen);
 3338 noah                      374 ECB             : 
 2588 andres                    375 CBC          25 :     query = (ltxtquery *) palloc0(commonlen);
 5884 tgl                       376              25 :     SET_VARSIZE(query, commonlen);
 7558 bruce                     377              25 :     query->size = state.num;
                                378              25 :     ptr = GETQUERY(query);
                                379                 : 
                                380                 :     /* set item in polish notation */
                                381             106 :     for (i = 0; i < state.num; i++)
 7558 bruce                     382 ECB             :     {
 7558 bruce                     383 CBC          81 :         ptr[i].type = state.str->type;
                                384              81 :         ptr[i].val = state.str->val;
 7558 bruce                     385 GIC          81 :         ptr[i].distance = state.str->distance;
                                386              81 :         ptr[i].length = state.str->length;
 7558 bruce                     387 CBC          81 :         ptr[i].flag = state.str->flag;
                                388              81 :         tmp = state.str->next;
                                389              81 :         pfree(state.str);
 7558 bruce                     390 GBC          81 :         state.str = tmp;
                                391                 :     }
                                392                 : 
                                393                 :     /* set user-friendly operand view */
   61 peter                     394 GNC          25 :     memcpy(GETOPERAND(query), state.op, state.sumlen);
 7558 bruce                     395 CBC          25 :     pfree(state.op);
 7558 bruce                     396 EUB             : 
                                397                 :     /* set left operand's position for every operator */
 7558 bruce                     398 GIC          25 :     pos = 0;
 7558 bruce                     399 CBC          25 :     findoprnd(ptr, &pos);
                                400                 : 
                                401              25 :     return query;
 7558 bruce                     402 ECB             : }
                                403                 : 
                                404                 : /*
                                405                 :  * in without morphology
                                406                 :  */
 1103 tgl                       407 CBC           3 : PG_FUNCTION_INFO_V1(ltxtq_in);
                                408                 : Datum
 7558 bruce                     409              27 : ltxtq_in(PG_FUNCTION_ARGS)
 7558 bruce                     410 ECB             : {
                                411                 :     ltxtquery *res;
                                412                 : 
  102 andrew                    413 GNC          27 :     if ((res = queryin((char *) PG_GETARG_POINTER(0), fcinfo->context)) == NULL)
                                414               2 :         PG_RETURN_NULL();
                                415              25 :     PG_RETURN_POINTER(res);
 7558 bruce                     416 ECB             : }
                                417                 : 
 1103 tgl                       418                 : /*
                                419                 :  * ltxtquery type recv function
                                420                 :  *
                                421                 :  * The type is sent as text in binary mode, so this is almost the same
                                422                 :  * as the input function, but it's prefixed with a version number so we
                                423                 :  * can change the binary format sent in future if necessary. For now,
                                424                 :  * only version 1 is supported.
                                425                 :  */
 1103 tgl                       426 GIC           2 : PG_FUNCTION_INFO_V1(ltxtq_recv);
                                427                 : Datum
 1103 tgl                       428 LBC           0 : ltxtq_recv(PG_FUNCTION_ARGS)
 1103 tgl                       429 ECB             : {
 1103 tgl                       430 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
 1103 tgl                       431 LBC           0 :     int         version = pq_getmsgint(buf, 1);
                                432                 :     char       *str;
                                433                 :     int         nbytes;
                                434                 :     ltxtquery  *res;
                                435                 : 
 1103 tgl                       436 UIC           0 :     if (version != 1)
 1103 tgl                       437 LBC           0 :         elog(ERROR, "unsupported ltxtquery version number %d", version);
                                438                 : 
                                439               0 :     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
  102 andrew                    440 UNC           0 :     res = queryin(str, NULL);
 1103 tgl                       441 UIC           0 :     pfree(str);
                                442                 : 
 1103 tgl                       443 LBC           0 :     PG_RETURN_POINTER(res);
 1103 tgl                       444 ECB             : }
                                445                 : 
                                446                 : /*
                                447                 :  * out function
                                448                 :  */
                                449                 : typedef struct
                                450                 : {
                                451                 :     ITEM       *curpol;
                                452                 :     char       *buf;
                                453                 :     char       *cur;
                                454                 :     char       *op;
                                455                 :     int32       buflen;
 5624 bruce                     456                 : } INFIX;
                                457                 : 
 7558 bruce                     458 EUB             : #define RESIZEBUF(inf,addsize) \
                                459                 : while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \
                                460                 : { \
 3940 peter_e                   461                 :     int32 len = (inf)->cur - (inf)->buf; \
                                462                 :     (inf)->buflen *= 2; \
                                463                 :     (inf)->buf = (char*) repalloc( (void*)(inf)->buf, (inf)->buflen ); \
                                464                 :     (inf)->cur = (inf)->buf + len; \
                                465                 : }
 7558 bruce                     466                 : 
                                467                 : /*
                                468                 :  * recursive walk on tree and print it in
                                469                 :  * infix (human-readable) view
                                470                 :  */
                                471                 : static void
 5624 bruce                     472 GIC          10 : infix(INFIX *in, bool first)
 7558 bruce                     473 EUB             : {
                                474                 :     /* since this function recurses, it could be driven to stack overflow. */
 2743 noah                      475 GIC          10 :     check_stack_depth();
                                476                 : 
 7558 bruce                     477              10 :     if (in->curpol->type == VAL)
                                478                 :     {
 7522                           479               6 :         char       *op = in->op + in->curpol->distance;
                                480                 : 
 7558                           481               8 :         RESIZEBUF(in, in->curpol->length * 2 + 5);
 7522                           482              32 :         while (*op)
                                483                 :         {
 7558                           484              26 :             *(in->cur) = *op;
                                485              26 :             op++;
                                486              26 :             in->cur++;
                                487                 :         }
 6248 neilc                     488               6 :         if (in->curpol->flag & LVAR_SUBLEXEME)
                                489                 :         {
 7558 bruce                     490               2 :             *(in->cur) = '%';
                                491               2 :             in->cur++;
                                492                 :         }
 7522                           493               6 :         if (in->curpol->flag & LVAR_INCASE)
                                494                 :         {
 7558                           495               1 :             *(in->cur) = '@';
                                496               1 :             in->cur++;
                                497                 :         }
 7522                           498               6 :         if (in->curpol->flag & LVAR_ANYEND)
                                499                 :         {
 7558                           500               3 :             *(in->cur) = '*';
                                501               3 :             in->cur++;
 7558 bruce                     502 ECB             :         }
 7558 bruce                     503 GIC           6 :         *(in->cur) = '\0';
                                504               6 :         in->curpol++;
 7558 bruce                     505 ECB             :     }
 3940 peter_e                   506 GIC           4 :     else if (in->curpol->val == (int32) '!')
 7558 bruce                     507 ECB             :     {
 7522 bruce                     508 GIC           1 :         bool        isopr = false;
 7558 bruce                     509 ECB             : 
 7558 bruce                     510 GIC           1 :         RESIZEBUF(in, 1);
 7558 bruce                     511 CBC           1 :         *(in->cur) = '!';
                                512               1 :         in->cur++;
 7558 bruce                     513 GIC           1 :         *(in->cur) = '\0';
 7558 bruce                     514 CBC           1 :         in->curpol++;
                                515               1 :         if (in->curpol->type == OPR)
 7558 bruce                     516 ECB             :         {
 7558 bruce                     517 UIC           0 :             isopr = true;
 7558 bruce                     518 LBC           0 :             RESIZEBUF(in, 2);
 7558 bruce                     519 UIC           0 :             sprintf(in->cur, "( ");
 7558 bruce                     520 LBC           0 :             in->cur = strchr(in->cur, '\0');
 7558 bruce                     521 ECB             :         }
 7558 bruce                     522 GIC           1 :         infix(in, isopr);
 7558 bruce                     523 CBC           1 :         if (isopr)
                                524                 :         {
 7558 bruce                     525 LBC           0 :             RESIZEBUF(in, 2);
                                526               0 :             sprintf(in->cur, " )");
 7558 bruce                     527 UIC           0 :             in->cur = strchr(in->cur, '\0');
 7558 bruce                     528 ECB             :         }
                                529                 :     }
                                530                 :     else
                                531                 :     {
 3940 peter_e                   532 GIC           3 :         int32       op = in->curpol->val;
 7522 bruce                     533 ECB             :         INFIX       nrm;
 7558                           534                 : 
 7558 bruce                     535 GIC           3 :         in->curpol++;
 3940 peter_e                   536 CBC           3 :         if (op == (int32) '|' && !first)
                                537                 :         {
 7558 bruce                     538 LBC           0 :             RESIZEBUF(in, 2);
 7558 bruce                     539 UIC           0 :             sprintf(in->cur, "( ");
 7558 bruce                     540 LBC           0 :             in->cur = strchr(in->cur, '\0');
 7558 bruce                     541 ECB             :         }
                                542                 : 
 7558 bruce                     543 CBC           3 :         nrm.curpol = in->curpol;
                                544               3 :         nrm.op = in->op;
                                545               3 :         nrm.buflen = 16;
 7558 bruce                     546 GIC           3 :         nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 7558 bruce                     547 EUB             : 
                                548                 :         /* get right operand */
 7558 bruce                     549 GBC           3 :         infix(&nrm, false);
 7558 bruce                     550 EUB             : 
                                551                 :         /* get & print left operand */
 7558 bruce                     552 CBC           3 :         in->curpol = nrm.curpol;
                                553               3 :         infix(in, false);
                                554                 : 
 7558 bruce                     555 EUB             :         /* print operator & right operand */
 7558 bruce                     556 GBC           3 :         RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
                                557               3 :         sprintf(in->cur, " %c %s", op, nrm.buf);
 7558 bruce                     558 GIC           3 :         in->cur = strchr(in->cur, '\0');
                                559               3 :         pfree(nrm.buf);
                                560                 : 
 3940 peter_e                   561               3 :         if (op == (int32) '|' && !first)
 7558 bruce                     562 ECB             :         {
 7558 bruce                     563 UIC           0 :             RESIZEBUF(in, 2);
                                564               0 :             sprintf(in->cur, " )");
 7558 bruce                     565 LBC           0 :             in->cur = strchr(in->cur, '\0');
 7558 bruce                     566 ECB             :         }
                                567                 :     }
 7558 bruce                     568 GBC          10 : }
 7558 bruce                     569 EUB             : 
 1103 tgl                       570 GBC           3 : PG_FUNCTION_INFO_V1(ltxtq_out);
                                571                 : Datum
 7558 bruce                     572 GIC           3 : ltxtq_out(PG_FUNCTION_ARGS)
 7558 bruce                     573 ECB             : {
 2029 tgl                       574 CBC           3 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(0);
 7522 bruce                     575 ECB             :     INFIX       nrm;
 7558                           576                 : 
 7558 bruce                     577 GIC           3 :     if (query->size == 0)
 7199 tgl                       578 UIC           0 :         ereport(ERROR,
 7199 tgl                       579 ECB             :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                580                 :                  errmsg("syntax error"),
                                581                 :                  errdetail("Empty query.")));
                                582                 : 
 7558 bruce                     583 CBC           3 :     nrm.curpol = GETQUERY(query);
 7558 bruce                     584 GIC           3 :     nrm.buflen = 32;
                                585               3 :     nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 7558 bruce                     586 CBC           3 :     *(nrm.cur) = '\0';
                                587               3 :     nrm.op = GETOPERAND(query);
                                588               3 :     infix(&nrm, true);
 7558 bruce                     589 ECB             : 
 7558 bruce                     590 GIC           3 :     PG_RETURN_POINTER(nrm.buf);
 7558 bruce                     591 ECB             : }
                                592                 : 
 1103 tgl                       593 EUB             : /*
                                594                 :  * ltxtquery type send function
                                595                 :  *
                                596                 :  * The type is sent as text in binary mode, so this is almost the same
                                597                 :  * as the output function, but it's prefixed with a version number so we
 1103 tgl                       598 ECB             :  * can change the binary format sent in future if necessary. For now,
                                599                 :  * only version 1 is supported.
                                600                 :  */
 1103 tgl                       601 GIC           2 : PG_FUNCTION_INFO_V1(ltxtq_send);
 1103 tgl                       602 ECB             : Datum
 1103 tgl                       603 UIC           0 : ltxtq_send(PG_FUNCTION_ARGS)
 1103 tgl                       604 ECB             : {
 1103 tgl                       605 UIC           0 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(0);
                                606                 :     StringInfoData buf;
 1103 tgl                       607 LBC           0 :     int         version = 1;
 1103 tgl                       608 EUB             :     INFIX       nrm;
                                609                 : 
 1103 tgl                       610 UIC           0 :     if (query->size == 0)
                                611               0 :         ereport(ERROR,
                                612                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
 1103 tgl                       613 ECB             :                  errmsg("syntax error"),
                                614                 :                  errdetail("Empty query.")));
                                615                 : 
 1103 tgl                       616 LBC           0 :     nrm.curpol = GETQUERY(query);
                                617               0 :     nrm.buflen = 32;
                                618               0 :     nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
 1103 tgl                       619 UIC           0 :     *(nrm.cur) = '\0';
 1103 tgl                       620 LBC           0 :     nrm.op = GETOPERAND(query);
 1103 tgl                       621 UIC           0 :     infix(&nrm, true);
                                622                 : 
                                623               0 :     pq_begintypsend(&buf);
                                624               0 :     pq_sendint8(&buf, version);
                                625               0 :     pq_sendtext(&buf, nrm.buf, strlen(nrm.buf));
                                626               0 :     pfree(nrm.buf);
                                627                 : 
                                628               0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                                629                 : }
        

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