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

Generated by: LCOV version 1.14