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.
This commit is contained in:
Tom Lane 2003-09-14 01:52:25 +00:00
parent b38c04335a
commit 03e47392e0
9 changed files with 228 additions and 431 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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;