btree operator class, too, since in PG 7.4 you can't GROUP without one.
-# $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
cubescan.c: cubescan.l
ifdef FLEX
- $(FLEX) $(FLEXFLAGS) -Pcube_yy -o'$@' $<
+ $(FLEX) $(FLEXFLAGS) -o'$@' $<
else
@$(missing) flex $< $@
endif
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
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-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);
#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
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);
{
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);
}
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;
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);
/* 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 */
{
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 */
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);
}
-- 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'
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
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
);
);
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
);
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
#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 */
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);
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"),
YYABORT;
}
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
|
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"),
YYABORT;
}
if (dim > CUBE_MAX_DIM) {
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad cube representation"),
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"),
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"),
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 {
%%
-
-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)
{
#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]+
%%
-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);
}
-- 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)
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)
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
--
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;