From 37cfb040949057a0a07ef0652d5c546ab27655d5 Mon Sep 17 00:00:00 2001
From: "Thomas G. Lockhart" <lockhart@fourpalms.org>
Date: Sun, 21 Apr 2002 19:21:49 +0000
Subject: [PATCH] Make WITHOUT TIME ZONE the default for TIMESTAMP and TIME
 data types.  This is a big change from past behavior, but the last release
 was  designed to handle this correctly for dump/restore upgrades. Fix up
 handling of SET value arguments. Allow lists for most options at  least at
 the parser level; multiple values may be rejected at the  command processor
 of course. Allow more variations on values for SET commands, including
 integer and  float values where formerly stringy fields were required. Check
 precision specification for date/time fields against the true  precision
 range allowed by the data types. Especially useful with the  new int8-based
 storage for these types, where precision is fixed and  predictable. Stub out
 a basic CREATE ASSERTION per SQL9x. Does not do anything (yet) but  should be
 augmented as appropriate. Minor fixups in braces and tabbing.

---
 src/backend/parser/gram.y     | 458 ++++++++++++++++++----------------
 src/backend/parser/keywords.c |   3 +-
 2 files changed, 242 insertions(+), 219 deletions(-)

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 9ee7a66a421..91e33573aed 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.306 2002/04/21 00:26:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.307 2002/04/21 19:21:49 thomas Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -60,6 +60,7 @@
 #include "storage/lmgr.h"
 #include "utils/numeric.h"
 #include "utils/datetime.h"
+#include "utils/date.h"
 
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
@@ -84,7 +85,9 @@ static int	pfunc_num_args;
 
 static Node *makeTypeCast(Node *arg, TypeName *typename);
 static Node *makeStringConst(char *str, TypeName *typename);
+static Node *makeIntConst(int val);
 static Node *makeFloatConst(char *str);
