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

Generated by: LCOV version 1.14