summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2003-09-14 01:52:25 +0000
committerTom Lane2003-09-14 01:52:25 +0000
commite8277969bcd2b317b3ff8aecdcb0dbcff6c52041 (patch)
treed77d9a0036471769387a4b9d3b84b6b9174464bb
parent6fd3119ede1d9c0c7d97aa3b2e9fab0354c4f84e (diff)
Make contrib/cube work with flex 2.5.31. Fix it up to have a real
btree operator class, too, since in PG 7.4 you can't GROUP without one.
-rw-r--r--contrib/cube/Makefile4
-rw-r--r--contrib/cube/README.cube5
-rw-r--r--contrib/cube/buffer.c85
-rw-r--r--contrib/cube/buffer.h8
-rw-r--r--contrib/cube/cube.c207
-rw-r--r--contrib/cube/cube.sql.in74
-rw-r--r--contrib/cube/cubeparse.y123
-rw-r--r--contrib/cube/cubescan.l86
-rw-r--r--contrib/cube/expected/cube.out51
9 files changed, 220 insertions, 423 deletions
diff --git a/contrib/cube/Makefile b/contrib/cube/Makefile
index 6645bc3cd3..6b200bcd50 100644
--- a/contrib/cube/Makefile
+++ b/contrib/cube/Makefile
@@ -5,7 +5,7 @@ top_builddir = ../..
include $(top_builddir)/src/Makefile.global
MODULE_big = cube
-OBJS= cube.o cubeparse.o buffer.o
+OBJS= cube.o cubeparse.o
DATA_built = cube.sql
DOCS = README.cube
@@ -28,7 +28,7 @@ endif
cubescan.c: cubescan.l
ifdef FLEX
- $(FLEX) $(FLEXFLAGS) -Pcube_yy -o'$@' $<
+ $(FLEX) $(FLEXFLAGS) -o'$@' $<
else
@$(missing) flex $< $@
endif
diff --git a/contrib/cube/README.cube b/contrib/cube/README.cube
index 42b84fb061..c4ad7b33b5 100644
--- a/contrib/cube/README.cube
+++ b/contrib/cube/README.cube
@@ -9,11 +9,6 @@ Makefile building instructions for the shared library
README.cube the file you are now reading
-buffer.c globals and buffer access utilities shared between
- the parser (cubeparse.y) and the scanner (cubescan.l)
-
-buffer.h function prototypes for buffer.c
-
cube.c the implementation of this data type in c
cube.sql.in SQL code needed to register this type with postgres
diff --git a/contrib/cube/buffer.c b/contrib/cube/buffer.c
deleted file mode 100644
index 3a1b728812..0000000000
--- a/contrib/cube/buffer.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This module defines the parse buffer and routines for setting/reading it */
-
-#include "postgres.h"
-
-static char *PARSE_BUFFER;
-static char *PARSE_BUFFER_PTR;
-static unsigned int PARSE_BUFFER_SIZE;
-static unsigned int SCANNER_POS;
-
-void set_parse_buffer(char *s);
-void reset_parse_buffer(void);
-int read_parse_buffer(void);
-char *parse_buffer(void);
-char *parse_buffer_ptr(void);
-unsigned int parse_buffer_curr_char(void);
-unsigned int parse_buffer_size(void);
-unsigned int parse_buffer_pos(void);
-
-extern void cube_flush_scanner_buffer(void); /* defined in cubescan.l */
-
-void
-set_parse_buffer(char *s)
-{
- PARSE_BUFFER = s;
- PARSE_BUFFER_SIZE = strlen(s);
- if (PARSE_BUFFER_SIZE == 0)
- ereport(ERROR,
- (errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING),
- errmsg("can't parse an empty string")));
-
- PARSE_BUFFER_PTR = PARSE_BUFFER;
- SCANNER_POS = 0;
-}
-
-void
-reset_parse_buffer(void)
-{
- PARSE_BUFFER_PTR = PARSE_BUFFER;
- SCANNER_POS = 0;
- cube_flush_scanner_buffer();
-}
-
-int
-read_parse_buffer(void)
-{
- int c;
-
- /*
- * c = *PARSE_BUFFER_PTR++; SCANNER_POS++;
- */
- c = PARSE_BUFFER[SCANNER_POS];
- if (SCANNER_POS < PARSE_BUFFER_SIZE)
- SCANNER_POS++;
- return c;
-}
-
-char *
-parse_buffer(void)
-{
- return PARSE_BUFFER;
-}
-
-unsigned int
-parse_buffer_curr_char(void)
-{
- return PARSE_BUFFER[SCANNER_POS];
-}
-
-char *
-parse_buffer_ptr(void)
-{
- return PARSE_BUFFER_PTR;
-}
-
-unsigned int
-parse_buffer_pos(void)
-{
- return SCANNER_POS;
-}
-
-unsigned int
-parse_buffer_size(void)
-{
- return PARSE_BUFFER_SIZE;
-}
diff --git a/contrib/cube/buffer.h b/contrib/cube/buffer.h
deleted file mode 100644
index eef9124dac..0000000000
--- a/contrib/cube/buffer.h
+++ /dev/null
@@ -1,8 +0,0 @@
-extern void set_parse_buffer(char *s);
-extern void reset_parse_buffer(void);
-extern int read_parse_buffer(void);
-extern char *parse_buffer(void);
-extern char *parse_buffer_ptr(void);
-extern unsigned int parse_buffer_curr_char(void);
-extern unsigned int parse_buffer_pos(void);
-extern unsigned int parse_buffer_size(void);
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 396253261d..15fce4f1f7 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -19,8 +19,10 @@
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define abs(a) ((a) < (0) ? (-a) : (a))
-extern void set_parse_buffer(char *str);
extern int cube_yyparse();
+extern void cube_yyerror(const char *message);
+extern void cube_scanner_init(const char *str);
+extern void cube_scanner_finish(void);
/*
** Input/Output routines
@@ -52,10 +54,19 @@ NDBOX *g_cube_binary_union(NDBOX * r1, NDBOX * r2, int *sizep);
bool *g_cube_same(NDBOX * b1, NDBOX * b2, bool *result);
/*
+** B-tree support functions
+*/
+bool cube_eq(NDBOX * a, NDBOX * b);
+bool cube_ne(NDBOX * a, NDBOX * b);
+bool cube_lt(NDBOX * a, NDBOX * b);
+bool cube_gt(NDBOX * a, NDBOX * b);
+bool cube_le(NDBOX * a, NDBOX * b);
+bool cube_ge(NDBOX * a, NDBOX * b);
+int32 cube_cmp(NDBOX * a, NDBOX * b);
+
+/*
** R-tree support functions
*/
-bool cube_same(NDBOX * a, NDBOX * b);
-bool cube_different(NDBOX * a, NDBOX * b);
bool cube_contains(NDBOX * a, NDBOX * b);
bool cube_contained(NDBOX * a, NDBOX * b);
bool cube_overlap(NDBOX * a, NDBOX * b);
@@ -99,10 +110,12 @@ cube_in(char *str)
{
void *result;
- set_parse_buffer(str);
+ cube_scanner_init(str);
if (cube_yyparse(&result) != 0)
- return NULL;
+ cube_yyerror("bogus input");
+
+ cube_scanner_finish();
return ((NDBOX *) result);
}
@@ -438,7 +451,7 @@ g_cube_picksplit(bytea *entryvec,
bool *
g_cube_same(NDBOX * b1, NDBOX * b2, bool *result)
{
- if (cube_same(b1, b2))
+ if (cube_eq(b1, b2))
*result = TRUE;
else
*result = FALSE;
@@ -480,7 +493,7 @@ g_cube_leaf_consistent(NDBOX * key,
retval = (bool) cube_right(key, query);
break;
case RTSameStrategyNumber:
- retval = (bool) cube_same(key, query);
+ retval = (bool) cube_eq(key, query);
break;
case RTContainsStrategyNumber:
retval = (bool) cube_contains(key, query);
@@ -754,15 +767,12 @@ cube_right(NDBOX * a, NDBOX * b)
/* make up a metric in which one box will be 'lower' than the other
-- this can be useful for sorting and to determine uniqueness */
-bool
-cube_lt(NDBOX * a, NDBOX * b)
+int32
+cube_cmp(NDBOX * a, NDBOX * b)
{
int i;
int dim;
- if ((a == NULL) || (b == NULL))
- return (FALSE);
-
dim = min(a->dim, b->dim);
/* compare the common dimensions */
@@ -770,19 +780,19 @@ cube_lt(NDBOX * a, NDBOX * b)
{
if (min(a->x[i], a->x[a->dim + i]) >
min(b->x[i], b->x[b->dim + i]))
- return (FALSE);
+ return 1;
if (min(a->x[i], a->x[a->dim + i]) <
min(b->x[i], b->x[b->dim + i]))
- return (TRUE);
+ return -1;
}
for (i = 0; i < dim; i++)
{
if (max(a->x[i], a->x[a->dim + i]) >
max(b->x[i], b->x[b->dim + i]))
- return (FALSE);
+ return 1;
if (max(a->x[i], a->x[a->dim + i]) <
max(b->x[i], b->x[b->dim + i]))
- return (TRUE);
+ return -1;
}
/* compare extra dimensions to zero */
@@ -791,186 +801,87 @@ cube_lt(NDBOX * a, NDBOX * b)
for (i = dim; i < a->dim; i++)
{
if (min(a->x[i], a->x[a->dim + i]) > 0)
- return (FALSE);
+ return 1;
if (min(a->x[i], a->x[a->dim + i]) < 0)
- return (TRUE);
+ return -1;
}
for (i = dim; i < a->dim; i++)
{
if (max(a->x[i], a->x[a->dim + i]) > 0)
- return (FALSE);
+ return 1;
if (max(a->x[i], a->x[a->dim + i]) < 0)
- return (TRUE);
+ return -1;
}
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
- return (FALSE);
+ return 1;
}
if (a->dim < b->dim)
{
for (i = dim; i < b->dim; i++)
{
if (min(b->x[i], b->x[b->dim + i]) > 0)
- return (TRUE);
+ return -1;
if (min(b->x[i], b->x[b->dim + i]) < 0)
- return (FALSE);
+ return 1;
}
for (i = dim; i < b->dim; i++)
{
if (max(b->x[i], b->x[b->dim + i]) > 0)
- return (TRUE);
+ return -1;
if (max(b->x[i], b->x[b->dim + i]) < 0)
- return (FALSE);
+ return 1;
}
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
- return (TRUE);
+ return -1;
}
- return (FALSE);
+ /* They're really equal */
+ return 0;
}
bool
-cube_gt(NDBOX * a, NDBOX * b)
+cube_eq(NDBOX * a, NDBOX * b)
{
- int i;
- int dim;
-
- if ((a == NULL) || (b == NULL))
- return (FALSE);
-
- dim = min(a->dim, b->dim);
-
- /* compare the common dimensions */
- for (i = 0; i < dim; i++)
- {
- if (min(a->x[i], a->x[a->dim + i]) <
- min(b->x[i], b->x[b->dim + i]))
- return (FALSE);
- if (min(a->x[i], a->x[a->dim + i]) >
- min(b->x[i], b->x[b->dim + i]))
- return (TRUE);
- }
- for (i = 0; i < dim; i++)
- {
- if (max(a->x[i], a->x[a->dim + i]) <
- max(b->x[i], b->x[b->dim + i]))
- return (FALSE);
- if (max(a->x[i], a->x[a->dim + i]) >
- max(b->x[i], b->x[b->dim + i]))
- return (TRUE);
- }
-
-
- /* compare extra dimensions to zero */
- if (a->dim > b->dim)
- {
- for (i = dim; i < a->dim; i++)
- {
- if (min(a->x[i], a->x[a->dim + i]) < 0)
- return (FALSE);
- if (min(a->x[i], a->x[a->dim + i]) > 0)
- return (TRUE);
- }
- for (i = dim; i < a->dim; i++)
- {
- if (max(a->x[i], a->x[a->dim + i]) < 0)
- return (FALSE);
- if (max(a->x[i], a->x[a->dim + i]) > 0)
- return (TRUE);
- }
-
- /*
- * if all common dimensions are equal, the cube with more
- * dimensions wins
- */
- return (TRUE);
- }
- if (a->dim < b->dim)
- {
- for (i = dim; i < b->dim; i++)
- {
- if (min(b->x[i], b->x[b->dim + i]) < 0)
- return (TRUE);
- if (min(b->x[i], b->x[b->dim + i]) > 0)
- return (FALSE);
- }
- for (i = dim; i < b->dim; i++)
- {
- if (max(b->x[i], b->x[b->dim + i]) < 0)
- return (TRUE);
- if (max(b->x[i], b->x[b->dim + i]) > 0)
- return (FALSE);
- }
-
- /*
- * if all common dimensions are equal, the cube with more
- * dimensions wins
- */
- return (FALSE);
- }
-
- return (FALSE);
+ return (cube_cmp(a, b) == 0);
}
-
-/* Equal */
bool
-cube_same(NDBOX * a, NDBOX * b)
+cube_ne(NDBOX * a, NDBOX * b)
{
- int i;
-
- if ((a == NULL) || (b == NULL))
- return (FALSE);
-
- /* swap the box pointers if necessary */
- if (a->dim < b->dim)
- {
- NDBOX *tmp = b;
-
- b = a;
- a = tmp;
- }
+ return (cube_cmp(a, b) != 0);
+}
- for (i = 0; i < b->dim; i++)
- {
- if (min(a->x[i], a->x[a->dim + i]) !=
- min(b->x[i], b->x[b->dim + i]))
- return (FALSE);
- if (max(a->x[i], a->x[a->dim + i]) !=
- max(b->x[i], b->x[b->dim + i]))
- return (FALSE);
- }
+bool
+cube_lt(NDBOX * a, NDBOX * b)
+{
+ return (cube_cmp(a, b) < 0);
+}
- /*
- * all dimensions of (b) are compared to those of (a); instead of
- * those in (a) absent in (b), compare (a) to zero Since both LL and
- * UR coordinates are compared to zero, we can just check them all
- * without worrying about which is which.
- */
- for (i = b->dim; i < a->dim; i++)
- {
- if (a->x[i] != 0)
- return (FALSE);
- if (a->x[i + a->dim] != 0)
- return (FALSE);
- }
+bool
+cube_gt(NDBOX * a, NDBOX * b)
+{
+ return (cube_cmp(a, b) > 0);
+}
- return (TRUE);
+bool
+cube_le(NDBOX * a, NDBOX * b)
+{
+ return (cube_cmp(a, b) <= 0);
}
-/* Different */
bool
-cube_different(NDBOX * a, NDBOX * b)
+cube_ge(NDBOX * a, NDBOX * b)
{
- return (!cube_same(a, b));
+ return (cube_cmp(a, b) >= 0);
}
diff --git a/contrib/cube/cube.sql.in b/contrib/cube/cube.sql.in
index 6afcce5aeb..b9b812f581 100644
--- a/contrib/cube/cube.sql.in
+++ b/contrib/cube/cube.sql.in
@@ -70,6 +70,20 @@ COMMENT ON FUNCTION cube_right(cube, cube) IS 'is right of (NOT IMPLEMENTED)';
-- Comparison methods
+CREATE OR REPLACE FUNCTION cube_eq(cube, cube)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION cube_eq(cube, cube) IS 'same as';
+
+CREATE OR REPLACE FUNCTION cube_ne(cube, cube)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION cube_ne(cube, cube) IS 'different';
+
CREATE OR REPLACE FUNCTION cube_lt(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
@@ -84,40 +98,47 @@ LANGUAGE 'C' IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_gt(cube, cube) IS 'greater than';
-CREATE OR REPLACE FUNCTION cube_contains(cube, cube)
+CREATE OR REPLACE FUNCTION cube_le(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-COMMENT ON FUNCTION cube_contains(cube, cube) IS 'contains';
+COMMENT ON FUNCTION cube_le(cube, cube) IS 'lower than or equal to';
-CREATE OR REPLACE FUNCTION cube_contained(cube, cube)
+CREATE OR REPLACE FUNCTION cube_ge(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-COMMENT ON FUNCTION cube_contained(cube, cube) IS 'contained in';
+COMMENT ON FUNCTION cube_ge(cube, cube) IS 'greater than or equal to';
-CREATE OR REPLACE FUNCTION cube_overlap(cube, cube)
+CREATE OR REPLACE FUNCTION cube_cmp(cube, cube)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION cube_cmp(cube, cube) IS 'btree comparison function';
+
+CREATE OR REPLACE FUNCTION cube_contains(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
+COMMENT ON FUNCTION cube_contains(cube, cube) IS 'contains';
-CREATE OR REPLACE FUNCTION cube_same(cube, cube)
+CREATE OR REPLACE FUNCTION cube_contained(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-COMMENT ON FUNCTION cube_same(cube, cube) IS 'same as';
+COMMENT ON FUNCTION cube_contained(cube, cube) IS 'contained in';
-CREATE OR REPLACE FUNCTION cube_different(cube, cube)
+CREATE OR REPLACE FUNCTION cube_overlap(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-COMMENT ON FUNCTION cube_different(cube, cube) IS 'different';
+COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
-- support routines for indexing
@@ -199,13 +220,25 @@ LANGUAGE 'C' IMMUTABLE STRICT;
CREATE OPERATOR < (
LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_lt,
- COMMUTATOR = '>',
+ COMMUTATOR = '>', NEGATOR = '>=',
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);
CREATE OPERATOR > (
LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_gt,
- COMMUTATOR = '<',
+ COMMUTATOR = '<', NEGATOR = '<=',
+ RESTRICT = scalargtsel, JOIN = scalargtjoinsel
+);
+
+CREATE OPERATOR <= (
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_le,
+ COMMUTATOR = '>=', NEGATOR = '>',
+ RESTRICT = scalarltsel, JOIN = scalarltjoinsel
+);
+
+CREATE OPERATOR >= (
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_ge,
+ COMMUTATOR = '<=', NEGATOR = '<',
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);
@@ -240,14 +273,14 @@ CREATE OPERATOR >> (
);
CREATE OPERATOR = (
- LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_same,
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_eq,
COMMUTATOR = '=', NEGATOR = '<>',
RESTRICT = eqsel, JOIN = eqjoinsel,
- SORT1 = '<', SORT2 = '<'
+ MERGES
);
CREATE OPERATOR <> (
- LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_different,
+ LEFTARG = cube, RIGHTARG = cube, PROCEDURE = cube_ne,
COMMUTATOR = '<>', NEGATOR = '=',
RESTRICT = neqsel, JOIN = neqjoinsel
);
@@ -302,7 +335,16 @@ AS 'MODULE_PATHNAME'
LANGUAGE 'C';
--- Create the operator class for indexing
+-- Create the operator classes for indexing
+
+CREATE OPERATOR CLASS cube_ops
+ DEFAULT FOR TYPE cube USING btree AS
+ OPERATOR 1 < ,
+ OPERATOR 2 <= ,
+ OPERATOR 3 = ,
+ OPERATOR 4 >= ,
+ OPERATOR 5 > ,
+ FUNCTION 1 cube_cmp(cube, cube);
CREATE OPERATOR CLASS gist_cube_ops
DEFAULT FOR TYPE cube USING gist AS
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index 917d84079e..e996a488c6 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -9,7 +9,6 @@
#include "postgres.h"
#include "cubedata.h"
-#include "buffer.h"
#undef yylex /* falure to redefine yylex will result in a call to the */
#define yylex cube_yylex /* wrong scanner when running inside the postgres backend */
@@ -17,7 +16,10 @@
extern int yylex(); /* defined as cube_yylex in cubescan.c */
extern int errno;
-int cube_yyerror( char *msg );
+static char *scanbuf;
+static int scanbuflen;
+
+void cube_yyerror(const char *message);
int cube_yyparse(void *result);
static int delim_count(char *s, char delim);
@@ -37,25 +39,9 @@ box:
O_BRACKET paren_list COMMA paren_list C_BRACKET {
int dim;
- int c = parse_buffer_curr_char();
- int pos = parse_buffer_pos();
-
- /* We can't let the parser recognize more than one valid expression:
- the job is done and memory is allocated. */
- if ( c != '\0' ) {
- /* Not at EOF */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('%c', \\%03o)",
- pos, c, c)));
- YYERROR;
- }
dim = delim_count($2, ',') + 1;
if ( (delim_count($4, ',') + 1) != dim ) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -64,7 +50,6 @@ box:
YYABORT;
}
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -79,23 +64,10 @@ box:
|
paren_list COMMA paren_list {
int dim;
- int c = parse_buffer_curr_char();
- int pos = parse_buffer_pos();
-
- if ( c != '\0' ) { /* Not at EOF */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('%c', \\%03o)",
- pos, c, c)));
- YYABORT;
- }
dim = delim_count($1, ',') + 1;
if ( (delim_count($3, ',') + 1) != dim ) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -104,7 +76,6 @@ box:
YYABORT;
}
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -119,33 +90,9 @@ box:
paren_list {
int dim;
- int c = parse_buffer_curr_char();
- int pos = parse_buffer_pos();
-
- if ( c != '\0') { /* Not at EOF */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('%c', \\%03o)",
- pos, c, c)));
- YYABORT;
- }
-
- if ( yychar != YYEOF) {
- /* There's still a lookahead token to be parsed */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('end of input', \\%03o)",
- pos, c)));
- YYABORT;
- }
dim = delim_count($1, ',') + 1;
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -161,33 +108,9 @@ box:
list {
int dim;
- int c = parse_buffer_curr_char();
- int pos = parse_buffer_pos();
-
- if ( c != '\0') { /* Not at EOF */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('%c', \\%03o)",
- pos, c, c)));
- YYABORT;
- }
-
- if ( yychar != YYEOF) {
- /* There's still a lookahead token to be parsed */
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("garbage at or before char %d, ('end of input', \\%03o)",
- pos, c)));
- YYABORT;
- }
dim = delim_count($1, ',') + 1;
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
@@ -207,8 +130,9 @@ paren_list:
list:
FLOAT {
- $$ = palloc(strlen(parse_buffer()) + 1);
- strcpy($$, $1);
+ /* alloc enough space to be sure whole list will fit */
+ $$ = palloc(scanbuflen + 1);
+ strcpy($$, $1);
}
|
list COMMA FLOAT {
@@ -220,39 +144,6 @@ list:
%%
-
-int cube_yyerror ( char *msg ) {
- char *buf = (char *) palloc(256);
- int position;
-
- yyclearin;
-
- if ( !strcmp(msg, "parse error, expecting `$'") ) {
- msg = "expecting end of input";
- }
-
- position = parse_buffer_pos() > parse_buffer_size() ? parse_buffer_pos() - 1 : parse_buffer_pos();
-
- snprintf(
- buf,
- 256,
- "%s at or before position %d, character ('%c', \\%03o), input: '%s'",
- msg,
- position,
- parse_buffer()[position - 1],
- parse_buffer()[position - 1],
- parse_buffer()
- );
-
- reset_parse_buffer();
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("bad cube representation"),
- errdetail("%s", buf)));
-
- return 0;
-}
-
static int
delim_count(char *s, char delim)
{
diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index 1b44397f46..c5e1a20f6b 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -5,33 +5,30 @@
#include "postgres.h"
-#include "buffer.h"
+/* No reason to constrain amount of data slurped */
+#define YY_READ_BUF_SIZE 16777216
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))
+/* Handles to the buffer that the lexer uses internally */
+static YY_BUFFER_STATE scanbufhandle;
+/* this is now declared in cubeparse.y: */
+/* static char *scanbuf; */
+/* static int scanbuflen; */
-/* flex screws a couple symbols when used with the -P option; fix those */
-#define YY_DECL int cube_yylex YY_PROTO(( void )); \
-int cube_yylex YY_PROTO(( void ))
-#define yylval cube_yylval
+/* flex 2.5.4 doesn't bother with a decl for this */
+int cube_yylex(void);
-
-/* redefined YY_INPUT reads byte-wise from the memory area defined in buffer.c */
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-{ \
- int c = read_parse_buffer(); \
- result = (c == '\0') ? YY_NULL : (buf[0] = c, 1); \
-}
-
-void cube_flush_scanner_buffer(void);
+void cube_scanner_init(const char *str);
+void cube_scanner_finish(void);
%}
%option 8bit
%option never-interactive
%option nounput
%option noyywrap
+%option prefix="cube_yy"
n [0-9]+
@@ -52,8 +49,61 @@ float ({integer}|{real})([eE]{integer})?
%%
-int cube_yylex();
+void
+yyerror(const char *message)
+{
+ if (*yytext == YY_END_OF_BUFFER_CHAR)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("bad cube representation"),
+ /* translator: %s is typically "syntax error" */
+ errdetail("%s at end of input", message)));
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("bad cube representation"),
+ /* translator: first %s is typically "syntax error" */
+ errdetail("%s at or near \"%s\"", message, yytext)));
+ }
+}
+
+
+/*
+ * Called before any actual parsing is done
+ */
+void
+cube_scanner_init(const char *str)
+{
+ Size slen = strlen(str);
+
+ /*
+ * Might be left over after ereport()
+ */
+ if (YY_CURRENT_BUFFER)
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+
+ /*
+ * Make a scan buffer with special termination needed by flex.
+ */
+ scanbuflen = slen;
+ scanbuf = palloc(slen + 2);
+ memcpy(scanbuf, str, slen);
+ scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
+ scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
+
+ BEGIN(INITIAL);
+}
+
-void cube_flush_scanner_buffer(void) {
- YY_FLUSH_BUFFER;
+/*
+ * Called after parsing is done to clean up after cube_scanner_init()
+ */
+void
+cube_scanner_finish(void)
+{
+ yy_delete_buffer(scanbufhandle);
+ pfree(scanbuf);
}
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 086d76fd0b..367031e983 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -257,53 +257,54 @@ SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube;
-- invalid input: parse errors
SELECT ''::cube AS cube;
-ERROR: can't parse an empty string
+ERROR: bad cube representation
+DETAIL: syntax error at end of input
SELECT 'ABC'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 1, character ('A', \101), input: 'ABC'
+DETAIL: syntax error at or near "A"
SELECT '()'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 2, character (')', \051), input: '()'
+DETAIL: syntax error at or near ")"
SELECT '[]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 2, character (']', \135), input: '[]'
+DETAIL: syntax error at or near "]"
SELECT '[()]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 3, character (')', \051), input: '[()]'
+DETAIL: syntax error at or near ")"
SELECT '[(1)]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 5, character (']', \135), input: '[(1)]'
+DETAIL: syntax error at or near "]"
SELECT '[(1),]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 6, character (']', \135), input: '[(1),]'
+DETAIL: syntax error at or near "]"
SELECT '[(1),2]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 7, character (']', \135), input: '[(1),2]'
+DETAIL: syntax error at or near "2"
SELECT '[(1),(2),(3)]'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 9, character (',', \054), input: '[(1),(2),(3)]'
+DETAIL: syntax error at or near ","
SELECT '1,'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 2, character (',', \054), input: '1,'
+DETAIL: syntax error at end of input
SELECT '1,2,'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 4, character (',', \054), input: '1,2,'
+DETAIL: syntax error at end of input
SELECT '1,,2'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 3, character (',', \054), input: '1,,2'
+DETAIL: syntax error at or near ","
SELECT '(1,)'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 4, character (')', \051), input: '(1,)'
+DETAIL: syntax error at or near ")"
SELECT '(1,2,)'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 6, character (')', \051), input: '(1,2,)'
+DETAIL: syntax error at or near ")"
SELECT '(1,,2)'::cube AS cube;
ERROR: bad cube representation
-DETAIL: syntax error at or before position 4, character (',', \054), input: '(1,,2)'
+DETAIL: syntax error at or near ","
-- invalid input: semantic errors and trailing garbage
SELECT '[(1),(2)],'::cube AS cube; -- 0
ERROR: bad cube representation
-DETAIL: garbage at or before char 9, (',', \054)
+DETAIL: syntax error at or near ","
SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
ERROR: bad cube representation
DETAIL: different point dimensions in (1,2,3) and (2,3)
@@ -312,7 +313,7 @@ ERROR: bad cube representation
DETAIL: different point dimensions in (1,2) and (1,2,3)
SELECT '(1),(2),'::cube AS cube; -- 2
ERROR: bad cube representation
-DETAIL: garbage at or before char 7, (',', \054)
+DETAIL: syntax error at or near ","
SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
ERROR: bad cube representation
DETAIL: different point dimensions in (1,2,3) and (2,3)
@@ -321,25 +322,25 @@ ERROR: bad cube representation
DETAIL: different point dimensions in (1,2) and (1,2,3)
SELECT '(1,2,3)ab'::cube AS cube; -- 4
ERROR: bad cube representation
-DETAIL: garbage at or before char 8, ('b', \142)
+DETAIL: syntax error at or near "a"
SELECT '(1,2,3)a'::cube AS cube; -- 5
ERROR: bad cube representation
-DETAIL: garbage at or before char 8, ('end of input', \000)
+DETAIL: syntax error at or near "a"
SELECT '(1,2)('::cube AS cube; -- 5
ERROR: bad cube representation
-DETAIL: garbage at or before char 6, ('end of input', \000)
+DETAIL: syntax error at or near "("
SELECT '1,2ab'::cube AS cube; -- 6
ERROR: bad cube representation
-DETAIL: garbage at or before char 4, ('b', \142)
+DETAIL: syntax error at or near "a"
SELECT '1 e7'::cube AS cube; -- 6
ERROR: bad cube representation
-DETAIL: garbage at or before char 3, ('7', \067)
+DETAIL: syntax error at or near "e"
SELECT '1,2a'::cube AS cube; -- 7
ERROR: bad cube representation
-DETAIL: garbage at or before char 4, ('end of input', \000)
+DETAIL: syntax error at or near "a"
SELECT '1..2'::cube AS cube; -- 7
ERROR: bad cube representation
-DETAIL: garbage at or before char 4, ('end of input', \000)
+DETAIL: syntax error at or near ".2"
--
-- Testing building cubes from float8 values
--
@@ -435,7 +436,7 @@ SELECT '24, 33.20'::cube != '24, 33.21'::cube AS bool;
SELECT '(2,0),(3,1)'::cube = '(2,0,0,0,0),(3,1,0,0,0)'::cube AS bool;
bool
------
- t
+ f
(1 row)
SELECT '(2,0),(3,1)'::cube = '(2,0,0,0,0),(3,1,0,0,1)'::cube AS bool;