+static Node *makeAConst(Value *v);
 static Node *makeRowExpr(List *opr, List *largs, List *rargs);
 static SelectStmt *findLeftmostSelect(SelectStmt *node);
 static void insertSelectOptions(SelectStmt *stmt,
@@ -131,9 +134,9 @@ static bool set_name_needs_quotes(const char *name);
 		AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
 		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
 		CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
-		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
+		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateAssertStmt, CreateTrigStmt,
 		CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
-		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
+		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropAssertStmt, DropTrigStmt,
 		DropRuleStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
 		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
 		NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
@@ -231,7 +234,7 @@ static bool set_name_needs_quotes(const char *name);
 %type <boolean>	opt_freeze, analyze_keyword
 
 %type <ival>	copy_dirn, direction, reindex_type, drop_type,
-		opt_column, event, comment_type
+				opt_column, event, comment_type
 
 %type <ival>	fetch_how_many
 
@@ -273,14 +276,15 @@ static bool set_name_needs_quotes(const char *name);
 %type <str>		opt_charset, opt_collate
 %type <str>		opt_float
 %type <ival>	opt_numeric, opt_decimal
-%type <boolean>	opt_varying, opt_timezone, opt_timezone_x
+%type <boolean>	opt_varying, opt_timezone
 
 %type <ival>	Iconst
 %type <str>		Sconst, comment_text
-%type <str>		UserId, opt_boolean, var_value, ColId_or_Sconst
+%type <str>		UserId, opt_boolean, ColId_or_Sconst
+%type <list>	var_list
 %type <str>		ColId, ColLabel, type_name, func_name_keyword
 %type <str>		col_name_keyword, unreserved_keyword, reserved_keyword
-%type <node>	zone_value
+%type <node>	var_value, zone_value
 
 %type <node>	TableConstraint
 %type <list>	ColQualList
@@ -340,7 +344,7 @@ static bool set_name_needs_quotes(const char *name);
 		WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
 
 /* Keywords (in SQL99 reserved words) */
-%token	CHAIN, CHARACTERISTICS,
+%token	ASSERTION, CHAIN, CHARACTERISTICS,
 		DEFERRABLE, DEFERRED,
 		IMMEDIATE, INITIALLY, INOUT,
 		OFF, OUT,
@@ -458,6 +462,7 @@ stmt : AlterDatabaseSetStmt
 		| CreateGroupStmt
 		| CreateSeqStmt
 		| CreatePLangStmt
+		| CreateAssertStmt
 		| CreateTrigStmt
 		| CreateUserStmt
 		| ClusterStmt
@@ -468,6 +473,7 @@ stmt : AlterDatabaseSetStmt
 		| CommentStmt
 		| DropGroupStmt
 		| DropPLangStmt
+		| DropAssertStmt
 		| DropTrigStmt
 		| DropRuleStmt
 		| DropUserStmt
@@ -512,19 +518,19 @@ stmt : AlterDatabaseSetStmt
  *****************************************************************************/
 
 CreateUserStmt:  CREATE USER UserId OptUserList 
-				  {
+				{
 					CreateUserStmt *n = makeNode(CreateUserStmt);
 					n->user = $3;
 					n->options = $4;
 					$$ = (Node *)n;
-				  }
-                 | CREATE USER UserId WITH OptUserList
-                  {
+				}
+			| CREATE USER UserId WITH OptUserList
+				{
 					CreateUserStmt *n = makeNode(CreateUserStmt);
 					n->user = $3;
 					n->options = $5;
 					$$ = (Node *)n;
-                  }                   
+				}                   
 		;
 
 /*****************************************************************************
@@ -593,66 +599,66 @@ OptUserList: OptUserList OptUserElem		{ $$ = lappend($1, $2); }
 		;
 
 OptUserElem:  PASSWORD Sconst
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "password";
-				  $$->arg = (Node *)makeString($2);
-				}
-			  | ENCRYPTED PASSWORD Sconst
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "encryptedPassword";
-				  $$->arg = (Node *)makeString($3);
-				}
-			  | UNENCRYPTED PASSWORD Sconst
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "unencryptedPassword";
-				  $$->arg = (Node *)makeString($3);
-				}
-              | SYSID Iconst
-				{
-				  $$ = makeNode(DefElem);
-				  $$->defname = "sysid";
-				  $$->arg = (Node *)makeInteger($2);
-				}
-              | CREATEDB
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "createdb";
-				  $$->arg = (Node *)makeInteger(TRUE);
-				}
-              | NOCREATEDB
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "createdb";
-				  $$->arg = (Node *)makeInteger(FALSE);
-				}
-              | CREATEUSER
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "createuser";
-				  $$->arg = (Node *)makeInteger(TRUE);
-				}
-              | NOCREATEUSER
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "createuser";
-				  $$->arg = (Node *)makeInteger(FALSE);
-				}
-              | IN GROUP user_list
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "groupElts";
-				  $$->arg = (Node *)$3;
-				}
-              | VALID UNTIL Sconst
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "validUntil";
-				  $$->arg = (Node *)makeString($3);
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "password";
+					$$->arg = (Node *)makeString($2);
 				}
-        ;
+			| ENCRYPTED PASSWORD Sconst
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "encryptedPassword";
+					$$->arg = (Node *)makeString($3);
+				}
+			| UNENCRYPTED PASSWORD Sconst
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "unencryptedPassword";
+					$$->arg = (Node *)makeString($3);
+				}
+			| SYSID Iconst
+				{
+					$$ = makeNode(DefElem);
+					$$->defname = "sysid";
+					$$->arg = (Node *)makeInteger($2);
+				}
+			| CREATEDB
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "createdb";
+					$$->arg = (Node *)makeInteger(TRUE);
+				}
+			| NOCREATEDB
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "createdb";
+					$$->arg = (Node *)makeInteger(FALSE);
+				}
+			| CREATEUSER
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "createuser";
+					$$->arg = (Node *)makeInteger(TRUE);
+				}
+			| NOCREATEUSER
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "createuser";
+					$$->arg = (Node *)makeInteger(FALSE);
+				}
+			| IN GROUP user_list
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "groupElts";
+					$$->arg = (Node *)$3;
+				}
+			| VALID UNTIL Sconst
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "validUntil";
+					$$->arg = (Node *)makeString($3);
+				}
+		;
 
 user_list:  user_list ',' UserId
 				{
@@ -674,19 +680,19 @@ user_list:  user_list ',' UserId
  *****************************************************************************/
 
 CreateGroupStmt:  CREATE GROUP UserId OptGroupList
-				   {
+				{
 					CreateGroupStmt *n = makeNode(CreateGroupStmt);
 					n->name = $3;
 					n->options = $4;
 					$$ = (Node *)n;
-				   }
-			      | CREATE GROUP UserId WITH OptGroupList
-				   {
+				}
+			| CREATE GROUP UserId WITH OptGroupList
+				{
 					CreateGroupStmt *n = makeNode(CreateGroupStmt);
 					n->name = $3;
 					n->options = $5;
 					$$ = (Node *)n;
-				   }
+				}
 		;
 
 /*
@@ -697,18 +703,18 @@ OptGroupList: OptGroupList OptGroupElem		{ $$ = lappend($1, $2); }
 		;
 
 OptGroupElem:  USER user_list
-                { 
-				  $$ = makeNode(DefElem);
-				  $$->defname = "userElts";
-				  $$->arg = (Node *)$2;
+				{ 
+					$$ = makeNode(DefElem);
+					$$->defname = "userElts";
+					$$->arg = (Node *)$2;
 				}
-               | SYSID Iconst
+			| SYSID Iconst
 				{
-				  $$ = makeNode(DefElem);
-				  $$->defname = "sysid";
-				  $$->arg = (Node *)makeInteger($2);
+					$$ = makeNode(DefElem);
+					$$->defname = "sysid";
+					$$->arg = (Node *)makeInteger($2);
 				}
-        ;
+		;
 
 
 /*****************************************************************************
@@ -812,6 +818,7 @@ schema_stmt: CreateStmt
 		| ViewStmt
 		;
 
+
 /*****************************************************************************
  *
  * Set PG internal variable
@@ -821,20 +828,18 @@ schema_stmt: CreateStmt
  *
  *****************************************************************************/
 
-VariableSetStmt:  SET ColId TO var_value
+VariableSetStmt:  SET ColId TO var_list
 				{
 					VariableSetStmt *n = makeNode(VariableSetStmt);
 					n->name  = $2;
-					if ($4 != NULL)
-						n->args = makeList1(makeStringConst($4, NULL));
+					n->args = $4;
 					$$ = (Node *) n;
 				}
-		| SET ColId '=' var_value
+		| SET ColId '=' var_list
 				{
 					VariableSetStmt *n = makeNode(VariableSetStmt);
 					n->name  = $2;
-					if ($4 != NULL)
-						n->args = makeList1(makeStringConst($4, NULL));
+					n->args = $4;
 					$$ = (Node *) n;
 				}
 		| SET TIME ZONE zone_value
@@ -876,69 +881,24 @@ VariableSetStmt:  SET ColId TO var_value
 				}
 		;
 
