aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas G. Lockhart <lockhart@fourpalms.org>1997-09-13 03:15:46 +0000
committerThomas G. Lockhart <lockhart@fourpalms.org>1997-09-13 03:15:46 +0000
commitbc85dbf893c5d92d11f5dc43e527be26f927b516 (patch)
tree01b18aec350ccc1ae8290b9ecb5393f2b481b4b7
parent9ea74630fc11005585e4c93c48d096c83a958cb8 (diff)
downloadpostgresql-bc85dbf893c5d92d11f5dc43e527be26f927b516.tar.gz
postgresql-bc85dbf893c5d92d11f5dc43e527be26f927b516.zip
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.
-rw-r--r--src/backend/parser/gram.y662
1 files changed, 462 insertions, 200 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7e74bac4183..1c72134fb86 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10,7 +10,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@@ -35,6 +35,7 @@
#include "postgres.h"
#include "nodes/parsenodes.h"
+#include "nodes/print.h"
#include "parser/gramparse.h"
#include "parser/catalog_utils.h"
#include "parser/parse_query.h"
@@ -49,11 +50,6 @@ static bool QueryIsRule = FALSE;
static Node *saved_In_Expr;
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
* 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 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 */
#if defined(yywrap)
@@ -117,17 +115,17 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
-%type <str> txname
+%type <str> txname, char_type
%type <node> SubSelect
-%type <str> join_clause, join_type, join_outer, join_spec
-%type <boolean> join_qual, TriggerActionTime, TriggerForSpec
+%type <str> join_expr, join_outer, join_spec
+%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,
database_name, access_method_clause, access_method, attr_name,
class, index_name, name, file_name, recipe_name,
- var_name, aggr_argtype, OptDefault
+ var_name, aggr_argtype
%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,
sort_clause, sortby_list, index_params, index_list, name_list,
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
%type <list> union_clause, select_list
%type <list> join_list
%type <sortgroupby> join_using
+%type <node> position_expr
%type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list
%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 <node> def_arg, columnElem, where_clause,
a_expr, a_expr_or_null, AexprConst,
- default_expr, default_expr_or_null,
in_expr_nodes, not_in_expr_nodes,
having_clause
%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> ColId
+%type <list> default_expr
+%type <str> opt_default
+%type <list> constraint_elem
/*
* 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,
AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
- CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, COPY, CREATE, CROSS,
- CURRENT, CURSOR, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
- DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, EXTRACT,
- FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP,
- HAVING, HEAVY, HOURINTERVAL,
- IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTERVAL, INTO, IS, ISNULL,
- JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL,
- MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
+ CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
+ COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
+ DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
+ DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
+ FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY, HOURINTERVAL,
+ IN, INDEX, INHERITS, INNERJOIN, INSERT, INTERVAL, INSTEAD, INTO, IS, ISNULL,
+ JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
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,
- SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, SUBSTRING,
- TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER, TRIM,
+ SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE,
+ TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER,
UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
%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 */
%token <str> IDENT, SCONST, Op
%token <ival> ICONST, PARAM
%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
/* precedence */
@@ -384,10 +389,10 @@ AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
;
/* Column definition might include WITH TIME ZONE, but only for the data types
- * 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
*/
-columnDef: Id Typename opt_with_col OptDefault opt_null
+columnDef: Id Typename opt_with_col opt_default opt_null
{
$$ = makeNode(ColumnDef);
$$->colname = $1;
@@ -396,118 +401,80 @@ columnDef: Id Typename opt_with_col OptDefault opt_null
$$->defval = $4;
$$->is_not_null = $5;
if ($$->typename->timezone
- && (strcasecmp($$->typename->name, "timestamp")
- && strcasecmp($$->typename->name, "time")))
- elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
- }
- ;
-
-OptDefault: DEFAULT default_expr
- {
- int deflen = CurScanPosition() - DefaultStartPosition;
- char *defval;
-
- defval = (char*) palloc (deflen + 1);
- memcpy (defval, parseString + DefaultStartPosition,
- deflen);
- defval[deflen] = 0;
- $$ = defval;
+ && (strcasecmp($$->typename->name, "timestamp")
+ && strcasecmp($$->typename->name, "time")))
+ elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
}
- | /*EMPTY*/ { $$ = NULL; }
;
-default_expr_or_null: default_expr
- { $$ = $1;}
- | Pnull
+opt_default: DEFAULT default_expr
{
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
- $$ = (Node *)n;
+ $$ = FlattenStringList($2);
}
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
-default_expr: AexprConst
+default_expr: AexprConst
+ { $$ = makeConstantList((A_Const *) $1); }
+ | Pnull
+ { $$ = lcons( makeString("NULL"), NIL); }
+ | '-' default_expr %prec UMINUS
+ { $$ = lcons( makeString( "-"), $2); }
+ | default_expr '+' default_expr
+ { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
+ | default_expr '-' default_expr
+ { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
+ | default_expr '/' default_expr
+ { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
+ | default_expr '*' default_expr
+ { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
+ | 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
+ { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+ | ':' default_expr
+ { $$ = lcons( makeString( ":"), $2); }
+ | ';' default_expr
+ { $$ = lcons( makeString( ";"), $2); }
+ | '|' default_expr
+ { $$ = lcons( makeString( "|"), $2); }
+ | default_expr TYPECAST Typename
{
- if (nodeTag($1) != T_A_Const)
- elog (WARN, "Cannot handle parameter in DEFAULT");
- $$ = $1;
+ $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
}
- | '-' default_expr %prec UMINUS
- { $$ = makeA_Expr(OP, "-", NULL, $2); }
- | default_expr '+' default_expr
- { $$ = makeA_Expr(OP, "+", $1, $3); }
- | default_expr '-' default_expr
- { $$ = makeA_Expr(OP, "-", $1, $3); }
- | default_expr '/' default_expr
- { $$ = makeA_Expr(OP, "/", $1, $3); }
- | default_expr '*' default_expr
- { $$ = makeA_Expr(OP, "*", $1, $3); }
- | default_expr '<' default_expr
- { $$ = makeA_Expr(OP, "<", $1, $3); }
- | default_expr '>' default_expr
- { $$ = makeA_Expr(OP, ">", $1, $3); }
- | default_expr '=' default_expr
- { $$ = makeA_Expr(OP, "=", $1, $3); }
- | ':' default_expr
- { $$ = makeA_Expr(OP, ":", NULL, $2); }
- | ';' default_expr
- { $$ = makeA_Expr(OP, ";", NULL, $2); }
- | '|' default_expr
- { $$ = makeA_Expr(OP, "|", NULL, $2); }
- | AexprConst TYPECAST Typename
+ | CAST default_expr AS Typename
{
- /* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($1) == T_A_Const)
- ((A_Const *)$1)->typename = $3;
- else
- elog (WARN, "Cannot handle parameter in DEFAULT");
- $$ = (Node *)$1;
+ $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
}
- | CAST AexprConst AS Typename
+ | '(' default_expr ')'
+ { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
+ | name '(' default_expr ')'
{
- /* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($2) == T_A_Const)
- ((A_Const *)$2)->typename = $4;
- else
- elog (WARN, "Cannot handle parameter in DEFAULT");
- $$ = (Node *)$2;
+ $$ = makeList( makeString($1), makeString("("), -1);
+ $$ = nconc( $$, $3);
+ $$ = lappend( $$, makeString(")"));
}
- | '(' default_expr ')'
- { $$ = $2; }
- | default_expr Op default_expr
- { $$ = makeA_Expr(OP, $2, $1, $3); }
- | Op default_expr
- { $$ = makeA_Expr(OP, $1, NULL, $2); }
- | default_expr Op
- { $$ = makeA_Expr(OP, $2, $1, NULL); }
- | name '(' ')'
+ | default_expr Op default_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- $$ = (Node *)n;
+ if (!strcmp("<=", $2) || !strcmp(">=", $2))
+ elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
+ $$ = nconc( $1, lcons( $2, $3));
}
- | name '(' default_expr_list ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- $$ = (Node *)n;
- }
- ;
-
-default_expr_list: default_expr_or_null
- { $$ = lcons($1, NIL); }
- | default_expr_list ',' default_expr_or_null
- { $$ = lappend($1, $3); }
+ | Op default_expr
+ { $$ = lcons( $1, $2); }
+ | default_expr Op
+ { $$ = lcons( $2, $1); }
;
-opt_null: NOT PNULL { $$ = true; }
- | NOTNULL { $$ = true; }
- | /* EMPTY */ { $$ = false; }
+opt_null: NOT PNULL { $$ = TRUE; }
+ | NOTNULL { $$ = TRUE; }
+ | /* EMPTY */ { $$ = FALSE; }
;
opt_with_col: WITH TIME ZONE { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /* EMPTY */ { $$ = FALSE; }
;
/*****************************************************************************
@@ -639,11 +606,11 @@ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
-OptConstraint: ConstraintList { $$ = $1; }
- | { $$ = NULL; }
+OptConstraint: ConstraintList { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
;
-ConstraintList :
+ConstraintList:
ConstraintList ',' ConstraintElem
{ $$ = lappend($1, $3); }
| ConstraintElem
@@ -659,24 +626,81 @@ ConstraintElem:
| ConstraintDef { $$ = $1; }
;
-ConstraintDef: CHECK a_expr
+ConstraintDef: CHECK constraint_elem
{
ConstraintDef *constr = palloc (sizeof(ConstraintDef));
- int chklen = CurScanPosition() - CheckStartPosition;
- char *check;
-
- check = (char*) palloc (chklen + 1);
- memcpy (check,
- parseString + CheckStartPosition,
- chklen);
- check[chklen] = 0;
+#ifdef PARSEDEBUG
+printf("in ConstraintDef\n");
+#endif
constr->type = CONSTR_CHECK;
constr->name = NULL;
- constr->def = (void*) check;
+ constr->def = FlattenStringList($2);
$$ = 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 :
@@ -738,8 +762,8 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
}
;
-TriggerActionTime: BEFORE { $$ = true; }
- | AFTER { $$ = false; }
+TriggerActionTime: BEFORE { $$ = TRUE; }
+ | AFTER { $$ = FALSE; }
;
TriggerEvents: TriggerOneEvent
@@ -768,13 +792,13 @@ TriggerOneEvent: INSERT { $$ = 'i'; }
TriggerForSpec: FOR name name
{
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 )
- $$ = true;
+ $$ = TRUE;
else if ( strcmp ($3, "statement") == 0 )
- $$ = false;
+ $$ = FALSE;
else
- elog (WARN, "parser: syntax error near %s", $3);
+ elog(WARN,"parser: syntax error near %s",$3);
}
;
@@ -821,61 +845,81 @@ def_rest: def_name definition
{
$$ = makeNode(DefineStmt);
$$->defname = $1;
+#ifdef PARSEDEBUG
+printf("def_rest: defname is %s\n", $1);
+#endif
$$->definition = $2;
}
;
-def_type: OPERATOR { $$ = OPERATOR; }
- | Type { $$ = P_TYPE; }
- | AGGREGATE { $$ = AGGREGATE; }
+def_type: OPERATOR { $$ = OPERATOR; }
+ | Type
+ {
+#ifdef PARSEDEBUG
+printf("def_type: decoding P_TYPE\n");
+#endif
+ $$ = P_TYPE;
+ }
+ | 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
- { $$ = lappend($1, $3); }
+def_list: def_elem { $$ = lcons($1, NIL); }
+ | def_list ',' def_elem { $$ = lappend($1, $3); }
;
def_elem: def_name '=' def_arg
{
+#ifdef PARSEDEBUG
+printf("def_elem: decoding %s =\n", $1);
+pprint($3);
+#endif
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
- | def_name
+ | def_name
{
+#ifdef PARSEDEBUG
+printf("def_elem: decoding %s\n", $1);
+#endif
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)NULL;
}
- | DEFAULT '=' def_arg
+ | DEFAULT '=' def_arg
{
+#ifdef PARSEDEBUG
+printf("def_elem: decoding DEFAULT =\n");
+pprint($3);
+#endif
$$ = makeNode(DefElem);
- $$->defname = (char*) palloc (8);
- strcpy ($$->defname, "default");
+ $$->defname = "default";
$$->arg = (Node *)$3;
}
;
-def_arg: Id { $$ = (Node *)makeString($1); }
- | all_Op { $$ = (Node *)makeString($1); }
- | NumConst { $$ = (Node *)$1; /* already a Value */ }
- | Sconst { $$ = (Node *)makeString($1); }
- | SETOF Id {
- TypeName *n = makeNode(TypeName);
- n->name = $2;
- n->setof = TRUE;
- n->arrayBounds = NULL;
- $$ = (Node *)n;
- }
+def_arg: Id { $$ = (Node *)makeString($1); }
+ | all_Op { $$ = (Node *)makeString($1); }
+ | NumConst { $$ = (Node *)$1; /* already a Value */ }
+ | Sconst { $$ = (Node *)makeString($1); }
+ | SETOF Id
+ {
+ TypeName *n = makeNode(TypeName);
+ n->name = $2;
+ n->setof = TRUE;
+ n->arrayBounds = NULL;
+ $$ = (Node *)n;
+ }
+ | DOUBLE { $$ = (Node *)makeString("double"); }
;
@@ -890,14 +934,14 @@ DestroyStmt: DROP TABLE relation_name_list
{
DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3;
- n->sequence = false;
+ n->sequence = FALSE;
$$ = (Node *)n;
}
| DROP SEQUENCE relation_name_list
{
DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3;
- n->sequence = true;
+ n->sequence = TRUE;
$$ = (Node *)n;
}
;
@@ -927,7 +971,7 @@ opt_direction: FORWARD { $$ = FORWARD; }
fetch_how_many: Iconst
{ $$ = $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*/}
| /*EMPTY*/ { $$ = 1; /*default*/ }
;
@@ -1129,7 +1173,7 @@ RecipeStmt: EXECUTE RECIPE recipe_name
{
RecipeStmt *n;
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->recipeName = $3;
@@ -1299,7 +1343,7 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
all_Op: Op | MathOp;
-MathOp: '+' { $$ = "+"; }
+MathOp: '+' { $$ = "+"; }
| '-' { $$ = "-"; }
| '*' { $$ = "*"; }
| '/' { $$ = "/"; }
@@ -1310,7 +1354,7 @@ MathOp: '+' { $$ = "+"; }
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
{ $$ = makeList(makeString($1), makeString($3), -1); }
@@ -1637,7 +1681,7 @@ VacuumStmt: VACUUM opt_verbose opt_analyze
n->vacrel = $3;
n->va_spec = $5;
if ( $5 != NIL && !$4 )
- elog (WARN, "parser: syntax error at or near \"(\"");
+ elog(WARN,"parser: syntax error at or near \"(\"",NULL);
$$ = (Node *)n;
}
;
@@ -1811,7 +1855,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
* -- mao
*/
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->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;
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
- {
- $$ = NULL;
- }
- ;
-
-join_qual: NATURAL { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
-
-join_type: FULL join_outer
+join_expr: NATURAL join_expr { $$ = NULL; }
+ | FULL join_outer
{ elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
| LEFT join_outer
{ elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
| RIGHT join_outer
{ elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
- | join_outer
+ | OUTERJOIN
{ elog(WARN,"OUTER JOIN not yet implemented",NULL); }
| INNERJOIN
{ elog(WARN,"INNER JOIN not yet implemented",NULL); }
| UNION
{ 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; }
@@ -2280,8 +2316,14 @@ typname: txname
;
txname: Id { $$ = $1; }
- | TIME { $$ = "time"; }
- | INTERVAL interval_opts { $$ = "interval"; }
+ | TIME { $$ = xlateSqlType("time"); }
+ | 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); }
@@ -2303,6 +2345,10 @@ Typename: typname opt_array_bounds
{
$$ = $1;
$$->arrayBounds = $2;
+ if (!strcasecmp($1->name, "varchar"))
+ {
+ $$->typlen = 4 + 1;
+ }
}
| txname '(' Iconst ')'
{
@@ -2331,14 +2377,14 @@ Typename: typname opt_array_bounds
else
yyerror("parse error");
if ($3 < 1)
- elog(WARN, "length for '%s' type must be at least 1",$1);
+ elog(WARN,"length for '%s' type must be at least 1",$1);
else if ($3 > 4096)
/* we can store a char() of length up to the size
* of a page (8KB) - page headers and friends but
* just to be safe here... - ay 6/95
* XXX note this hardcoded limit - thomas 1997-07-13
*/
- elog(WARN, "length for '%s' type cannot exceed 4096",$1);
+ elog(WARN,"length for '%s' type cannot exceed 4096",$1);
/* we actually implement this sort of like a varlen, so
* the first 4 bytes is the length. (the difference
@@ -2577,24 +2623,138 @@ expr_list: a_expr_or_null
{ $$ = lappend($1, $3); }
;
-extract_list: datetime FROM a_expr
+extract_list: DateTime FROM a_expr
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = $1;
+#ifdef PARSEDEBUG
printf( "string is %s\n", $1);
+#endif
$$ = lappend(lcons((Node *)n,NIL), $3);
}
| /* EMPTY */
{ $$ = NIL; }
;
-position_list: a_expr IN expr_list
- { $$ = lappend($3, $1); }
+position_list: position_expr IN position_expr
+ { $$ = makeList($3, $1, -1); }
| /* EMPTY */
{ $$ = 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
{
$$ = $1;
@@ -2667,7 +2827,7 @@ attrs: attr_name
{ $$ = lappend($1, makeString("*")); }
;
-datetime: YEARINTERVAL { $$ = "year"; }
+DateTime: YEARINTERVAL { $$ = "year"; }
| MONTHINTERVAL { $$ = "month"; }
| DAYINTERVAL { $$ = "day"; }
| HOURINTERVAL { $$ = "hour"; }
@@ -2796,7 +2956,7 @@ relation_name: SpecialRuleRelation
|| strcmp(VariableRelationName, $1) == 0
|| strcmp(TimeRelationName, $1) == 0
|| strcmp(MagicRelationName, $1) == 0)
- elog(WARN, "%s cannot be accessed by users", $1);
+ elog(WARN,"%s cannot be accessed by users",$1);
else
$$ = $1;
strNcpy(saved_relname, $1, NAMEDATALEN-1);
@@ -2857,7 +3017,7 @@ Sconst: SCONST { $$ = $1; };
Id: IDENT { $$ = $1; };
ColId: Id { $$ = $1; }
- | datetime { $$ = $1; }
+ | DateTime { $$ = $1; }
;
SpecialRuleRelation: CURRENT
@@ -2865,14 +3025,14 @@ SpecialRuleRelation: CURRENT
if (QueryIsRule)
$$ = "*CURRENT*";
else
- elog(WARN,"CURRENT used in non-rule query");
+ elog(WARN,"CURRENT used in non-rule query",NULL);
}
| NEW
{
if (QueryIsRule)
$$ = "*NEW*";
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;
}
+/* xlateSqlType()
+ * Convert alternate type names to internal Postgres types.
+ */
static char *
xlateSqlType(char *name)
{
@@ -2911,9 +3074,108 @@ xlateSqlType(char *name)
void parser_init(Oid *typev, int nargs)
{
- QueryIsRule = false;
+ QueryIsRule = FALSE;
saved_relname[0]= '\0';
saved_In_Expr = NULL;
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() */