1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-20 15:22:23 +03:00

Remove backdoor strings from scan.l for DEFAULT and CHECK.

Reconstruct string input for DEFAULT and CHECK.
Add DOUBLE PRECISION, CHARACTER (VARYING) SQL-92 data types.
This commit is contained in:
Thomas G. Lockhart
1997-09-13 03:15:46 +00:00
parent 9ea74630fc
commit bc85dbf893

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.44 1997/09/12 22:14:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.45 1997/09/13 03:15:46 thomas Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -35,6 +35,7 @@
#include "postgres.h" #include "postgres.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/print.h"
#include "parser/gramparse.h" #include "parser/gramparse.h"
#include "parser/catalog_utils.h" #include "parser/catalog_utils.h"
#include "parser/parse_query.h" #include "parser/parse_query.h"
@ -49,11 +50,6 @@ static bool QueryIsRule = FALSE;
static Node *saved_In_Expr; static Node *saved_In_Expr;
extern List *parsetree; extern List *parsetree;
extern int CurScanPosition(void);
extern int DefaultStartPosition;
extern int CheckStartPosition;
extern char *parseString;
/* /*
* If you need access to certain yacc-generated variables and find that * If you need access to certain yacc-generated variables and find that
* they're static by default, uncomment the next line. (this is not a * they're static by default, uncomment the next line. (this is not a
@ -63,6 +59,8 @@ extern char *parseString;
static char *xlateSqlType(char *); static char *xlateSqlType(char *);
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
static List *makeConstantList( A_Const *node);
static char *FlattenStringList(List *list);
/* old versions of flex define this as a macro */ /* old versions of flex define this as a macro */
#if defined(yywrap) #if defined(yywrap)
@ -117,17 +115,17 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt, ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
%type <str> txname %type <str> txname, char_type
%type <node> SubSelect %type <node> SubSelect
%type <str> join_clause, join_type, join_outer, join_spec %type <str> join_expr, join_outer, join_spec
%type <boolean> join_qual, TriggerActionTime, TriggerForSpec %type <boolean> TriggerActionTime, TriggerForSpec
%type <str> datetime, TriggerEvents, TriggerFuncArg %type <str> DateTime, TriggerEvents, TriggerFuncArg
%type <str> relation_name, copy_file_name, copy_delimiter, def_name, %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
database_name, access_method_clause, access_method, attr_name, database_name, access_method_clause, access_method, attr_name,
class, index_name, name, file_name, recipe_name, class, index_name, name, file_name, recipe_name,
var_name, aggr_argtype, OptDefault var_name, aggr_argtype
%type <constrdef> ConstraintElem, ConstraintDef %type <constrdef> ConstraintElem, ConstraintDef
@ -147,13 +145,14 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
opt_column_list, columnList, opt_va_list, va_list, opt_column_list, columnList, opt_va_list, va_list,
sort_clause, sortby_list, index_params, index_list, name_list, sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_list, opt_array_bounds, nest_array_bounds, from_clause, from_list, opt_array_bounds, nest_array_bounds,
expr_list, default_expr_list, attrs, res_target_list, res_target_list2, expr_list, attrs, res_target_list, res_target_list2,
def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
%type <list> union_clause, select_list %type <list> union_clause, select_list
%type <list> join_list %type <list> join_list
%type <sortgroupby> join_using %type <sortgroupby> join_using
%type <node> position_expr
%type <list> extract_list, position_list %type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list %type <list> substr_list, substr_from, substr_for, trim_list
%type <list> interval_opts %type <list> interval_opts
@ -178,7 +177,6 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <defelt> def_elem %type <defelt> def_elem
%type <node> def_arg, columnElem, where_clause, %type <node> def_arg, columnElem, where_clause,
a_expr, a_expr_or_null, AexprConst, a_expr, a_expr_or_null, AexprConst,
default_expr, default_expr_or_null,
in_expr_nodes, not_in_expr_nodes, in_expr_nodes, not_in_expr_nodes,
having_clause having_clause
%type <value> NumConst %type <value> NumConst
@ -197,6 +195,9 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <str> Id, date, var_value, zone_value %type <str> Id, date, var_value, zone_value
%type <str> ColId %type <str> ColId
%type <list> default_expr
%type <str> opt_default
%type <list> constraint_elem
/* /*
* If you make any token changes, remember to: * If you make any token changes, remember to:
@ -208,30 +209,34 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE, %token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC, AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY, BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
CURRENT, CURSOR, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC, COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, EXTRACT, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
HAVING, HEAVY, HOURINTERVAL, FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY, HOURINTERVAL,
IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTERVAL, INTO, IS, ISNULL, IN, INDEX, INHERITS, INNERJOIN, INSERT, INTERVAL, INSTEAD, INTO, IS, ISNULL,
JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL, JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL, NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN, OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
PNULL, POSITION, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE, PNULL, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, SUBSTRING, SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE,
TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER, TRIM, TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER,
UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES, UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE %token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
/* SQL-92 support */
%token EXTRACT, POSITION, SUBSTRING, TRIM
%token DOUBLE, PRECISION
%token CHARACTER, VARYING
/* Special keywords, not in the query language - see the "lex" file */ /* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, SCONST, Op %token <str> IDENT, SCONST, Op
%token <ival> ICONST, PARAM %token <ival> ICONST, PARAM
%token <dval> FCONST %token <dval> FCONST
/* these are not real. they are here so that they gets generated as #define's*/ /* these are not real. they are here so that they get generated as #define's*/
%token OP %token OP
/* precedence */ /* precedence */
@ -387,7 +392,7 @@ AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
* called out in SQL92 date/time definitions. So, check explicitly for "timestamp" * called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
* and "time". - thomas 1997-07-14 * and "time". - thomas 1997-07-14
*/ */
columnDef: Id Typename opt_with_col OptDefault opt_null columnDef: Id Typename opt_with_col opt_default opt_null
{ {
$$ = makeNode(ColumnDef); $$ = makeNode(ColumnDef);
$$->colname = $1; $$->colname = $1;
@ -402,108 +407,70 @@ columnDef: Id Typename opt_with_col OptDefault opt_null
} }
; ;
OptDefault: DEFAULT default_expr opt_default: DEFAULT default_expr
{ {
int deflen = CurScanPosition() - DefaultStartPosition; $$ = FlattenStringList($2);
char *defval;
defval = (char*) palloc (deflen + 1);
memcpy (defval, parseString + DefaultStartPosition,
deflen);
defval[deflen] = 0;
$$ = defval;
} }
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
default_expr_or_null: default_expr
{ $$ = $1;}
| Pnull
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
$$ = (Node *)n;
}
default_expr: AexprConst default_expr: AexprConst
{ { $$ = makeConstantList((A_Const *) $1); }
if (nodeTag($1) != T_A_Const) | Pnull
elog (WARN, "Cannot handle parameter in DEFAULT"); { $$ = lcons( makeString("NULL"), NIL); }
$$ = $1;
}
| '-' default_expr %prec UMINUS | '-' default_expr %prec UMINUS
{ $$ = makeA_Expr(OP, "-", NULL, $2); } { $$ = lcons( makeString( "-"), $2); }
| default_expr '+' default_expr | default_expr '+' default_expr
{ $$ = makeA_Expr(OP, "+", $1, $3); } { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
| default_expr '-' default_expr | default_expr '-' default_expr
{ $$ = makeA_Expr(OP, "-", $1, $3); } { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
| default_expr '/' default_expr | default_expr '/' default_expr
{ $$ = makeA_Expr(OP, "/", $1, $3); } { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
| default_expr '*' default_expr | default_expr '*' default_expr
{ $$ = makeA_Expr(OP, "*", $1, $3); } { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
| default_expr '<' default_expr
{ $$ = makeA_Expr(OP, "<", $1, $3); }
| default_expr '>' default_expr
{ $$ = makeA_Expr(OP, ">", $1, $3); }
| default_expr '=' default_expr | default_expr '=' default_expr
{ $$ = makeA_Expr(OP, "=", $1, $3); } { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
| default_expr '<' default_expr
{ elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
| default_expr '>' default_expr
{ elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
| ':' default_expr | ':' default_expr
{ $$ = makeA_Expr(OP, ":", NULL, $2); } { $$ = lcons( makeString( ":"), $2); }
| ';' default_expr | ';' default_expr
{ $$ = makeA_Expr(OP, ";", NULL, $2); } { $$ = lcons( makeString( ";"), $2); }
| '|' default_expr | '|' default_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); } { $$ = lcons( makeString( "|"), $2); }
| AexprConst TYPECAST Typename | default_expr TYPECAST Typename
{ {
/* AexprConst can be either A_Const or ParamNo */ $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
if (nodeTag($1) == T_A_Const)
((A_Const *)$1)->typename = $3;
else
elog (WARN, "Cannot handle parameter in DEFAULT");
$$ = (Node *)$1;
} }
| CAST AexprConst AS Typename | CAST default_expr AS Typename
{ {
/* AexprConst can be either A_Const or ParamNo */ $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
if (nodeTag($2) == T_A_Const)
((A_Const *)$2)->typename = $4;
else
elog (WARN, "Cannot handle parameter in DEFAULT");
$$ = (Node *)$2;
} }
| '(' default_expr ')' | '(' default_expr ')'
{ $$ = $2; } { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
| name '(' default_expr ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
$$ = nconc( $$, $3);
$$ = lappend( $$, makeString(")"));
}
| default_expr Op default_expr | default_expr Op default_expr
{ $$ = makeA_Expr(OP, $2, $1, $3); } {
if (!strcmp("<=", $2) || !strcmp(">=", $2))
elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
$$ = nconc( $1, lcons( $2, $3));
}
| Op default_expr | Op default_expr
{ $$ = makeA_Expr(OP, $1, NULL, $2); } { $$ = lcons( $1, $2); }
| default_expr Op | default_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); } { $$ = lcons( $2, $1); }
| name '(' ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
$$ = (Node *)n;
}
| name '(' default_expr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $3;
$$ = (Node *)n;
}
; ;
default_expr_list: default_expr_or_null opt_null: NOT PNULL { $$ = TRUE; }
{ $$ = lcons($1, NIL); } | NOTNULL { $$ = TRUE; }
| default_expr_list ',' default_expr_or_null | /* EMPTY */ { $$ = FALSE; }
{ $$ = lappend($1, $3); }
;
opt_null: NOT PNULL { $$ = true; }
| NOTNULL { $$ = true; }
| /* EMPTY */ { $$ = false; }
; ;
opt_with_col: WITH TIME ZONE { $$ = TRUE; } opt_with_col: WITH TIME ZONE { $$ = TRUE; }
@ -640,7 +607,7 @@ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
; ;
OptConstraint: ConstraintList { $$ = $1; } OptConstraint: ConstraintList { $$ = $1; }
| { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
ConstraintList: ConstraintList:
@ -659,24 +626,81 @@ ConstraintElem:
| ConstraintDef { $$ = $1; } | ConstraintDef { $$ = $1; }
; ;
ConstraintDef: CHECK a_expr ConstraintDef: CHECK constraint_elem
{ {
ConstraintDef *constr = palloc (sizeof(ConstraintDef)); ConstraintDef *constr = palloc (sizeof(ConstraintDef));
int chklen = CurScanPosition() - CheckStartPosition; #ifdef PARSEDEBUG
char *check; printf("in ConstraintDef\n");
#endif
check = (char*) palloc (chklen + 1);
memcpy (check,
parseString + CheckStartPosition,
chklen);
check[chklen] = 0;
constr->type = CONSTR_CHECK; constr->type = CONSTR_CHECK;
constr->name = NULL; constr->name = NULL;
constr->def = (void*) check; constr->def = FlattenStringList($2);
$$ = constr; $$ = constr;
} }
; ;
constraint_elem: AexprConst
{ $$ = makeConstantList((A_Const *) $1); }
| Pnull
{ $$ = lcons( makeString("NULL"), NIL); }
| Id
{
#ifdef PARSEDEBUG
printf( "Id is %s\n", $1);
#endif
$$ = lcons( makeString($1), NIL);
}
| '-' constraint_elem %prec UMINUS
{ $$ = lcons( makeString( "-"), $2); }
| constraint_elem '+' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "+"), $3)); }
| constraint_elem '-' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "-"), $3)); }
| constraint_elem '/' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "/"), $3)); }
| constraint_elem '*' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "*"), $3)); }
| constraint_elem '=' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "="), $3)); }
| constraint_elem '<' constraint_elem
{ $$ = nconc( $1, lcons( makeString( "<"), $3)); }
| constraint_elem '>' constraint_elem
{ $$ = nconc( $1, lcons( makeString( ">"), $3)); }
| ':' constraint_elem
{ $$ = lcons( makeString( ":"), $2); }
| ';' constraint_elem
{ $$ = lcons( makeString( ";"), $2); }
| '|' constraint_elem
{ $$ = lcons( makeString( "|"), $2); }
| constraint_elem TYPECAST Typename
{
$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
}
| CAST constraint_elem AS Typename
{
$$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
}
| '(' constraint_elem ')'
{ $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
| name '(' constraint_elem ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
$$ = nconc( $$, $3);
$$ = lappend( $$, makeString(")"));
}
| constraint_elem Op constraint_elem
{ $$ = nconc( $1, lcons( $2, $3)); }
| constraint_elem AND constraint_elem
{ $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
| constraint_elem OR constraint_elem
{ $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
| Op constraint_elem
{ $$ = lcons( $1, $2); }
| constraint_elem Op
{ $$ = lcons( $2, $1); }
;
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
@ -738,8 +762,8 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
} }
; ;
TriggerActionTime: BEFORE { $$ = true; } TriggerActionTime: BEFORE { $$ = TRUE; }
| AFTER { $$ = false; } | AFTER { $$ = FALSE; }
; ;
TriggerEvents: TriggerOneEvent TriggerEvents: TriggerOneEvent
@ -770,9 +794,9 @@ TriggerForSpec: FOR name name
if ( strcmp ($2, "each") != 0 ) if ( strcmp ($2, "each") != 0 )
elog(WARN,"parser: syntax error near %s",$2); elog(WARN,"parser: syntax error near %s",$2);
if ( strcmp ($3, "row") == 0 ) if ( strcmp ($3, "row") == 0 )
$$ = true; $$ = TRUE;
else if ( strcmp ($3, "statement") == 0 ) else if ( strcmp ($3, "statement") == 0 )
$$ = false; $$ = FALSE;
else else
elog(WARN,"parser: syntax error near %s",$3); elog(WARN,"parser: syntax error near %s",$3);
} }
@ -821,46 +845,64 @@ def_rest: def_name definition
{ {
$$ = makeNode(DefineStmt); $$ = makeNode(DefineStmt);
$$->defname = $1; $$->defname = $1;
#ifdef PARSEDEBUG
printf("def_rest: defname is %s\n", $1);
#endif
$$->definition = $2; $$->definition = $2;
} }
; ;
def_type: OPERATOR { $$ = OPERATOR; } def_type: OPERATOR { $$ = OPERATOR; }
| Type { $$ = P_TYPE; } | Type
{
#ifdef PARSEDEBUG
printf("def_type: decoding P_TYPE\n");
#endif
$$ = P_TYPE;
}
| AGGREGATE { $$ = AGGREGATE; } | AGGREGATE { $$ = AGGREGATE; }
; ;
def_name: Id | MathOp | Op def_name: PROCEDURE { $$ = "procedure"; }
| Id { $$ = $1; }
| MathOp { $$ = $1; }
| Op { $$ = $1; }
; ;
definition: '(' def_list ')' { $$ = $2; } definition: '(' def_list ')' { $$ = $2; }
; ;
def_list: def_elem { $$ = lcons($1, NIL); }
def_list: def_elem | def_list ',' def_elem { $$ = lappend($1, $3); }
{ $$ = lcons($1, NIL); }
| def_list ',' def_elem
{ $$ = lappend($1, $3); }
; ;
def_elem: def_name '=' def_arg def_elem: def_name '=' def_arg
{ {
#ifdef PARSEDEBUG
printf("def_elem: decoding %s =\n", $1);
pprint($3);
#endif
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
$$->arg = (Node *)$3; $$->arg = (Node *)$3;
} }
| def_name | def_name
{ {
#ifdef PARSEDEBUG
printf("def_elem: decoding %s\n", $1);
#endif
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
$$->arg = (Node *)NULL; $$->arg = (Node *)NULL;
} }
| DEFAULT '=' def_arg | DEFAULT '=' def_arg
{ {
#ifdef PARSEDEBUG
printf("def_elem: decoding DEFAULT =\n");
pprint($3);
#endif
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = (char*) palloc (8); $$->defname = "default";
strcpy ($$->defname, "default");
$$->arg = (Node *)$3; $$->arg = (Node *)$3;
} }
; ;
@ -869,13 +911,15 @@ def_arg: Id { $$ = (Node *)makeString($1); }
| all_Op { $$ = (Node *)makeString($1); } | all_Op { $$ = (Node *)makeString($1); }
| NumConst { $$ = (Node *)$1; /* already a Value */ } | NumConst { $$ = (Node *)$1; /* already a Value */ }
| Sconst { $$ = (Node *)makeString($1); } | Sconst { $$ = (Node *)makeString($1); }
| SETOF Id { | SETOF Id
{
TypeName *n = makeNode(TypeName); TypeName *n = makeNode(TypeName);
n->name = $2; n->name = $2;
n->setof = TRUE; n->setof = TRUE;
n->arrayBounds = NULL; n->arrayBounds = NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| DOUBLE { $$ = (Node *)makeString("double"); }
; ;
@ -890,14 +934,14 @@ DestroyStmt: DROP TABLE relation_name_list
{ {
DestroyStmt *n = makeNode(DestroyStmt); DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3; n->relNames = $3;
n->sequence = false; n->sequence = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| DROP SEQUENCE relation_name_list | DROP SEQUENCE relation_name_list
{ {
DestroyStmt *n = makeNode(DestroyStmt); DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3; n->relNames = $3;
n->sequence = true; n->sequence = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
@ -927,7 +971,7 @@ opt_direction: FORWARD { $$ = FORWARD; }
fetch_how_many: Iconst fetch_how_many: Iconst
{ $$ = $1; { $$ = $1;
if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); } if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
| ALL { $$ = 0; /* 0 means fetch all tuples*/} | ALL { $$ = 0; /* 0 means fetch all tuples*/}
| /*EMPTY*/ { $$ = 1; /*default*/ } | /*EMPTY*/ { $$ = 1; /*default*/ }
; ;
@ -1129,7 +1173,7 @@ RecipeStmt: EXECUTE RECIPE recipe_name
{ {
RecipeStmt *n; RecipeStmt *n;
if (!IsTransactionBlock()) if (!IsTransactionBlock())
elog(WARN, "EXECUTE RECIPE may only be used in begin/end transaction blocks."); elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
n = makeNode(RecipeStmt); n = makeNode(RecipeStmt);
n->recipeName = $3; n->recipeName = $3;
@ -1310,7 +1354,7 @@ MathOp: '+' { $$ = "+"; }
oper_argtypes: name oper_argtypes: name
{ {
elog(WARN, "parser: argument type missing (use NONE for unary operators)"); elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
} }
| name ',' name | name ',' name
{ $$ = makeList(makeString($1), makeString($3), -1); } { $$ = makeList(makeString($1), makeString($3), -1); }
@ -1637,7 +1681,7 @@ VacuumStmt: VACUUM opt_verbose opt_analyze
n->vacrel = $3; n->vacrel = $3;
n->va_spec = $5; n->va_spec = $5;
if ( $5 != NIL && !$4 ) if ( $5 != NIL && !$4 )
elog (WARN, "parser: syntax error at or near \"(\""); elog(WARN,"parser: syntax error at or near \"(\"",NULL);
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
@ -1811,7 +1855,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
* -- mao * -- mao
*/ */
if (!IsTransactionBlock()) if (!IsTransactionBlock())
elog(WARN, "Named portals may only be used in begin/end transaction blocks."); elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
n->portalname = $2; n->portalname = $2;
n->binary = $3; n->binary = $3;
@ -2077,7 +2121,7 @@ having_clause: HAVING a_expr { $$ = $2; }
* *
*****************************************************************************/ *****************************************************************************/
from_clause: FROM '(' relation_expr join_clause relation_expr join_spec ')' from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
{ {
$$ = NIL; $$ = NIL;
elog(WARN,"JOIN not yet implemented",NULL); elog(WARN,"JOIN not yet implemented",NULL);
@ -2114,29 +2158,21 @@ from_val: relation_expr AS var_name
} }
; ;
join_clause: join_qual join_type JOIN join_expr: NATURAL join_expr { $$ = NULL; }
{ | FULL join_outer
$$ = NULL;
}
;
join_qual: NATURAL { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
join_type: FULL join_outer
{ elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); } { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
| LEFT join_outer | LEFT join_outer
{ elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); } { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
| RIGHT join_outer | RIGHT join_outer
{ elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); } { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
| join_outer | OUTERJOIN
{ elog(WARN,"OUTER JOIN not yet implemented",NULL); } { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
| INNERJOIN | INNERJOIN
{ elog(WARN,"INNER JOIN not yet implemented",NULL); } { elog(WARN,"INNER JOIN not yet implemented",NULL); }
| UNION | UNION
{ elog(WARN,"UNION JOIN not yet implemented",NULL); } { elog(WARN,"UNION JOIN not yet implemented",NULL); }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ } | /*EMPTY*/
{ elog(WARN,"INNER JOIN not yet implemented",NULL); }
; ;
join_outer: OUTERJOIN { $$ = NULL; } join_outer: OUTERJOIN { $$ = NULL; }
@ -2280,8 +2316,14 @@ typname: txname
; ;
txname: Id { $$ = $1; } txname: Id { $$ = $1; }
| TIME { $$ = "time"; } | TIME { $$ = xlateSqlType("time"); }
| INTERVAL interval_opts { $$ = "interval"; } | INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
| CHARACTER char_type { $$ = $2; }
| DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
;
char_type: VARYING { $$ = xlateSqlType("varchar"); }
| /*EMPTY*/ { $$ = xlateSqlType("char"); }
; ;
interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); } interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); }
@ -2303,6 +2345,10 @@ Typename: typname opt_array_bounds
{ {
$$ = $1; $$ = $1;
$$->arrayBounds = $2; $$->arrayBounds = $2;
if (!strcasecmp($1->name, "varchar"))
{
$$->typlen = 4 + 1;
}
} }
| txname '(' Iconst ')' | txname '(' Iconst ')'
{ {
@ -2577,24 +2623,138 @@ expr_list: a_expr_or_null
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
; ;
extract_list: datetime FROM a_expr extract_list: DateTime FROM a_expr
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_String; n->val.type = T_String;
n->val.val.str = $1; n->val.val.str = $1;
#ifdef PARSEDEBUG
printf( "string is %s\n", $1); printf( "string is %s\n", $1);
#endif
$$ = lappend(lcons((Node *)n,NIL), $3); $$ = lappend(lcons((Node *)n,NIL), $3);
} }
| /* EMPTY */ | /* EMPTY */
{ $$ = NIL; } { $$ = NIL; }
; ;
position_list: a_expr IN expr_list position_list: position_expr IN position_expr
{ $$ = lappend($3, $1); } { $$ = makeList($3, $1, -1); }
| /* EMPTY */ | /* EMPTY */
{ $$ = NIL; } { $$ = NIL; }
; ;
position_expr: attr opt_indirection
{
$1->indirection = $2;
$$ = (Node *)$1;
}
| AexprConst
{ $$ = $1; }
| '-' position_expr %prec UMINUS
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
| position_expr '+' position_expr
{ $$ = makeA_Expr(OP, "+", $1, $3); }
| position_expr '-' position_expr
{ $$ = makeA_Expr(OP, "-", $1, $3); }
| position_expr '/' position_expr
{ $$ = makeA_Expr(OP, "/", $1, $3); }
| position_expr '*' position_expr
{ $$ = makeA_Expr(OP, "*", $1, $3); }
| '|' position_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); }
| AexprConst TYPECAST Typename
{
/* AexprConst can be either A_Const or ParamNo */
if (nodeTag($1) == T_A_Const)
((A_Const *)$1)->typename = $3;
else
((ParamNo *)$1)->typename = $3;
$$ = (Node *)$1;
}
| CAST AexprConst AS Typename
{
/* AexprConst can be either A_Const or ParamNo */
if (nodeTag($2) == T_A_Const)
((A_Const *)$2)->typename = $4;
else
((ParamNo *)$2)->typename = $4;
$$ = (Node *)$2;
}
| '(' position_expr ')'
{ $$ = $2; }
| position_expr Op position_expr
{ $$ = makeA_Expr(OP, $2, $1, $3); }
| Op position_expr
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
| position_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
| Id
{
/* could be a column name or a relation_name */
Ident *n = makeNode(Ident);
n->name = $1;
n->indirection = NULL;
$$ = (Node *)n;
}
| name '(' ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "strpos";
n->args = $3;
$$ = (Node *)n;
}
| SUBSTRING '(' substr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "substr";
n->args = $3;
$$ = (Node *)n;
}
/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
| TRIM '(' BOTH trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "btrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' LEADING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "ltrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' TRAILING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "rtrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "btrim";
n->args = $3;
$$ = (Node *)n;
}
| name '(' expr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $3;
$$ = (Node *)n;
}
;
substr_list: expr_list substr_from substr_for substr_list: expr_list substr_from substr_for
{ {
$$ = $1; $$ = $1;
@ -2667,7 +2827,7 @@ attrs: attr_name
{ $$ = lappend($1, makeString("*")); } { $$ = lappend($1, makeString("*")); }
; ;
datetime: YEARINTERVAL { $$ = "year"; } DateTime: YEARINTERVAL { $$ = "year"; }
| MONTHINTERVAL { $$ = "month"; } | MONTHINTERVAL { $$ = "month"; }
| DAYINTERVAL { $$ = "day"; } | DAYINTERVAL { $$ = "day"; }
| HOURINTERVAL { $$ = "hour"; } | HOURINTERVAL { $$ = "hour"; }
@ -2857,7 +3017,7 @@ Sconst: SCONST { $$ = $1; };
Id: IDENT { $$ = $1; }; Id: IDENT { $$ = $1; };
ColId: Id { $$ = $1; } ColId: Id { $$ = $1; }
| datetime { $$ = $1; } | DateTime { $$ = $1; }
; ;
SpecialRuleRelation: CURRENT SpecialRuleRelation: CURRENT
@ -2865,14 +3025,14 @@ SpecialRuleRelation: CURRENT
if (QueryIsRule) if (QueryIsRule)
$$ = "*CURRENT*"; $$ = "*CURRENT*";
else else
elog(WARN,"CURRENT used in non-rule query"); elog(WARN,"CURRENT used in non-rule query",NULL);
} }
| NEW | NEW
{ {
if (QueryIsRule) if (QueryIsRule)
$$ = "*NEW*"; $$ = "*NEW*";
else else
elog(WARN,"NEW used in non-rule query"); elog(WARN,"NEW used in non-rule query",NULL);
} }
; ;
@ -2892,6 +3052,9 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
return (Node *)a; return (Node *)a;
} }
/* xlateSqlType()
* Convert alternate type names to internal Postgres types.
*/
static char * static char *
xlateSqlType(char *name) xlateSqlType(char *name)
{ {
@ -2911,9 +3074,108 @@ xlateSqlType(char *name)
void parser_init(Oid *typev, int nargs) void parser_init(Oid *typev, int nargs)
{ {
QueryIsRule = false; QueryIsRule = FALSE;
saved_relname[0]= '\0'; saved_relname[0]= '\0';
saved_In_Expr = NULL; saved_In_Expr = NULL;
param_type_init(typev, nargs); param_type_init(typev, nargs);
} }
/* FlattenStringList()
* Traverse list of string nodes and convert to a single string.
* Used for reconstructing string form of complex expressions.
*/
static char *
FlattenStringList(List *list)
{
List *l, *lp;
char *s;
char *sp;
int nlist, len = 1;
nlist = length(list);
#ifdef PARSEDEBUG
printf( "list has %d elements\n", nlist);
#endif
l = list;
while(l != NIL) {
lp = lfirst(l);
sp = (char *)(lp->elem.ptr_value);
l = lnext(l);
#ifdef PARSEDEBUG
printf( "length of %s is %d\n", sp, strlen(sp));
#endif
len += strlen(sp)+1;
};
s = (char*) palloc(len);
*s = '\0';
l = list;
while(l != NIL) {
lp = lfirst(l);
sp = (char *)(lp->elem.ptr_value);
l = lnext(l);
#ifdef PARSEDEBUG
printf( "length of %s is %d\n", sp, strlen(sp));
#endif
strcat(s,sp);
strcat(s," ");
};
*(s+len-2) = '\0';
#ifdef PARSEDEBUG
printf( "flattened string is \"%s\"\n", s);
#endif
return(s);
} /* FlattenStringList() */
/* makeConstantList()
* Convert constant value node into string node.
*/
static List *
makeConstantList( A_Const *n)
{
char *defval = NULL;
#ifdef PARSEDEBUG
printf( "in AexprConst\n");
#endif
if (nodeTag(n) != T_A_Const) {
elog(WARN,"Cannot handle non-constant parameter",NULL);
} else if (n->val.type == T_Float) {
#ifdef PARSEDEBUG
printf( "AexprConst float is %f\n", n->val.val.dval);
#endif
defval = (char*) palloc(20+1);
sprintf( defval, "%g", n->val.val.dval);
} else if (n->val.type == T_Integer) {
#ifdef PARSEDEBUG
printf( "AexprConst integer is %ld\n", n->val.val.ival);
#endif
defval = (char*) palloc(20+1);
sprintf( defval, "%ld", n->val.val.ival);
} else if (n->val.type == T_String) {
#ifdef PARSEDEBUG
printf( "AexprConst string is \"%s\"\n", n->val.val.str);
#endif
defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
strcpy( defval, "'");
strcat( defval, ((A_Const *) n)->val.val.str);
strcat( defval, "'");
} else {
elog(WARN,"Internal error: cannot encode node",NULL);
};
#ifdef PARSEDEBUG
printf( "AexprConst argument is \"%s\"\n", defval);
#endif
return( lcons( makeString(defval), NIL));
} /* makeConstantList() */