-opt_level:  READ COMMITTED					{ $$ = "read committed"; }
-		| SERIALIZABLE						{ $$ = "serializable"; }
+var_list:  var_value
+				{	$$ = makeList1($1); }
+		| var_list ',' var_value
+				{	$$ = lappend($1, $3); }
+		| DEFAULT
+				{ $$ = NIL; }
 		;
 
-var_value:  opt_boolean						{ $$ = $1; }
-		| SCONST							{ $$ = $1; }
-		| ICONST
-			{
-				char	buf[64];
-				sprintf(buf, "%d", $1);
-				$$ = pstrdup(buf);
-			}
-		| '-' ICONST
-			{
-				char	buf[64];
-				sprintf(buf, "%d", -($2));
-				$$ = pstrdup(buf);
-			}
-		| FCONST							{ $$ = $1; }
-		| '-' FCONST
-			{
-				char * s = palloc(strlen($2)+2);
-				s[0] = '-';
-				strcpy(s + 1, $2);
-				$$ = s;
-			}
-		| name_list
-			{
-				List *n;
-				int slen = 0;
-				char *result;
-
-				/* List of words? Then concatenate together */
-				if ($1 == NIL)
-					elog(ERROR, "SET must have at least one argument");
+var_value:  opt_boolean
+				{ $$ = makeStringConst($1, NULL); }
+		| ColId_or_Sconst
+				{ $$ = makeStringConst($1, NULL); }
+		| NumericOnly
+				{ $$ = makeAConst($1); }
+		;
 
-				/* compute space needed; allow for quotes and comma */
-				foreach (n, $1)
-				{
-					Value *p = (Value *) lfirst(n);
-					Assert(IsA(p, String));
-					slen += (strlen(p->val.str) + 3);
-				}
-				result = palloc(slen + 1);
-				*result = '\0';
-				foreach (n, $1)
-				{
-					Value *p = (Value *) lfirst(n);
-					if (set_name_needs_quotes(p->val.str))
-					{
-						strcat(result, "\"");
-						strcat(result, p->val.str);
-						strcat(result, "\"");
-					}
-					else
-						strcat(result, p->val.str);
-					strcat(result, ",");
-				}
-				/* remove the trailing comma from the last element */
-				*(result+strlen(result)-1) = '\0';
-				$$ = result;
-			}
-		| DEFAULT							{ $$ = NULL; }
+opt_level:  READ COMMITTED					{ $$ = "read committed"; }
+		| SERIALIZABLE						{ $$ = "serializable"; }
 		;
 
 opt_boolean:  TRUE_P						{ $$ = "true"; }
