LCOV - code coverage report
Current view: top level - contrib/cube - cubeparse.y (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 84.2 % 101 85
Test Date: 2026-03-03 03:15:11 Functions: 100.0 % 3 3
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           16 :         dim = item_count($2, ',');
      52           16 :         if (item_count($4, ',') != dim)
      53              :         {
      54            2 :             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           14 :         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           14 :         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         3246 :         dim = item_count($1, ',');
      82         3246 :         if (item_count($3, ',') != dim)
      83              :         {
      84            2 :             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         3244 :         if (dim > CUBE_MAX_DIM)
      92              :         {
      93            1 :             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         3243 :         if (!write_box(dim, $1, $3, result, escontext))
     102            0 :             YYABORT;
     103              :     }
     104              : 
     105              :     | paren_list
     106              :     {
     107              :         int         dim;
     108              : 
     109           69 :         dim = item_count($1, ',');
     110           69 :         if (dim > CUBE_MAX_DIM)
     111              :         {
     112            1 :             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           68 :         if (!write_point_as_box(dim, $1, result, escontext))
     121            0 :             YYABORT;
     122              :     }
     123              : 
     124              :     | list
     125              :     {
     126              :         int         dim;
     127              : 
     128           89 :         dim = item_count($1, ',');
     129           89 :         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           89 :         if (!write_point_as_box(dim, $1, result, escontext))
     140            2 :             YYABORT;
     141              :     }
     142              :     ;
     143              : 
     144              : paren_list: O_PAREN list C_PAREN
     145              :     {
     146         6596 :         $$ = $2;
     147              :     }
     148              :     | O_PAREN C_PAREN
     149              :     {
     150            4 :         $$ = pstrdup("");
     151              :     }
     152              :     ;
     153              : 
     154              : list: CUBEFLOAT
     155              :     {
     156              :         /* alloc enough space to be sure whole list will fit */
     157         6691 :         $$ = palloc(scanbuflen + 1);
     158         6691 :         strcpy($$, $1);
     159              :     }
     160              :     | list COMMA CUBEFLOAT
     161              :     {
     162         7368 :         $$ = $1;
     163         7368 :         strcat($$, ",");
     164         7368 :         strcat($$, $3);
     165              :     }
     166              :     ;
     167              : 
     168              : %%
     169              : 
     170              : /* This assumes the string has been normalized by productions above */
     171              : static int
     172         6682 : item_count(const char *s, char delim)
     173              : {
     174         6682 :     int         nitems = 0;
     175              : 
     176         6682 :     if (s[0] != '\0')
     177              :     {
     178         6679 :         nitems++;
     179        14045 :         while ((s = strchr(s, delim)) != NULL)
     180              :         {
     181         7366 :             nitems++;
     182         7366 :             s++;
     183              :         }
     184              :     }
     185         6682 :     return nitems;
     186              : }
     187              : 
     188              : static bool
     189         3257 : 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         3257 :     int         size = CUBE_SIZE(dim);
     197         3257 :     bool        point = true;
     198              : 
     199         3257 :     bp = palloc0(size);
     200         3257 :     SET_VARSIZE(bp, size);
     201         3257 :     SET_DIM(bp, dim);
     202              : 
     203         3257 :     s = str1;
     204         3257 :     i = 0;
     205         3257 :     if (dim > 0)
     206              :     {
     207         3256 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
     208         3256 :         if (SOFT_ERROR_OCCURRED(escontext))
     209            0 :             return false;
     210              :     }
     211         6576 :     while ((s = strchr(s, ',')) != NULL)
     212              :     {
     213         3319 :         s++;
     214         3319 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
     215         3319 :         if (SOFT_ERROR_OCCURRED(escontext))
     216            0 :             return false;
     217              :     }
     218              :     Assert(i == dim);
     219              : 
     220         3257 :     s = str2;
     221         3257 :     if (dim > 0)
     222              :     {
     223         3256 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
     224         3256 :         if (SOFT_ERROR_OCCURRED(escontext))
     225            0 :             return false;
     226              :         /* code this way to do right thing with NaN */
     227         3256 :         point &= (bp->x[i] == bp->x[0]);
     228         3256 :         i++;
     229              :     }
     230         6576 :     while ((s = strchr(s, ',')) != NULL)
     231              :     {
     232         3319 :         s++;
     233         3319 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
     234         3319 :         if (SOFT_ERROR_OCCURRED(escontext))
     235            0 :             return false;
     236         3319 :         point &= (bp->x[i] == bp->x[i - dim]);
     237         3319 :         i++;
     238              :     }
     239              :     Assert(i == dim * 2);
     240              : 
     241         3257 :     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           25 :         size = POINT_SIZE(dim);
     251           25 :         SET_VARSIZE(bp, size);
     252           25 :         SET_POINT_BIT(bp);
     253              :     }
     254              : 
     255         3257 :     *result = bp;
     256         3257 :     return true;
     257              : }
     258              : 
     259              : static bool
     260          157 : 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          157 :     size = POINT_SIZE(dim);
     270          157 :     bp = palloc0(size);
     271          157 :     SET_VARSIZE(bp, size);
     272          157 :     SET_DIM(bp, dim);
     273          157 :     SET_POINT_BIT(bp);
     274              : 
     275          157 :     s = str;
     276          157 :     i = 0;
     277          157 :     if (dim > 0)
     278              :     {
     279          156 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
     280          155 :         if (SOFT_ERROR_OCCURRED(escontext))
     281            2 :             return false;
     282              :     }
     283          276 :     while ((s = strchr(s, ',')) != NULL)
     284              :     {
     285          122 :         s++;
     286          122 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
     287          122 :         if (SOFT_ERROR_OCCURRED(escontext))
     288            0 :             return false;
     289              :     }
     290              :     Assert(i == dim);
     291              : 
     292          154 :     *result = bp;
     293          154 :     return true;
     294              : }
        

Generated by: LCOV version 2.0-1