diff --git a/contrib/cube/Makefile b/contrib/cube/Makefile index 6c5570505c..80e56aa7f8 100644 --- a/contrib/cube/Makefile +++ b/contrib/cube/Makefile @@ -1,11 +1,11 @@ -# $Header: /cvsroot/pgsql/contrib/cube/Makefile,v 1.9 2003/05/14 03:27:21 tgl Exp $ +# $Header: /cvsroot/pgsql/contrib/cube/Makefile,v 1.10 2003/09/14 01:52:25 tgl Exp $ subdir = contrib/cube 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 @@ -51,11 +53,20 @@ NDBOX *g_cube_union(bytea *entryvec, int *sizep); 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_eq(NDBOX * a, NDBOX * b) +{ + return (cube_cmp(a, b) == 0); +} + +bool +cube_ne(NDBOX * a, NDBOX * b) +{ + return (cube_cmp(a, b) != 0); +} + +bool +cube_lt(NDBOX * a, NDBOX * b) +{ + return (cube_cmp(a, b) < 0); +} + bool cube_gt(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_le(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; - } - - 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); - } - - /* - * 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); - } - - return (TRUE); + 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,6 +98,27 @@ LANGUAGE 'C' IMMUTABLE STRICT; COMMENT ON FUNCTION cube_gt(cube, cube) IS 'greater than'; +CREATE OR REPLACE FUNCTION cube_le(cube, cube) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE 'C' IMMUTABLE STRICT; + +COMMENT ON FUNCTION cube_le(cube, cube) IS 'lower than or equal to'; + +CREATE OR REPLACE FUNCTION cube_ge(cube, cube) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE 'C' IMMUTABLE STRICT; + +COMMENT ON FUNCTION cube_ge(cube, cube) IS 'greater than or equal to'; + +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' @@ -105,20 +140,6 @@ LANGUAGE 'C' IMMUTABLE STRICT; COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps'; -CREATE OR REPLACE FUNCTION cube_same(cube, cube) -RETURNS bool -AS 'MODULE_PATHNAME' -LANGUAGE 'C' IMMUTABLE STRICT; - -COMMENT ON FUNCTION cube_same(cube, cube) IS 'same as'; - -CREATE OR REPLACE FUNCTION cube_different(cube, cube) -RETURNS bool -AS 'MODULE_PATHNAME' -LANGUAGE 'C' IMMUTABLE STRICT; - -COMMENT ON FUNCTION cube_different(cube, cube) IS 'different'; - -- support routines for indexing CREATE OR REPLACE FUNCTION cube_union(cube, cube) @@ -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 cube_flush_scanner_buffer(void) { - YY_FLUSH_BUFFER; +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); +} + + +/* + * 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;