@@ -949,13 +909,20 @@ opt_boolean:  TRUE_P						{ $$ = "true"; }
 
 /* Timezone values can be:
  * - a string such as 'pst8pdt'
+ * - a column identifier such as "pst8pdt"
  * - an integer or floating point number
  * - a time interval per SQL99
+ * ConstInterval and ColId give shift/reduce errors,
+ * so use IDENT and reject anything which is a reserved word.
  */
 zone_value:  Sconst
 			{
 				$$ = makeStringConst($1, NULL);
 			}
+		| IDENT
+			{
+				$$ = makeStringConst($1, NULL);
+			}
 		| ConstInterval Sconst opt_interval
 			{
 				A_Const *n = (A_Const *) makeStringConst($2, $1);
@@ -970,6 +937,9 @@ zone_value:  Sconst
 		| ConstInterval '(' Iconst ')' Sconst opt_interval
 			{
 				A_Const *n = (A_Const *) makeStringConst($5, $1);
+				if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION))
+					elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
+						 $3, 0, MAX_INTERVAL_PRECISION);
 				if ($6 != -1)
 				{
 					if (($6 & ~(MASK(HOUR) | MASK(MINUTE))) != 0)
@@ -983,26 +953,7 @@ zone_value:  Sconst
 
 				$$ = (Node *)n;
 			}
-		| FCONST
-			{
-				$$ = makeFloatConst($1);
-			}
-		| '-' FCONST
-			{
-				$$ = doNegate(makeFloatConst($2));
-			}
-		| ICONST
-			{
-				char buf[64];
-				sprintf(buf, "%d", $1);
-				$$ = makeFloatConst(pstrdup(buf));
-			}
-		| '-' ICONST
-			{
-				char buf[64];
-				sprintf(buf, "%d", $2);
-				$$ = doNegate(makeFloatConst(pstrdup(buf)));
-			}
+		| NumericOnly						{ $$ = makeAConst($1); }
 		| DEFAULT							{ $$ = NULL; }
 		| LOCAL								{ $$ = NULL; }
 		;
