LCOV - code coverage report
Current view: top level - contrib/cube - cubeparse.y (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 85 101 84.2 %
Date: 2024-04-19 10:11:37 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : %{
       2             : /* contrib/cube/cubeparse.y */
       3             : 
       4             : /* NdBox = [(lowerleft),(upperright)] */
       5             : /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
       6             : 
       7             : #include "postgres.h"
       8             : 
       9             : #include "cubedata.h"
      10             : #include "nodes/miscnodes.h"
      11             : #include "utils/float.h"
      12             : #include "varatt.h"
      13             : 
      14             : /* All grammar constructs return strings */
      15             : #define YYSTYPE char *
      16             : 
      17             : /*
      18             :  * Bison doesn't allocate anything that needs to live across parser calls,
      19             :  * so we can easily have it use palloc instead of malloc.  This prevents
      20             :  * memory leaks if we error out during parsing.
      21             :  */
      22             : #define YYMALLOC palloc
      23             : #define YYFREE   pfree
      24             : 
      25             : static int item_count(const char *s, char delim);
      26             : static bool write_box(int dim, char *str1, char *str2,
      27             :                       NDBOX **result, struct Node *escontext);
      28             : static bool write_point_as_box(int dim, char *str,
      29             :                                NDBOX **result, struct Node *escontext);
      30             : 
      31             : %}
      32             : 
      33             : /* BISON Declarations */
      34             : %parse-param {NDBOX **result}
      35             : %parse-param {Size scanbuflen}
      36             : %parse-param {struct Node *escontext}
      37             : %expect 0
      38             : %name-prefix="cube_yy"
      39             : 
      40             : %token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
      41             : %start box
      42             : 
      43             : /* Grammar follows */
      44             : %%
      45             : 
      46             : box: O_BRACKET paren_list COMMA paren_list C_BRACKET
      47             :     {
      48             :         int         dim;
      49             : 
      50          32 :         dim = item_count($2, ',');
      51          32 :         if (item_count($4, ',') != dim)
      52             :         {
      53           4 :             errsave(escontext,
      54             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      55             :                      errmsg("invalid input syntax for cube"),
      56             :                      errdetail("Different point dimensions in (%s) and (%s).",
      57             :                                $2, $4)));
      58           0 :             YYABORT;
      59             :         }
      60          28 :         if (dim > CUBE_MAX_DIM)
      61             :         {
      62           0 :             errsave(escontext,
      63             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      64             :                      errmsg("invalid input syntax for cube"),
      65             :                      errdetail("A cube cannot have more than %d dimensions.",
      66             :                                CUBE_MAX_DIM)));
      67           0 :             YYABORT;
      68             :         }
      69             : 
      70          28 :         if (!write_box(dim, $2, $4, result, escontext))
      71           0 :             YYABORT;
      72             :     }
      73             : 
      74             :     | paren_list COMMA paren_list
      75             :     {
      76             :         int         dim;
      77             : 
      78        6492 :         dim = item_count($1, ',');
      79        6492 :         if (item_count($3, ',') != dim)
      80             :         {
      81           4 :             errsave(escontext,
      82             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      83             :                      errmsg("invalid input syntax for cube"),
      84             :                      errdetail("Different point dimensions in (%s) and (%s).",
      85             :                                $1, $3)));
      86           0 :             YYABORT;
      87             :         }
      88        6488 :         if (dim > CUBE_MAX_DIM)
      89             :         {
      90           2 :             errsave(escontext,
      91             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      92             :                      errmsg("invalid input syntax for cube"),
      93             :                      errdetail("A cube cannot have more than %d dimensions.",
      94             :                                CUBE_MAX_DIM)));
      95           0 :             YYABORT;
      96             :         }
      97             : 
      98        6486 :         if (!write_box(dim, $1, $3, result, escontext))
      99           0 :             YYABORT;
     100             :     }
     101             : 
     102             :     | paren_list
     103             :     {
     104             :         int         dim;
     105             : 
     106         138 :         dim = item_count($1, ',');
     107         138 :         if (dim > CUBE_MAX_DIM)
     108             :         {
     109           2 :             errsave(escontext,
     110             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     111             :                      errmsg("invalid input syntax for cube"),
     112             :                      errdetail("A cube cannot have more than %d dimensions.",
     113             :                                CUBE_MAX_DIM)));
     114           0 :             YYABORT;
     115             :         }
     116             : 
     117         136 :         if (!write_point_as_box(dim, $1, result, escontext))
     118           0 :             YYABORT;
     119             :     }
     120             : 
     121             :     | list
     122             :     {
     123             :         int         dim;
     124             : 
     125         178 :         dim = item_count($1, ',');
     126         178 :         if (dim > CUBE_MAX_DIM)
     127             :         {
     128           0 :             errsave(escontext,
     129             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     130             :                      errmsg("invalid input syntax for cube"),
     131             :                      errdetail("A cube cannot have more than %d dimensions.",
     132             :                                CUBE_MAX_DIM)));
     133           0 :             YYABORT;
     134             :         }
     135             : 
     136         178 :         if (!write_point_as_box(dim, $1, result, escontext))
     137           4 :             YYABORT;
     138             :     }
     139             :     ;
     140             : 
     141             : paren_list: O_PAREN list C_PAREN
     142             :     {
     143       13192 :         $$ = $2;
     144             :     }
     145             :     | O_PAREN C_PAREN
     146             :     {
     147           8 :         $$ = pstrdup("");
     148             :     }
     149             :     ;
     150             : 
     151             : list: CUBEFLOAT
     152             :     {
     153             :         /* alloc enough space to be sure whole list will fit */
     154       13382 :         $$ = palloc(scanbuflen + 1);
     155       13382 :         strcpy($$, $1);
     156             :     }
     157             :     | list COMMA CUBEFLOAT
     158             :     {
     159       14736 :         $$ = $1;
     160       14736 :         strcat($$, ",");
     161       14736 :         strcat($$, $3);
     162             :     }
     163             :     ;
     164             : 
     165             : %%
     166             : 
     167             : /* This assumes the string has been normalized by productions above */
     168             : static int
     169       13364 : item_count(const char *s, char delim)
     170             : {
     171       13364 :     int         nitems = 0;
     172             : 
     173       13364 :     if (s[0] != '\0')
     174             :     {
     175       13358 :         nitems++;
     176       28090 :         while ((s = strchr(s, delim)) != NULL)
     177             :         {
     178       14732 :             nitems++;
     179       14732 :             s++;
     180             :         }
     181             :     }
     182       13364 :     return nitems;
     183             : }
     184             : 
     185             : static bool
     186        6514 : write_box(int dim, char *str1, char *str2,
     187             :           NDBOX **result, struct Node *escontext)
     188             : {
     189             :     NDBOX      *bp;
     190             :     char       *s;
     191             :     char       *endptr;
     192             :     int         i;
     193        6514 :     int         size = CUBE_SIZE(dim);
     194        6514 :     bool        point = true;
     195             : 
     196        6514 :     bp = palloc0(size);
     197        6514 :     SET_VARSIZE(bp, size);
     198        6514 :     SET_DIM(bp, dim);
     199             : 
     200        6514 :     s = str1;
     201        6514 :     i = 0;
     202        6514 :     if (dim > 0)
     203             :     {
     204        6512 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
     205        6512 :         if (SOFT_ERROR_OCCURRED(escontext))
     206           0 :             return false;
     207             :     }
     208       13152 :     while ((s = strchr(s, ',')) != NULL)
     209             :     {
     210        6638 :         s++;
     211        6638 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
     212        6638 :         if (SOFT_ERROR_OCCURRED(escontext))
     213           0 :             return false;
     214             :     }
     215             :     Assert(i == dim);
     216             : 
     217        6514 :     s = str2;
     218        6514 :     if (dim > 0)
     219             :     {
     220        6512 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
     221        6512 :         if (SOFT_ERROR_OCCURRED(escontext))
     222           0 :             return false;
     223             :         /* code this way to do right thing with NaN */
     224        6512 :         point &= (bp->x[i] == bp->x[0]);
     225        6512 :         i++;
     226             :     }
     227       13152 :     while ((s = strchr(s, ',')) != NULL)
     228             :     {
     229        6638 :         s++;
     230        6638 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
     231        6638 :         if (SOFT_ERROR_OCCURRED(escontext))
     232           0 :             return false;
     233        6638 :         point &= (bp->x[i] == bp->x[i - dim]);
     234        6638 :         i++;
     235             :     }
     236             :     Assert(i == dim * 2);
     237             : 
     238        6514 :     if (point)
     239             :     {
     240             :         /*
     241             :          * The value turned out to be a point, ie. all the upper-right
     242             :          * coordinates were equal to the lower-left coordinates. Resize the
     243             :          * cube we constructed.  Note: we don't bother to repalloc() it
     244             :          * smaller, as it's unlikely that the tiny amount of memory freed
     245             :          * that way would be useful, and the output is always short-lived.
     246             :          */
     247          50 :         size = POINT_SIZE(dim);
     248          50 :         SET_VARSIZE(bp, size);
     249          50 :         SET_POINT_BIT(bp);
     250             :     }
     251             : 
     252        6514 :     *result = bp;
     253        6514 :     return true;
     254             : }
     255             : 
     256             : static bool
     257         314 : write_point_as_box(int dim, char *str,
     258             :                    NDBOX **result, struct Node *escontext)
     259             : {
     260             :     NDBOX       *bp;
     261             :     int         i,
     262             :                 size;
     263             :     char       *s;
     264             :     char       *endptr;
     265             : 
     266         314 :     size = POINT_SIZE(dim);
     267         314 :     bp = palloc0(size);
     268         314 :     SET_VARSIZE(bp, size);
     269         314 :     SET_DIM(bp, dim);
     270         314 :     SET_POINT_BIT(bp);
     271             : 
     272         314 :     s = str;
     273         314 :     i = 0;
     274         314 :     if (dim > 0)
     275             :     {
     276         312 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
     277         310 :         if (SOFT_ERROR_OCCURRED(escontext))
     278           4 :             return false;
     279             :     }
     280         552 :     while ((s = strchr(s, ',')) != NULL)
     281             :     {
     282         244 :         s++;
     283         244 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
     284         244 :         if (SOFT_ERROR_OCCURRED(escontext))
     285           0 :             return false;
     286             :     }
     287             :     Assert(i == dim);
     288             : 
     289         308 :     *result = bp;
     290         308 :     return true;
     291             : }

Generated by: LCOV version 1.14