LCOV - differential code coverage report
Current view: top level - contrib/intarray - _int_bool.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 94.5 % 289 273 3 4 3 6 3 72 5 193 7 74 2
Current Date: 2023-04-08 15:15:32 Functions: 91.7 % 24 22 1 1 5 1 16 1 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  * contrib/intarray/_int_bool.c
       3                 :  */
       4                 : #include "postgres.h"
       5                 : 
       6                 : #include "_int.h"
       7                 : #include "miscadmin.h"
       8                 : #include "utils/builtins.h"
       9                 : 
      10 CBC           2 : PG_FUNCTION_INFO_V1(bqarr_in);
      11               2 : PG_FUNCTION_INFO_V1(bqarr_out);
      12               2 : PG_FUNCTION_INFO_V1(boolop);
      13               1 : PG_FUNCTION_INFO_V1(rboolop);
      14               1 : PG_FUNCTION_INFO_V1(querytree);
      15                 : 
      16                 : 
      17                 : /* parser's states */
      18                 : #define WAITOPERAND 1
      19                 : #define WAITENDOPERAND  2
      20                 : #define WAITOPERATOR    3
      21                 : 
      22                 : /*
      23                 :  * node of query tree, also used
      24                 :  * for storing polish notation in parser
      25                 :  */
      26                 : typedef struct NODE
      27                 : {
      28                 :     int32       type;
      29                 :     int32       val;
      30                 :     struct NODE *next;
      31                 : } NODE;
      32                 : 
      33                 : typedef struct
      34                 : {
      35                 :     char       *buf;
      36                 :     int32       state;
      37                 :     int32       count;
      38                 :     struct Node *escontext;
      39                 :     /* reverse polish notation in list (for temporary usage) */
      40                 :     NODE       *str;
      41                 :     /* number in str */
      42                 :     int32       num;
      43                 : } WORKSTATE;
      44                 : 
      45                 : /*
      46                 :  * get token from query string
      47                 :  */
      48                 : static int32
      49 GIC         515 : gettoken(WORKSTATE *state, int32 *val)
      50 ECB             : {
      51                 :     char        nnn[16];
      52                 :     int         innn;
      53                 : 
      54 GIC         515 :     *val = 0;                   /* default result */
      55 ECB             : 
      56 GIC         515 :     innn = 0;
      57 ECB             :     while (1)
      58                 :     {
      59 GIC         821 :         if (innn >= sizeof(nnn))
      60 LBC           0 :             return ERR;         /* buffer overrun => syntax error */
      61 GBC         821 :         switch (state->state)
      62 ECB             :         {
      63 GIC         297 :             case WAITOPERAND:
      64 CBC         297 :                 innn = 0;
      65             297 :                 if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
      66             106 :                     *(state->buf) == '-')
      67 ECB             :                 {
      68 GIC         191 :                     state->state = WAITENDOPERAND;
      69 CBC         191 :                     nnn[innn++] = *(state->buf);
      70 ECB             :                 }
      71 GIC         106 :                 else if (*(state->buf) == '!')
      72 ECB             :                 {
      73 GIC          45 :                     (state->buf)++;
      74 CBC          45 :                     *val = (int32) '!';
      75              45 :                     return OPR;
      76 ECB             :                 }
      77 GIC          61 :                 else if (*(state->buf) == '(')
      78 ECB             :                 {
      79 GIC          43 :                     state->count++;
      80 CBC          43 :                     (state->buf)++;
      81              43 :                     return OPEN;
      82 ECB             :                 }
      83 GIC          18 :                 else if (*(state->buf) != ' ')
      84 CBC           2 :                     return ERR;
      85             207 :                 break;
      86             275 :             case WAITENDOPERAND:
      87             275 :                 if (*(state->buf) >= '0' && *(state->buf) <= '9')
      88 ECB             :                 {
      89 GIC          84 :                     nnn[innn++] = *(state->buf);
      90 ECB             :                 }
      91                 :                 else
      92                 :                 {
      93                 :                     long        lval;
      94                 : 
      95 GIC         191 :                     nnn[innn] = '\0';
      96 CBC         191 :                     errno = 0;
      97             191 :                     lval = strtol(nnn, NULL, 0);
      98             191 :                     *val = (int32) lval;
      99             191 :                     if (errno != 0 || (long) *val != lval)
     100 LBC           0 :                         return ERR;
     101 GBC         191 :                     state->state = WAITOPERATOR;
     102 CBC          72 :                     return (state->count && *(state->buf) == '\0')
     103             263 :                         ? ERR : VAL;
     104 ECB             :                 }
     105 GIC          84 :                 break;
     106 CBC         249 :             case WAITOPERATOR:
     107             249 :                 if (*(state->buf) == '&' || *(state->buf) == '|')
     108 ECB             :                 {
     109 GIC         114 :                     state->state = WAITOPERAND;
     110 CBC         114 :                     *val = (int32) *(state->buf);
     111             114 :                     (state->buf)++;
     112             114 :                     return OPR;
     113 ECB             :                 }
     114 GIC         135 :                 else if (*(state->buf) == ')')
     115 ECB             :                 {
     116 GIC          43 :                     (state->buf)++;
     117 CBC          43 :                     state->count--;
     118              43 :                     return (state->count < 0) ? ERR : CLOSE;
     119 ECB             :                 }
     120 GIC          92 :                 else if (*(state->buf) == '\0')
     121 CBC          75 :                     return (state->count) ? ERR : END;
     122              17 :                 else if (*(state->buf) != ' ')
     123               2 :                     return ERR;
     124              15 :                 break;
     125 LBC           0 :             default:
     126 UBC           0 :                 return ERR;
     127 EUB             :                 break;
     128                 :         }
     129 GIC         306 :         (state->buf)++;
     130 ECB             :     }
     131                 : }
     132                 : 
     133                 : /*
     134                 :  * push new one in polish notation reverse view
     135                 :  */
     136                 : static void
     137 GIC         350 : pushquery(WORKSTATE *state, int32 type, int32 val)
     138 ECB             : {
     139 GIC         350 :     NODE       *tmp = (NODE *) palloc(sizeof(NODE));
     140 ECB             : 
     141 GIC         350 :     tmp->type = type;
     142 CBC         350 :     tmp->val = val;
     143             350 :     tmp->next = state->str;
     144             350 :     state->str = tmp;
     145             350 :     state->num++;
     146             350 : }
     147 ECB             : 
     148                 : #define STACKDEPTH  16
     149                 : 
     150                 : /*
     151                 :  * make polish notation of query
     152                 :  */
     153                 : static int32
     154 GIC         122 : makepol(WORKSTATE *state)
     155 ECB             : {
     156                 :     int32       val,
     157                 :                 type;
     158                 :     int32       stack[STACKDEPTH];
     159 GIC         122 :     int32       lenstack = 0;
     160 ECB             : 
     161                 :     /* since this function recurses, it could be driven to stack overflow */
     162 GIC         122 :     check_stack_depth();
     163 ECB             : 
     164 GIC         515 :     while ((type = gettoken(state, &val)) != END)
     165 ECB             :     {
     166 GIC         440 :         switch (type)
     167 ECB             :         {
     168 GIC         191 :             case VAL:
     169 CBC         191 :                 pushquery(state, type, val);
     170             280 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
     171              78 :                                     stack[lenstack - 1] == (int32) '!'))
     172 ECB             :                 {
     173 GIC          89 :                     lenstack--;
     174 CBC          89 :                     pushquery(state, OPR, stack[lenstack]);
     175 ECB             :                 }
     176 GIC         191 :                 break;
     177 CBC         159 :             case OPR:
     178             159 :                 if (lenstack && val == (int32) '|')
     179               3 :                     pushquery(state, OPR, val);
     180 ECB             :                 else
     181                 :                 {
     182 GIC         156 :                     if (lenstack == STACKDEPTH)
     183 UNC           0 :                         ereturn(state->escontext, ERR,
     184 EUB             :                                 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
     185                 :                                  errmsg("statement too complex")));
     186 GIC         156 :                     stack[lenstack] = val;
     187 CBC         156 :                     lenstack++;
     188 ECB             :                 }
     189 GIC         159 :                 break;
     190 CBC          43 :             case OPEN:
     191              43 :                 if (makepol(state) == ERR)
     192 LBC           0 :                     return ERR;
     193 GBC          66 :                 while (lenstack && (stack[lenstack - 1] == (int32) '&' ||
     194 CBC          18 :                                     stack[lenstack - 1] == (int32) '!'))
     195 ECB             :                 {
     196 GIC          23 :                     lenstack--;
     197 CBC          23 :                     pushquery(state, OPR, stack[lenstack]);
     198 ECB             :                 }
     199 GIC          43 :                 break;
     200 CBC          43 :             case CLOSE:
     201              57 :                 while (lenstack)
     202 ECB             :                 {
     203 GIC          14 :                     lenstack--;
     204 CBC          14 :                     pushquery(state, OPR, stack[lenstack]);
     205 ECB             :                 };
     206 GIC          43 :                 return END;
     207 ECB             :                 break;
     208 GIC           4 :             case ERR:
     209 ECB             :             default:
     210 GNC           4 :                 ereturn(state->escontext, ERR,
     211 ECB             :                         (errcode(ERRCODE_SYNTAX_ERROR),
     212                 :                          errmsg("syntax error")));
     213                 :         }
     214                 :     }
     215                 : 
     216 CBC         105 :     while (lenstack)
     217                 :     {
     218              30 :         lenstack--;
     219              30 :         pushquery(state, OPR, stack[lenstack]);
     220                 :     };
     221              75 :     return END;
     222                 : }
     223                 : 
     224                 : typedef struct
     225                 : {
     226                 :     int32      *arrb;
     227                 :     int32      *arre;
     228                 : } CHKVAL;
     229                 : 
     230                 : /*
     231                 :  * is there value 'val' in (sorted) array or not ?
     232                 :  */
     233                 : static bool
     234          223162 : checkcondition_arr(void *checkval, ITEM *item, void *options)
     235                 : {
     236          223162 :     int32      *StopLow = ((CHKVAL *) checkval)->arrb;
     237          223162 :     int32      *StopHigh = ((CHKVAL *) checkval)->arre;
     238                 :     int32      *StopMiddle;
     239                 : 
     240                 :     /* Loop invariant: StopLow <= val < StopHigh */
     241                 : 
     242          770743 :     while (StopLow < StopHigh)
     243                 :     {
     244          556778 :         StopMiddle = StopLow + (StopHigh - StopLow) / 2;
     245          556778 :         if (*StopMiddle == item->val)
     246            9197 :             return true;
     247          547581 :         else if (*StopMiddle < item->val)
     248          129422 :             StopLow = StopMiddle + 1;
     249                 :         else
     250          418159 :             StopHigh = StopMiddle;
     251                 :     }
     252          213965 :     return false;
     253                 : }
     254                 : 
     255                 : static bool
     256           43839 : checkcondition_bit(void *checkval, ITEM *item, void *siglen)
     257                 : {
     258           43839 :     return GETBIT(checkval, HASHVAL(item->val, (int) (intptr_t) siglen));
     259                 : }
     260                 : 
     261                 : /*
     262                 :  * evaluate boolean expression, using chkcond() to test the primitive cases
     263                 :  */
     264                 : static bool
     265          693384 : execute(ITEM *curitem, void *checkval, void *options, bool calcnot,
     266                 :         bool (*chkcond) (void *checkval, ITEM *item, void *options))
     267                 : {
     268                 :     /* since this function recurses, it could be driven to stack overflow */
     269          693384 :     check_stack_depth();
     270                 : 
     271          693384 :     if (curitem->type == VAL)
     272          295991 :         return (*chkcond) (checkval, curitem, options);
     273          397393 :     else if (curitem->val == (int32) '!')
     274                 :     {
     275                 :         return calcnot ?
     276          118943 :             ((execute(curitem - 1, checkval, options, calcnot, chkcond)) ? false : true)
     277          291288 :             : true;
     278                 :     }
     279          225048 :     else if (curitem->val == (int32) '&')
     280                 :     {
     281          121854 :         if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
     282           62355 :             return execute(curitem - 1, checkval, options, calcnot, chkcond);
     283                 :         else
     284           59499 :             return false;
     285                 :     }
     286                 :     else
     287                 :     {                           /* |-operator */
     288          103194 :         if (execute(curitem + curitem->left, checkval, options, calcnot, chkcond))
     289            5706 :             return true;
     290                 :         else
     291           97488 :             return execute(curitem - 1, checkval, options, calcnot, chkcond);
     292                 :     }
     293                 : }
     294                 : 
     295                 : /*
     296                 :  * signconsistent & execconsistent called by *_consistent
     297                 :  */
     298                 : bool
     299           50701 : signconsistent(QUERYTYPE *query, BITVECP sign, int siglen, bool calcnot)
     300                 : {
     301          101402 :     return execute(GETQUERY(query) + query->size - 1,
     302           50701 :                    (void *) sign, (void *) (intptr_t) siglen, calcnot,
     303                 :                    checkcondition_bit);
     304                 : }
     305                 : 
     306                 : /* Array must be sorted! */
     307                 : bool
     308           55498 : execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
     309                 : {
     310                 :     CHKVAL      chkval;
     311                 : 
     312           55498 :     CHECKARRVALID(array);
     313           55498 :     chkval.arrb = ARRPTR(array);
     314           55498 :     chkval.arre = chkval.arrb + ARRNELEMS(array);
     315           55498 :     return execute(GETQUERY(query) + query->size - 1,
     316                 :                    (void *) &chkval, NULL, calcnot,
     317                 :                    checkcondition_arr);
     318                 : }
     319                 : 
     320                 : typedef struct
     321                 : {
     322                 :     ITEM       *first;
     323                 :     bool       *mapped_check;
     324                 : } GinChkVal;
     325                 : 
     326                 : static bool
     327           28990 : checkcondition_gin(void *checkval, ITEM *item, void *options)
     328                 : {
     329           28990 :     GinChkVal  *gcv = (GinChkVal *) checkval;
     330                 : 
     331           28990 :     return gcv->mapped_check[item - gcv->first];
     332                 : }
     333                 : 
     334                 : bool
     335           14901 : gin_bool_consistent(QUERYTYPE *query, bool *check)
     336                 : {
     337                 :     GinChkVal   gcv;
     338           14901 :     ITEM       *items = GETQUERY(query);
     339                 :     int         i,
     340           14901 :                 j = 0;
     341                 : 
     342           14901 :     if (query->size <= 0)
     343 UBC           0 :         return false;
     344                 : 
     345                 :     /*
     346                 :      * Set up data for checkcondition_gin.  This must agree with the query
     347                 :      * extraction code in ginint4_queryextract.
     348                 :      */
     349 CBC       14901 :     gcv.first = items;
     350           14901 :     gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
     351           82210 :     for (i = 0; i < query->size; i++)
     352                 :     {
     353           67309 :         if (items[i].type == VAL)
     354           30964 :             gcv.mapped_check[i] = check[j++];
     355                 :     }
     356                 : 
     357           14901 :     return execute(GETQUERY(query) + query->size - 1,
     358                 :                    (void *) &gcv, NULL, true,
     359                 :                    checkcondition_gin);
     360                 : }
     361                 : 
     362                 : static bool
     363              36 : contains_required_value(ITEM *curitem)
     364                 : {
     365                 :     /* since this function recurses, it could be driven to stack overflow */
     366              36 :     check_stack_depth();
     367                 : 
     368              36 :     if (curitem->type == VAL)
     369              14 :         return true;
     370              22 :     else if (curitem->val == (int32) '!')
     371                 :     {
     372                 :         /*
     373                 :          * Assume anything under a NOT is non-required.  For some cases with
     374                 :          * nested NOTs, we could prove there's a required value, but it seems
     375                 :          * unlikely to be worth the trouble.
     376                 :          */
     377               6 :         return false;
     378                 :     }
     379              16 :     else if (curitem->val == (int32) '&')
     380                 :     {
     381                 :         /* If either side has a required value, we're good */
     382              10 :         if (contains_required_value(curitem + curitem->left))
     383               8 :             return true;
     384                 :         else
     385               2 :             return contains_required_value(curitem - 1);
     386                 :     }
     387                 :     else
     388                 :     {                           /* |-operator */
     389                 :         /* Both sides must have required values */
     390               6 :         if (contains_required_value(curitem + curitem->left))
     391               6 :             return contains_required_value(curitem - 1);
     392                 :         else
     393 UBC           0 :             return false;
     394                 :     }
     395                 : }
     396                 : 
     397                 : bool
     398 CBC          12 : query_has_required_values(QUERYTYPE *query)
     399                 : {
     400              12 :     if (query->size <= 0)
     401 UBC           0 :         return false;
     402 CBC          12 :     return contains_required_value(GETQUERY(query) + query->size - 1);
     403                 : }
     404                 : 
     405                 : /*
     406                 :  * boolean operations
     407                 :  */
     408                 : Datum
     409 UBC           0 : rboolop(PG_FUNCTION_ARGS)
     410                 : {
     411                 :     /* just reverse the operands */
     412               0 :     return DirectFunctionCall2(boolop,
     413                 :                                PG_GETARG_DATUM(1),
     414                 :                                PG_GETARG_DATUM(0));
     415                 : }
     416                 : 
     417                 : Datum
     418 CBC       68450 : boolop(PG_FUNCTION_ARGS)
     419                 : {
     420           68450 :     ArrayType  *val = PG_GETARG_ARRAYTYPE_P_COPY(0);
     421           68450 :     QUERYTYPE  *query = PG_GETARG_QUERYTYPE_P(1);
     422                 :     CHKVAL      chkval;
     423                 :     bool        result;
     424                 : 
     425           68450 :     CHECKARRVALID(val);
     426           68450 :     PREPAREARR(val);
     427           68450 :     chkval.arrb = ARRPTR(val);
     428           68450 :     chkval.arre = chkval.arrb + ARRNELEMS(val);
     429           68450 :     result = execute(GETQUERY(query) + query->size - 1,
     430                 :                      &chkval, NULL, true,
     431                 :                      checkcondition_arr);
     432           68450 :     pfree(val);
     433                 : 
     434           68450 :     PG_FREE_IF_COPY(query, 1);
     435           68450 :     PG_RETURN_BOOL(result);
     436                 : }
     437                 : 
     438                 : static void
     439             348 : findoprnd(ITEM *ptr, int32 *pos)
     440                 : {
     441                 :     /* since this function recurses, it could be driven to stack overflow. */
     442             348 :     check_stack_depth();
     443                 : 
     444                 : #ifdef BS_DEBUG
     445                 :     elog(DEBUG3, (ptr[*pos].type == OPR) ?
     446                 :          "%d  %c" : "%d  %d", *pos, ptr[*pos].val);
     447                 : #endif
     448             348 :     if (ptr[*pos].type == VAL)
     449                 :     {
     450             189 :         ptr[*pos].left = 0;
     451             189 :         (*pos)--;
     452                 :     }
     453             159 :     else if (ptr[*pos].val == (int32) '!')
     454                 :     {
     455              45 :         ptr[*pos].left = -1;
     456              45 :         (*pos)--;
     457              45 :         findoprnd(ptr, pos);
     458                 :     }
     459                 :     else
     460                 :     {
     461             114 :         ITEM       *curitem = &ptr[*pos];
     462             114 :         int32       tmp = *pos;
     463                 : 
     464             114 :         (*pos)--;
     465             114 :         findoprnd(ptr, pos);
     466             114 :         curitem->left = *pos - tmp;
     467             114 :         findoprnd(ptr, pos);
     468                 :     }
     469             348 : }
     470                 : 
     471                 : 
     472                 : /*
     473                 :  * input
     474                 :  */
     475                 : Datum
     476              79 : bqarr_in(PG_FUNCTION_ARGS)
     477                 : {
     478              79 :     char       *buf = (char *) PG_GETARG_POINTER(0);
     479                 :     WORKSTATE   state;
     480                 :     int32       i;
     481                 :     QUERYTYPE  *query;
     482                 :     int32       commonlen;
     483                 :     ITEM       *ptr;
     484                 :     NODE       *tmp;
     485              79 :     int32       pos = 0;
     486 GNC          79 :     struct Node *escontext = fcinfo->context;
     487 ECB             : 
     488                 : #ifdef BS_DEBUG
     489                 :     StringInfoData pbuf;
     490                 : #endif
     491                 : 
     492 GIC          79 :     state.buf = buf;
     493 CBC          79 :     state.state = WAITOPERAND;
     494              79 :     state.count = 0;
     495              79 :     state.num = 0;
     496              79 :     state.str = NULL;
     497 GNC          79 :     state.escontext = escontext;
     498 ECB             : 
     499                 :     /* make polish notation (postfix, but in reverse order) */
     500 GNC          79 :     if (makepol(&state) == ERR)
     501               4 :         PG_RETURN_NULL();
     502 GIC          75 :     if (!state.num)
     503 UNC           0 :         ereturn(escontext, (Datum) 0,
     504 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     505                 :                  errmsg("empty query")));
     506 EUB             : 
     507 GIC          75 :     if (state.num > QUERYTYPEMAXITEMS)
     508 UNC           0 :         ereturn(escontext, (Datum) 0,
     509                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     510 ECB             :                  errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
     511 EUB             :                         state.num, (int) QUERYTYPEMAXITEMS)));
     512 GIC          75 :     commonlen = COMPUTESIZE(state.num);
     513                 : 
     514              75 :     query = (QUERYTYPE *) palloc(commonlen);
     515 CBC          75 :     SET_VARSIZE(query, commonlen);
     516 GIC          75 :     query->size = state.num;
     517 CBC          75 :     ptr = GETQUERY(query);
     518 ECB             : 
     519 CBC         423 :     for (i = state.num - 1; i >= 0; i--)
     520 ECB             :     {
     521 GIC         348 :         ptr[i].type = state.str->type;
     522 CBC         348 :         ptr[i].val = state.str->val;
     523 GIC         348 :         tmp = state.str->next;
     524 CBC         348 :         pfree(state.str);
     525             348 :         state.str = tmp;
     526 ECB             :     }
     527                 : 
     528 CBC          75 :     pos = query->size - 1;
     529 GIC          75 :     findoprnd(ptr, &pos);
     530                 : #ifdef BS_DEBUG
     531 ECB             :     initStringInfo(&pbuf);
     532                 :     for (i = 0; i < query->size; i++)
     533                 :     {
     534                 :         if (ptr[i].type == OPR)
     535                 :             appendStringInfo(&pbuf, "%c(%d) ", ptr[i].val, ptr[i].left);
     536                 :         else
     537                 :             appendStringInfo(&pbuf, "%d ", ptr[i].val);
     538                 :     }
     539                 :     elog(DEBUG3, "POR: %s", pbuf.data);
     540                 :     pfree(pbuf.data);
     541                 : #endif
     542                 : 
     543 GIC          75 :     PG_RETURN_POINTER(query);
     544                 : }
     545                 : 
     546 ECB             : 
     547                 : /*
     548                 :  * out function
     549                 :  */
     550                 : typedef struct
     551                 : {
     552                 :     ITEM       *curpol;
     553                 :     char       *buf;
     554                 :     char       *cur;
     555                 :     int32       buflen;
     556                 : } INFIX;
     557                 : 
     558                 : #define RESIZEBUF(inf,addsize) while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) { \
     559                 :     int32 len = inf->cur - inf->buf; \
     560                 :     inf->buflen *= 2; \
     561                 :     inf->buf = (char*) repalloc( (void*)inf->buf, inf->buflen ); \
     562                 :     inf->cur = inf->buf + len; \
     563                 : }
     564                 : 
     565                 : static void
     566 GIC         180 : infix(INFIX *in, bool first)
     567                 : {
     568                 :     /* since this function recurses, it could be driven to stack overflow. */
     569 CBC         180 :     check_stack_depth();
     570                 : 
     571 GIC         180 :     if (in->curpol->type == VAL)
     572 ECB             :     {
     573 GIC          95 :         RESIZEBUF(in, 11);
     574 CBC          95 :         sprintf(in->cur, "%d", in->curpol->val);
     575 GIC          95 :         in->cur = strchr(in->cur, '\0');
     576 CBC          95 :         in->curpol--;
     577 ECB             :     }
     578 CBC          85 :     else if (in->curpol->val == (int32) '!')
     579 ECB             :     {
     580 GIC          27 :         bool        isopr = false;
     581 ECB             : 
     582 GIC          27 :         RESIZEBUF(in, 1);
     583 CBC          27 :         *(in->cur) = '!';
     584 GIC          27 :         in->cur++;
     585 CBC          27 :         *(in->cur) = '\0';
     586              27 :         in->curpol--;
     587              27 :         if (in->curpol->type == OPR)
     588 ECB             :         {
     589 CBC           6 :             isopr = true;
     590               6 :             RESIZEBUF(in, 2);
     591 GIC           6 :             sprintf(in->cur, "( ");
     592 CBC           6 :             in->cur = strchr(in->cur, '\0');
     593 ECB             :         }
     594 CBC          27 :         infix(in, isopr);
     595              27 :         if (isopr)
     596                 :         {
     597               6 :             RESIZEBUF(in, 2);
     598               6 :             sprintf(in->cur, " )");
     599 GIC           6 :             in->cur = strchr(in->cur, '\0');
     600 ECB             :         }
     601                 :     }
     602                 :     else
     603                 :     {
     604 GIC          58 :         int32       op = in->curpol->val;
     605                 :         INFIX       nrm;
     606                 : 
     607 CBC          58 :         in->curpol--;
     608 GIC          58 :         if (op == (int32) '|' && !first)
     609                 :         {
     610 CBC          10 :             RESIZEBUF(in, 2);
     611              10 :             sprintf(in->cur, "( ");
     612 GIC          10 :             in->cur = strchr(in->cur, '\0');
     613 ECB             :         }
     614                 : 
     615 CBC          58 :         nrm.curpol = in->curpol;
     616 GIC          58 :         nrm.buflen = 16;
     617              58 :         nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
     618 ECB             : 
     619                 :         /* get right operand */
     620 CBC          58 :         infix(&nrm, false);
     621                 : 
     622                 :         /* get & print left operand */
     623              58 :         in->curpol = nrm.curpol;
     624 GIC          58 :         infix(in, false);
     625                 : 
     626 ECB             :         /* print operator & right operand */
     627 CBC          62 :         RESIZEBUF(in, 3 + (nrm.cur - nrm.buf));
     628 GIC          58 :         sprintf(in->cur, " %c %s", op, nrm.buf);
     629              58 :         in->cur = strchr(in->cur, '\0');
     630 CBC          58 :         pfree(nrm.buf);
     631 ECB             : 
     632 CBC          58 :         if (op == (int32) '|' && !first)
     633 ECB             :         {
     634 GIC          10 :             RESIZEBUF(in, 2);
     635 CBC          10 :             sprintf(in->cur, " )");
     636 GIC          10 :             in->cur = strchr(in->cur, '\0');
     637 ECB             :         }
     638                 :     }
     639 CBC         180 : }
     640                 : 
     641                 : 
     642 ECB             : Datum
     643 GIC          37 : bqarr_out(PG_FUNCTION_ARGS)
     644                 : {
     645              37 :     QUERYTYPE  *query = PG_GETARG_QUERYTYPE_P(0);
     646 ECB             :     INFIX       nrm;
     647                 : 
     648 CBC          37 :     if (query->size == 0)
     649 UIC           0 :         ereport(ERROR,
     650                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     651 ECB             :                  errmsg("empty query")));
     652 EUB             : 
     653 GIC          37 :     nrm.curpol = GETQUERY(query) + query->size - 1;
     654              37 :     nrm.buflen = 32;
     655              37 :     nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
     656 CBC          37 :     *(nrm.cur) = '\0';
     657              37 :     infix(&nrm, true);
     658 ECB             : 
     659 CBC          37 :     PG_FREE_IF_COPY(query, 0);
     660              37 :     PG_RETURN_POINTER(nrm.buf);
     661                 : }
     662 ECB             : 
     663                 : 
     664                 : /* Useless old "debugging" function for a fundamentally wrong algorithm */
     665                 : Datum
     666 UIC           0 : querytree(PG_FUNCTION_ARGS)
     667                 : {
     668               0 :     elog(ERROR, "querytree is no longer implemented");
     669 EUB             :     PG_RETURN_NULL();
     670                 : }
        

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