@@ -1386,7 +1337,7 @@ columnDef:  ColId Typename ColQualList opt_collate
 					n->constraints = $3;
 
 					if ($4 != NULL)
-						elog(NOTICE,"CREATE TABLE / COLLATE %s not yet implemented"
+						elog(NOTICE, "CREATE TABLE / COLLATE %s not yet implemented"
 							 "; clause ignored", $4);
 
 					$$ = (Node *)n;
@@ -1715,7 +1666,7 @@ CreateAsStmt:  CREATE OptTemp TABLE qualified_name OptCreateAs AS SelectStmt
 					 */
 					SelectStmt *n = findLeftmostSelect((SelectStmt *) $7);
 					if (n->into != NULL)
-						elog(ERROR,"CREATE TABLE AS may not specify INTO");
+						elog(ERROR, "CREATE TABLE AS may not specify INTO");
 					$4->istemp = $2;
 					n->into = $4;
 					n->intoColNames = $5;
@@ -2072,6 +2023,42 @@ DropTrigStmt:  DROP TRIGGER name ON qualified_name
 		;
 
 
+/*****************************************************************************
+ *
+ *		QUERIES :
+ *				CREATE ASSERTION ...
+ *				DROP ASSERTION ...
+ *
+ *****************************************************************************/
+
+CreateAssertStmt:  CREATE ASSERTION name
+			CHECK '(' a_expr ')' ConstraintAttributeSpec
+				{
+					CreateTrigStmt *n = makeNode(CreateTrigStmt);
+					n->trigname = $3;
+					n->args = makeList1($6);
+					n->isconstraint  = TRUE;
+					n->deferrable = ($8 & 1) != 0;
+					n->initdeferred = ($8 & 2) != 0;
+
+					elog(ERROR, "CREATE ASSERTION is not yet supported");
+
+					$$ = (Node *)n;
+				}
+		;
+
+DropAssertStmt:  DROP ASSERTION name
+				{
+					DropPropertyStmt *n = makeNode(DropPropertyStmt);
+					n->relation = NULL;
+					n->property = $3;
+					n->removeType = DROP_TRIGGER;
+					elog(ERROR, "DROP ASSERTION is not yet supported");
+					$$ = (Node *) n;
+				}
+		;
+
+
 /*****************************************************************************
  *
  *		QUERY :
@@ -2955,9 +2942,9 @@ opt_column:  COLUMN						{ $$ = COLUMN; }
  *****************************************************************************/
 
 RuleStmt:  CREATE RULE name AS
-		   { QueryIsRule=TRUE; }
-		   ON event TO qualified_name where_clause
-		   DO opt_instead RuleActionList
+			{ QueryIsRule=TRUE; }
+			ON event TO qualified_name where_clause
+			DO opt_instead RuleActionList
 				{
 					RuleStmt *n = makeNode(RuleStmt);
 					n->relation = $9;
@@ -4311,6 +4298,9 @@ SimpleTypename:  ConstTypename
 		| ConstInterval '(' Iconst ')' opt_interval
 				{
 					$$ = $1;
+					if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION))
+						elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
+							 $3, 0, MAX_INTERVAL_PRECISION);
 					$$->typmod = ((($5 & 0x7FFF) << 16) | $3);
 				}
 		| type_name attrs
