LCOV - code coverage report
Current view: top level - contrib/cube - cubeparse.y (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 75 77 97.4 %
Date: 2019-08-24 15:07:19 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 "utils/float.h"
      11             : 
      12             : /* All grammar constructs return strings */
      13             : #define YYSTYPE char *
      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.  Note this only works with
      19             :  * bison >= 2.0.  However, in bison 1.875 the default is to use alloca()
      20             :  * if possible, so there's not really much problem anyhow, at least if
      21             :  * you're building with gcc.
      22             :  */
      23             : #define YYMALLOC palloc
      24             : #define YYFREE   pfree
      25             : 
      26             : static char *scanbuf;
      27             : static int  scanbuflen;
      28             : 
      29             : static int item_count(const char *s, char delim);
      30             : static NDBOX *write_box(int dim, char *str1, char *str2);
      31             : static NDBOX *write_point_as_box(int dim, char *str);
      32             : 
      33             : %}
      34             : 
      35             : /* BISON Declarations */
      36             : %parse-param {NDBOX **result}
      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 :             ereport(ERROR,
      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             :             YYABORT;
      59             :         }
      60          28 :         if (dim > CUBE_MAX_DIM)
      61             :         {
      62           0 :             ereport(ERROR,
      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             :             YYABORT;
      68             :         }
      69             : 
      70          28 :         *result = write_box( dim, $2, $4 );
      71             :     }
      72             : 
      73             :     | paren_list COMMA paren_list
      74             :     {
      75             :         int dim;
      76             : 
      77        6492 :         dim = item_count($1, ',');
      78        6492 :         if (item_count($3, ',') != dim)
      79             :         {
      80           4 :             ereport(ERROR,
      81             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      82             :                      errmsg("invalid input syntax for cube"),
      83             :                      errdetail("Different point dimensions in (%s) and (%s).",
      84             :                                $1, $3)));
      85             :             YYABORT;
      86             :         }
      87        6488 :         if (dim > CUBE_MAX_DIM)
      88             :         {
      89           2 :             ereport(ERROR,
      90             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      91             :                      errmsg("invalid input syntax for cube"),
      92             :                      errdetail("A cube cannot have more than %d dimensions.",
      93             :                                CUBE_MAX_DIM)));
      94             :             YYABORT;
      95             :         }
      96             : 
      97        6486 :         *result = write_box( dim, $1, $3 );
      98             :     }
      99             : 
     100             :     | paren_list
     101             :     {
     102             :         int dim;
     103             : 
     104         136 :         dim = item_count($1, ',');
     105         136 :         if (dim > CUBE_MAX_DIM)
     106             :         {
     107           2 :             ereport(ERROR,
     108             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     109             :                      errmsg("invalid input syntax for cube"),
     110             :                      errdetail("A cube cannot have more than %d dimensions.",
     111             :                                CUBE_MAX_DIM)));
     112             :             YYABORT;
     113             :         }
     114             : 
     115         134 :         *result = write_point_as_box(dim, $1);
     116             :     }
     117             : 
     118             :     | list
     119             :     {
     120             :         int dim;
     121             : 
     122         174 :         dim = item_count($1, ',');
     123         174 :         if (dim > CUBE_MAX_DIM)
     124             :         {
     125           0 :             ereport(ERROR,
     126             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     127             :                      errmsg("invalid input syntax for cube"),
     128             :                      errdetail("A cube cannot have more than %d dimensions.",
     129             :                                CUBE_MAX_DIM)));
     130             :             YYABORT;
     131             :         }
     132             : 
     133         174 :         *result = write_point_as_box(dim, $1);
     134             :     }
     135             :     ;
     136             : 
     137             : paren_list: O_PAREN list C_PAREN
     138             :     {
     139       13188 :         $$ = $2;
     140             :     }
     141             :     | O_PAREN C_PAREN
     142             :     {
     143           8 :         $$ = pstrdup("");
     144             :     }
     145             :     ;
     146             : 
     147             : list: CUBEFLOAT
     148             :     {
     149             :         /* alloc enough space to be sure whole list will fit */
     150       13374 :         $$ = palloc(scanbuflen + 1);
     151       13374 :         strcpy($$, $1);
     152             :     }
     153             :     | list COMMA CUBEFLOAT
     154             :     {
     155       14734 :         $$ = $1;
     156       14734 :         strcat($$, ",");
     157       14734 :         strcat($$, $3);
     158             :     }
     159             :     ;
     160             : 
     161             : %%
     162             : 
     163             : /* This assumes the string has been normalized by productions above */
     164             : static int
     165       13358 : item_count(const char *s, char delim)
     166             : {
     167       13358 :     int         nitems = 0;
     168             : 
     169       13358 :     if (s[0] != '\0')
     170             :     {
     171       13352 :         nitems++;
     172       41434 :         while ((s = strchr(s, delim)) != NULL)
     173             :         {
     174       14730 :             nitems++;
     175       14730 :             s++;
     176             :         }
     177             :     }
     178       13358 :     return nitems;
     179             : }
     180             : 
     181             : static NDBOX *
     182        6514 : write_box(int dim, char *str1, char *str2)
     183             : {
     184             :     NDBOX      *bp;
     185             :     char       *s;
     186             :     char       *endptr;
     187             :     int         i;
     188        6514 :     int         size = CUBE_SIZE(dim);
     189        6514 :     bool        point = true;
     190             : 
     191        6514 :     bp = palloc0(size);
     192        6514 :     SET_VARSIZE(bp, size);
     193        6514 :     SET_DIM(bp, dim);
     194             : 
     195        6514 :     s = str1;
     196        6514 :     i = 0;
     197        6514 :     if (dim > 0)
     198        6512 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
     199       19666 :     while ((s = strchr(s, ',')) != NULL)
     200             :     {
     201        6638 :         s++;
     202        6638 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
     203             :     }
     204             :     Assert(i == dim);
     205             : 
     206        6514 :     s = str2;
     207        6514 :     if (dim > 0)
     208             :     {
     209        6512 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
     210             :         /* code this way to do right thing with NaN */
     211        6512 :         point &= (bp->x[i] == bp->x[0]);
     212        6512 :         i++;
     213             :     }
     214       19666 :     while ((s = strchr(s, ',')) != NULL)
     215             :     {
     216        6638 :         s++;
     217        6638 :         bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
     218        6638 :         point &= (bp->x[i] == bp->x[i - dim]);
     219        6638 :         i++;
     220             :     }
     221             :     Assert(i == dim * 2);
     222             : 
     223        6514 :     if (point)
     224             :     {
     225             :         /*
     226             :          * The value turned out to be a point, ie. all the upper-right
     227             :          * coordinates were equal to the lower-left coordinates. Resize the
     228             :          * cube we constructed.  Note: we don't bother to repalloc() it
     229             :          * smaller, as it's unlikely that the tiny amount of memory freed
     230             :          * that way would be useful, and the output is always short-lived.
     231             :          */
     232          50 :         size = POINT_SIZE(dim);
     233          50 :         SET_VARSIZE(bp, size);
     234          50 :         SET_POINT_BIT(bp);
     235             :     }
     236             : 
     237        6514 :     return bp;
     238             : }
     239             : 
     240             : static NDBOX *
     241         308 : write_point_as_box(int dim, char *str)
     242             : {
     243             :     NDBOX       *bp;
     244             :     int         i,
     245             :                 size;
     246             :     char       *s;
     247             :     char       *endptr;
     248             : 
     249         308 :     size = POINT_SIZE(dim);
     250         308 :     bp = palloc0(size);
     251         308 :     SET_VARSIZE(bp, size);
     252         308 :     SET_DIM(bp, dim);
     253         308 :     SET_POINT_BIT(bp);
     254             : 
     255         308 :     s = str;
     256         308 :     i = 0;
     257         308 :     if (dim > 0)
     258         306 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
     259         854 :     while ((s = strchr(s, ',')) != NULL)
     260             :     {
     261         242 :         s++;
     262         242 :         bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
     263             :     }
     264             :     Assert(i == dim);
     265             : 
     266         306 :     return bp;
     267             : }
     268             : 
     269             : #include "cubescan.c"

Generated by: LCOV version 1.13