@@ -4367,13 +4357,13 @@ Numeric:  FLOAT opt_float
 opt_float:  '(' Iconst ')'
 				{
 					if ($2 < 1)
-						elog(ERROR,"precision for FLOAT must be at least 1");
+						elog(ERROR, "precision for FLOAT must be at least 1");
 					else if ($2 < 7)
 						$$ = xlateSqlType("float4");
 					else if ($2 < 16)
 						$$ = xlateSqlType("float8");
 					else
-						elog(ERROR,"precision for FLOAT must be less than 16");
+						elog(ERROR, "precision for FLOAT must be less than 16");
 				}
 		| /*EMPTY*/
 				{
@@ -4384,10 +4374,10 @@ opt_float:  '(' Iconst ')'
 opt_numeric:  '(' Iconst ',' Iconst ')'
 				{
 					if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-						elog(ERROR,"NUMERIC precision %d must be between 1 and %d",
+						elog(ERROR, "NUMERIC precision %d must be between 1 and %d",
 							 $2, NUMERIC_MAX_PRECISION);
 					if ($4 < 0 || $4 > $2)
-						elog(ERROR,"NUMERIC scale %d must be between 0 and precision %d",
+						elog(ERROR, "NUMERIC scale %d must be between 0 and precision %d",
 							 $4,$2);
 
 					$$ = (($2 << 16) | $4) + VARHDRSZ;
@@ -4395,7 +4385,7 @@ opt_numeric:  '(' Iconst ',' Iconst ')'
 		| '(' Iconst ')'
 				{
 					if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-						elog(ERROR,"NUMERIC precision %d must be between 1 and %d",
+						elog(ERROR, "NUMERIC precision %d must be between 1 and %d",
 							 $2, NUMERIC_MAX_PRECISION);
 
 					$$ = ($2 << 16) + VARHDRSZ;
@@ -4410,10 +4400,10 @@ opt_numeric:  '(' Iconst ',' Iconst ')'
 opt_decimal:  '(' Iconst ',' Iconst ')'
 				{
 					if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-						elog(ERROR,"DECIMAL precision %d must be between 1 and %d",
+						elog(ERROR, "DECIMAL precision %d must be between 1 and %d",
 									$2, NUMERIC_MAX_PRECISION);
 					if ($4 < 0 || $4 > $2)
-						elog(ERROR,"DECIMAL scale %d must be between 0 and precision %d",
+						elog(ERROR, "DECIMAL scale %d must be between 0 and precision %d",
 									$4,$2);
 
 					$$ = (($2 << 16) | $4) + VARHDRSZ;
@@ -4421,7 +4411,7 @@ opt_decimal:  '(' Iconst ',' Iconst ')'
 		| '(' Iconst ')'
 				{
 					if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-						elog(ERROR,"DECIMAL precision %d must be between 1 and %d",
+						elog(ERROR, "DECIMAL precision %d must be between 1 and %d",
 									$2, NUMERIC_MAX_PRECISION);
 
 					$$ = ($2 << 16) + VARHDRSZ;
@@ -4442,10 +4432,10 @@ Bit:  bit '(' Iconst ')'
 				{
 					$$ = makeTypeName($1);
 					if ($3 < 1)
-						elog(ERROR,"length for type '%s' must be at least 1",
+						elog(ERROR, "length for type '%s' must be at least 1",
 							 $1);
 					else if ($3 > (MaxAttrSize * BITS_PER_BYTE))
-						elog(ERROR,"length for type '%s' cannot exceed %d",
+						elog(ERROR, "length for type '%s' cannot exceed %d",
 							 $1, (MaxAttrSize * BITS_PER_BYTE));
 					$$->typmod = $3;
 				}
@@ -4491,10 +4481,10 @@ Character:  character '(' Iconst ')' opt_charset
 					$$ = makeTypeName($1);
 
 					if ($3 < 1)
-						elog(ERROR,"length for type '%s' must be at least 1",
+						elog(ERROR, "length for type '%s' must be at least 1",
 							 $1);
 					else if ($3 > MaxAttrSize)
-						elog(ERROR,"length for type '%s' cannot exceed %d",
+						elog(ERROR, "length for type '%s' cannot exceed %d",
 							 $1, MaxAttrSize);
 
 					/* we actually implement these like a varlen, so
@@ -4547,7 +4537,7 @@ opt_collate:  COLLATE ColId						{ $$ = $2; }
 		| /*EMPTY*/								{ $$ = NULL; }
 		;
 
-ConstDatetime:  TIMESTAMP '(' Iconst ')' opt_timezone_x
+ConstDatetime:  TIMESTAMP '(' Iconst ')' opt_timezone
 				{
 					if ($5)
 						$$ = makeTypeName(xlateSqlType("timestamptz"));
@@ -4557,12 +4547,12 @@ ConstDatetime:  TIMESTAMP '(' Iconst ')' opt_timezone_x
 					 * - thomas 2001-09-06
 					 */
 					$$->timezone = $5;
-					if (($3 < 0) || ($3 > 13))
-						elog(ERROR,"TIMESTAMP(%d)%s precision must be between %d and %d",
-							 $3, ($5 ? " WITH TIME ZONE": ""), 0, 13);
+					if (($3 < 0) || ($3 > MAX_TIMESTAMP_PRECISION))
+						elog(ERROR, "TIMESTAMP(%d)%s precision must be between %d and %d",
+							 $3, ($5 ? " WITH TIME ZONE": ""), 0, MAX_TIMESTAMP_PRECISION);
 					$$->typmod = $3;
 				}
-		| TIMESTAMP opt_timezone_x
+		| TIMESTAMP opt_timezone
 				{
 					if ($2)
 						$$ = makeTypeName(xlateSqlType("timestamptz"));
@@ -4587,9 +4577,9 @@ ConstDatetime:  TIMESTAMP '(' Iconst ')' opt_timezone_x
 						$$ = makeTypeName(xlateSqlType("timetz"));
 					else
 						$$ = makeTypeName(xlateSqlType("time"));
-					if (($3 < 0) || ($3 > 13))
-						elog(ERROR,"TIME(%d)%s precision must be between %d and %d",
-							 $3, ($5 ? " WITH TIME ZONE": ""), 0, 13);
+					if (($3 < 0) || ($3 > MAX_TIME_PRECISION))
+						elog(ERROR, "TIME(%d)%s precision must be between %d and %d",
+							 $3, ($5 ? " WITH TIME ZONE": ""), 0, MAX_TIME_PRECISION);
 					$$->typmod = $3;
 				}
 		| TIME opt_timezone
@@ -4612,16 +4602,6 @@ ConstInterval:  INTERVAL
 				}
 		;
 
-/* XXX Make the default be WITH TIME ZONE for 7.2 to help with database upgrades
- * but revert this back to WITHOUT TIME ZONE for 7.3.
- * Do this by simply reverting opt_timezone_x to opt_timezone - thomas 2001-09-06
- */
-
-opt_timezone_x:  WITH TIME ZONE					{ $$ = TRUE; }
-		| WITHOUT TIME ZONE						{ $$ = FALSE; }
-		| /*EMPTY*/								{ $$ = TRUE; }
-		;
-
 opt_timezone:  WITH TIME ZONE					{ $$ = TRUE; }
 		| WITHOUT TIME ZONE						{ $$ = FALSE; }
 		| /*EMPTY*/								{ $$ = FALSE; }
@@ -5293,9 +5273,9 @@ c_expr:  columnref
 					s->val.val.str = "now";
 					s->typename = makeTypeName(xlateSqlType("text"));
 					d = makeTypeName(xlateSqlType("timetz"));
-					if (($3 < 0) || ($3 > 13))
-						elog(ERROR,"CURRENT_TIME(%d) precision must be between %d and %d",
-							 $3, 0, 13);
+					if (($3 < 0) || ($3 > MAX_TIME_PRECISION))
+						elog(ERROR, "CURRENT_TIME(%d) precision must be between %d and %d",
+							 $3, 0, MAX_TIME_PRECISION);
 					d->typmod = $3;
 
 					$$ = (Node *)makeTypeCast((Node *)s, d);
@@ -5337,9 +5317,9 @@ c_expr:  columnref
 					s->typename = makeTypeName(xlateSqlType("text"));
 
 					d = makeTypeName(xlateSqlType("timestamptz"));
-					if (($3 < 0) || ($3 > 13))
-						elog(ERROR,"CURRENT_TIMESTAMP(%d) precision must be between %d and %d",
-							 $3, 0, 13);
+					if (($3 < 0) || ($3 > MAX_TIMESTAMP_PRECISION))
+						elog(ERROR, "CURRENT_TIMESTAMP(%d) precision must be between %d and %d",
+							 $3, 0, MAX_TIMESTAMP_PRECISION);
 					d->typmod = $3;
 
 					$$ = (Node *)makeTypeCast((Node *)s, d);
@@ -5748,8 +5728,12 @@ target_el:  a_expr AS ColLabel
 				}
 		;
 
-/* Target list as found in UPDATE table SET ... */
-
+/* Target list as found in UPDATE table SET ...
+| '(' row_ ')' = '(' row_ ')'
+{
+	$$ = NULL;
+}
+ */
 update_target_list:  update_target_list ',' update_target_el
 				{	$$ = lappend($1,$3);  }
 		| update_target_el
@@ -5911,8 +5895,10 @@ AexprConst:  Iconst
 					n->val.type = T_String;
 					n->val.val.str = $5;
 					/* precision specified, and fields may be... */
+					if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION))
+						elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
+							 $3, 0, MAX_INTERVAL_PRECISION);
 					n->typename->typmod = ((($6 & 0x7FFF) << 16) | $3);
-
 					$$ = (Node *)n;
 				}
 		| PARAM opt_indirection
@@ -6013,6 +5999,7 @@ unreserved_keyword:
 		| AFTER							{ $$ = "after"; }
 		| AGGREGATE						{ $$ = "aggregate"; }
 		| ALTER							{ $$ = "alter"; }
+		| ASSERTION						{ $$ = "assertion"; }
 		| AT							{ $$ = "at"; }
 		| BACKWARD						{ $$ = "backward"; }
 		| BEFORE						{ $$ = "before"; }
@@ -6308,14 +6295,14 @@ SpecialRuleRelation:  OLD
 					if (QueryIsRule)
 						$$ = "*OLD*";
 					else
-						elog(ERROR,"OLD used in non-rule query");
+						elog(ERROR, "OLD used in non-rule query");
 				}
 		| NEW
 				{
 					if (QueryIsRule)
 						$$ = "*NEW*";
 					else
-						elog(ERROR,"NEW used in non-rule query");
+						elog(ERROR, "NEW used in non-rule query");
 				}
 		;
 
@@ -6357,6 +6344,17 @@ makeStringConst(char *str, TypeName *typename)
 	return (Node *)n;
 }
 
+static Node *
+makeIntConst(int val)
+{
+	A_Const *n = makeNode(A_Const);
+	n->val.type = T_Integer;
+	n->val.val.ival = val;
+	n->typename = makeTypeName(xlateSqlType("integer"));
+
+	return (Node *)n;
+}
+
 static Node *
 makeFloatConst(char *str)
 {
@@ -6369,6 +6367,30 @@ makeFloatConst(char *str)
 	return (Node *)n;
 }
 
+static Node *
+makeAConst(Value *v)
+{
+	Node *n;
+
+	switch (v->type)
+	{
+		case T_Float:
+			n = makeFloatConst(v->val.str);
+			break;
+
+		case T_Integer:
+			n = makeIntConst(v->val.ival);
+			break;
+
+		case T_String:
+		default:
+			n = makeStringConst(v->val.str, NULL);
+			break;
+	}
+
+	return n;
+}
+
 /* makeRowExpr()
  * Generate separate operator nodes for a single row descriptor expression.
  * Perhaps this should go deeper in the parser someday...
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index eee0e1b9b2e..aa9baa5a80c 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.106 2002/04/21 00:26:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.107 2002/04/21 19:21:49 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,6 +43,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"any", ANY},
 	{"as", AS},
 	{"asc", ASC},
+	{"assertion", ASSERTION},
 	{"at", AT},
 	{"authorization", AUTHORIZATION},
 	{"backward", BACKWARD},
-- 
GitLab