diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 30bdd9c0627e227154a986d1fde805d7fc7ab982..63b990aa7472fc7097ea6f9377927790434ddb1d 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -7,13 +7,14 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.51 1997/11/26 01:11:03 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.52 1997/12/04 23:07:18 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 
 #include "postgres.h"
@@ -39,7 +40,9 @@ static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
 static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
 static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
 static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
+static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
 
+List   *extras = NIL;
 
 /*
  * parse_analyze -
@@ -65,6 +68,17 @@ parse_analyze(List *pl)
 	{
 		pstate = make_parsestate();
 		result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
+		if (extras != NIL)
+		{
+			result->len += length(extras);
+			result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
+			while (extras != NIL)
+			{
+				result->qtrees[i++] = transformStmt(pstate, lfirst(extras));
+				extras = lnext(extras);
+			}
+		}
+		extras = NIL;
 		pl = lnext(pl);
 		if (pstate->p_target_relation != NULL)
 			heap_close(pstate->p_target_relation);
@@ -90,6 +104,10 @@ transformStmt(ParseState *pstate, Node *parseTree)
 			 *	Non-optimizable statements
 			 *------------------------
 			 */
+		case T_CreateStmt:
+			result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
+			break;
+
 		case T_IndexStmt:
 			result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
 			break;
@@ -309,6 +327,316 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
 	return (Query *) qry;
 }
 
+/* makeTableName()
+ * Create a table name from a list of fields.
+ */
+static char *
+makeTableName(void *elem,...);
+
+static char *
+makeTableName(void *elem,...)
+{
+	va_list	args;
+
+	char   *name;
+	char	buf[NAMEDATALEN+1];
+
+	strcpy(buf,"");
+
+	va_start(args,elem);
+
+	name = elem;
+	while (name != NULL)
+	{
+		/* not enough room for next part? then return nothing */
+		if ((strlen(buf)+strlen(name)) >= (sizeof(buf)-1))
+			return (NULL);
+
+		if (strlen(buf) > 0) strcat(buf,"_");
+		strcat(buf,name);
+
+		name = va_arg(args,void *);
+	}
+
+	va_end(args);
+
+	name = palloc(strlen(buf)+1);
+	strcpy(name,buf);
+
+	return (name);
+} /* makeTableName() */
+
+/*
+ * transformCreateStmt -
+ *	  transforms the "create table" statement
+ *	  SQL92 allows constraints to be scattered all over, so thumb through
+ *	   the columns and collect all constraints into one place.
+ *	  If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
+ *	   then expand those into multiple IndexStmt blocks.
+ *	  - thomas 1997-12-02
+ */
+static Query *
+transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
+{
+	Query	   *q;
+	List	   *elements;
+	Node	   *element;
+	List	   *columns;
+	List	   *dlist;
+	ColumnDef  *column;
+	List	   *constraints, *clist;
+	Constraint *constraint;
+	List	   *keys;
+	Ident	   *key;
+	List	   *ilist;
+	IndexStmt  *index;
+	IndexElem  *iparam;
+
+	q = makeNode(Query);
+	q->commandType = CMD_UTILITY;
+
+	elements = stmt->tableElts;
+	constraints = stmt->constraints;
+	columns = NIL;
+	dlist = NIL;
+
+	while (elements != NIL)
+	{
+		element = lfirst(elements);
+		switch (nodeTag(element))
+		{
+			case T_ColumnDef:
+				column = (ColumnDef *) element;
+#if PARSEDEBUG
+printf("transformCreateStmt- found column %s\n",column->colname);
+#endif
+				columns = lappend(columns,column);
+				if (column->constraints != NIL)
+				{
+#if PARSEDEBUG
+printf("transformCreateStmt- found constraint(s) on column %s\n",column->colname);
+#endif
+					clist = column->constraints;
+					while (clist != NIL)
+					{
+						constraint = lfirst(clist);
+						switch (constraint->contype)
+						{
+							case CONSTR_NOTNULL:
+#if PARSEDEBUG
+printf("transformCreateStmt- found NOT NULL constraint on column %s\n",column->colname);
+#endif
+								if (column->is_not_null)
+									elog(WARN,"CREATE TABLE/NOT NULL already specified"
+										" for %s.%s", stmt->relname, column->colname);
+								column->is_not_null = TRUE;
+								break;
+
+							case CONSTR_DEFAULT:
+#if PARSEDEBUG
+printf("transformCreateStmt- found DEFAULT clause on column %s\n",column->colname);
+#endif
+								if (column->defval != NULL)
+									elog(WARN,"CREATE TABLE/DEFAULT multiple values specified"
+										" for %s.%s", stmt->relname, column->colname);
+								column->defval = constraint->def;
+								break;
+
+							case CONSTR_PRIMARY:
+#if PARSEDEBUG
+printf("transformCreateStmt- found PRIMARY KEY clause on column %s\n",column->colname);
+#endif
+								if (constraint->name == NULL)
+									constraint->name = makeTableName(stmt->relname, "pkey", NULL);
+								if (constraint->keys == NIL)
+									constraint->keys = lappend(constraint->keys, column);
+								dlist = lappend(dlist, constraint);
+								break;
+
+							case CONSTR_UNIQUE:
+#if PARSEDEBUG
+printf("transformCreateStmt- found UNIQUE clause on column %s\n",column->colname);
+#endif
+								if (constraint->name == NULL)
+									constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
+								if (constraint->keys == NIL)
+									constraint->keys = lappend(constraint->keys, column);
+								dlist = lappend(dlist, constraint);
+								break;
+
+							case CONSTR_CHECK:
+#if PARSEDEBUG
+printf("transformCreateStmt- found CHECK clause on column %s\n",column->colname);
+#endif
+								constraints = lappend(constraints, constraint);
+								if (constraint->name == NULL)
+									constraint->name = makeTableName(stmt->relname, ".", column->colname, NULL);
+								break;
+
+							default:
+								elog(WARN,"parser: internal error; unrecognized constraint",NULL);
+								break;
+						}
+						clist = lnext(clist);
+					}
+				}
+				break;
+
+			case T_Constraint:
+				constraint = (Constraint *) element;
+#if PARSEDEBUG
+printf("transformCreateStmt- found constraint %s\n", ((constraint->name != NULL)? constraint->name: "(unknown)"));
+#endif
+				switch (constraint->contype)
+				{
+					case CONSTR_PRIMARY:
+#if PARSEDEBUG
+printf("transformCreateStmt- found PRIMARY KEY clause\n");
+#endif
+						if (constraint->name == NULL)
+							constraint->name = makeTableName(stmt->relname, "pkey", NULL);
+						dlist = lappend(dlist, constraint);
+						break;
+
+					case CONSTR_UNIQUE:
+#if PARSEDEBUG
+printf("transformCreateStmt- found UNIQUE clause\n");
+#endif
+#if FALSE
+						if (constraint->name == NULL)
+							constraint->name = makeTableName(stmt->relname, "key", NULL);
+#endif
+						dlist = lappend(dlist, constraint);
+						break;
+
+					case CONSTR_CHECK:
+#if PARSEDEBUG
+printf("transformCreateStmt- found CHECK clause\n");
+#endif
+						constraints = lappend(constraints, constraint);
+						break;
+
+					case CONSTR_NOTNULL:
+					case CONSTR_DEFAULT:
+						elog(WARN,"parser: internal error; illegal context for constraint",NULL);
+						break;
+					default:
+						elog(WARN,"parser: internal error; unrecognized constraint",NULL);
+						break;
+				}
+				break;
+
+			default:
+				elog(WARN,"parser: internal error; unrecognized node",NULL);
+		}
+
+		elements = lnext(elements);
+	}
+
+	stmt->tableElts = columns;
+	stmt->constraints = constraints;
+
+/* Now run through the "deferred list" to complete the query transformation.
+ * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
+ * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
+ *
+ * Note that this code does not currently look for all possible redundant cases
+ *  and either ignore or stop with warning. The create will fail later when
+ *  names for indices turn out to be redundant, or a user might just find
+ *  extra useless indices which might kill performance. - thomas 1997-12-04
+ */
+	ilist = NIL;
+	while (dlist != NIL)
+	{
+		constraint = lfirst(dlist);
+		if (nodeTag(constraint) != T_Constraint)
+			elog(WARN,"parser: internal error; unrecognized deferred node",NULL);
+
+		if ((constraint->contype != CONSTR_PRIMARY)
+		 && (constraint->contype != CONSTR_UNIQUE))
+			elog(WARN,"parser: internal error; illegal deferred constraint",NULL);
+
+#if PARSEDEBUG
+printf("transformCreateStmt- found deferred constraint %s\n",
+ ((constraint->name != NULL)? constraint->name: "(unknown)"));
+#endif
+
+#if PARSEDEBUG
+printf("transformCreateStmt- found deferred %s clause\n",
+ (constraint->contype == CONSTR_PRIMARY? "PRIMARY KEY": "UNIQUE"));
+#endif
+		index = makeNode(IndexStmt);
+		ilist = lappend(ilist, index);
+
+		index->unique = TRUE;
+		if (constraint->name != NULL)
+			index->idxname = constraint->name;
+		else if (constraint->contype == CONSTR_PRIMARY)
+			index->idxname = makeTableName(stmt->relname, "pkey", NULL);
+		else
+			index->idxname = NULL;
+
+		index->relname = stmt->relname;
+		index->accessMethod = "btree";
+		index->indexParams = NIL;
+		index->withClause = NIL;
+		index->whereClause = NULL;
+ 
+		keys = constraint->keys;
+		while (keys != NIL)
+		{
+			key = lfirst(keys);
+#if PARSEDEBUG
+printf("transformCreateStmt- check key %s for column match\n", key->name);
+#endif
+			columns = stmt->tableElts;
+			column = NULL;
+			while (columns != NIL)
+			{
+				column = lfirst(columns);
+#if PARSEDEBUG
+printf("transformCreateStmt- check column %s for key match\n", column->colname);
+#endif
+				if (strcasecmp(column->colname,key->name) == 0) break;
+				else column = NULL;
+				columns = lnext(columns);
+			}
+			if (column == NULL)
+				elog(WARN,"parser: column '%s' in key does not exist",key->name);
+
+			if (constraint->contype == CONSTR_PRIMARY)
+			{
+#if PARSEDEBUG
+printf("transformCreateStmt- mark column %s as NOT NULL\n", column->colname);
+#endif
+				column->is_not_null = TRUE;
+			}
+			iparam = makeNode(IndexElem);
+			iparam->name = strcpy(palloc(strlen(column->colname)+1), column->colname);
+			iparam->args = NIL;
+			iparam->class = NULL;
+			iparam->tname = NULL;
+			index->indexParams = lappend(index->indexParams, iparam);
+
+			if (index->idxname == NULL)
+				index->idxname = makeTableName(stmt->relname, iparam->name, "key", NULL);
+
+			keys = lnext(keys);
+		}
+
+		if (index->idxname == NULL)
+			elog(WARN,"parser: unable to construct implicit index for table %s"
+				"; name too long", stmt->relname);
+
+		dlist = lnext(dlist);
+	}
+
+	q->utilityStmt = (Node *) stmt;
+	extras = ilist;
+
+	return q;
+} /* transformCreateStmt() */
+
 /*
  * transformIndexStmt -
  *	  transforms the qualification of the index statement
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a7bc22d67c2b17c19e8e4704d47cca475792ae95..145a2f0e3d2f9d06ca14344c94a39cc5f32bc6a0 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.76 1997/12/04 00:26:57 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.77 1997/12/04 23:07:23 thomas Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -39,6 +39,7 @@
 #include "nodes/parsenodes.h"
 #include "nodes/print.h"
 #include "parser/gramparse.h"
+#include "parser/parse_type.h"
 #include "utils/acl.h"
 #include "utils/palloc.h"
 #include "catalog/catname.h"
@@ -91,8 +92,6 @@ Oid	param_type(int t); /* used in parse_expr.c */
 
 	Attr				*attr;
 
-	ColumnDef			*coldef;
-	ConstraintDef		*constrdef;
 	TypeName			*typnam;
 	DefElem				*defelt;
 	ParamString			*param;
@@ -149,8 +148,8 @@ Oid	param_type(int t); /* used in parse_expr.c */
 %type <chr>		operation, TriggerOneEvent
 
 %type <list>	stmtblock, stmtmulti,
-		relation_name_list, OptTableElementList, tableElementList,
-		OptInherit, OptConstraint, ConstraintList, definition,
+		relation_name_list, OptTableElementList,
+		OptInherit, definition,
 		opt_with, def_args, def_name_list, func_argtypes,
 		oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
 		opt_column_list, columnList, opt_va_list, va_list,
@@ -184,7 +183,8 @@ Oid	param_type(int t); /* used in parse_expr.c */
 %type <dstmt>	def_rest
 %type <astmt>	insert_rest
 
-%type <coldef>	columnDef, alter_clause
+%type <node>	OptTableElement, ConstraintElem
+%type <node>	columnDef, alter_clause
 %type <defelt>	def_elem
 %type <node>	def_arg, columnElem, where_clause,
 				a_expr, a_expr_or_null, AexprConst,
@@ -211,12 +211,11 @@ Oid	param_type(int t); /* used in parse_expr.c */
 %type <str>		Id, var_value, zone_value
 %type <str>		ColId, ColLabel
 
-%type <constrdef>	ConstraintElem, ConstraintDef
-
-%type <list>	constraint_elem
+%type <node>	TableConstraint
+%type <list>	constraint_expr
 %type <list>	default_expr
-%type <str>		opt_default
-%type <boolean>	opt_constraint
+%type <list>	ColQualList
+%type <node>	ColConstraint, ColConstraintElem
 %type <list>	key_actions, key_action
 %type <str>		key_match, key_reference
 
@@ -236,7 +235,7 @@ Oid	param_type(int t); /* used in parse_expr.c */
  */
 
 /* Keywords (in SQL92 reserved words) */
-%token	ACTION, ADD, ALL, ALTER, AND, ARCHIVE, AS, ASC,
+%token	ACTION, ADD, ALL, ALTER, AND, AS, ASC,
 		BEGIN_TRANS, BETWEEN, BOTH, BY,
 		CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT, 
 		CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, 
@@ -276,6 +275,9 @@ Oid	param_type(int t); /* used in parse_expr.c */
 		SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED, 
 		VACUUM, VERBOSE, VERSION
 
+/* Keywords (obsolete; retain temporarily for parser - thomas 1997-12-04) */
+%token	ARCHIVE
+
 /*
  * Tokens for pg_passwd support.  The CREATEDB and CREATEUSER tokens should go away
  * when some sort of pg_privileges relation is introduced.
@@ -566,9 +568,9 @@ alter_clause:  ADD opt_column columnDef
 				{
 					$$ = $3;
 				}
-			| ADD '(' tableElementList ')'
+			| ADD '(' OptTableElementList ')'
 				{
-					ColumnDef *lp = lfirst($3);
+					Node *lp = lfirst($3);
 
 					if (length($3) != 1)
 						elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
@@ -576,7 +578,7 @@ alter_clause:  ADD opt_column columnDef
 				}
 			| DROP opt_column ColId
 				{	elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
-			| ALTER opt_column ColId SET opt_default
+			| ALTER opt_column ColId SET DEFAULT default_expr
 				{	elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
 			| ALTER opt_column ColId DROP DEFAULT
 				{	elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
@@ -584,130 +586,6 @@ alter_clause:  ADD opt_column columnDef
 				{	elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
 		;
 
-columnDef:  ColId Typename opt_default opt_constraint
-				{
-					$$ = makeNode(ColumnDef);
-					$$->colname = $1;
-					$$->typename = $2;
-					$$->defval = $3;
-					$$->is_not_null = $4;
-				}
-		;
-
-opt_default:  DEFAULT default_expr
-				{
-					$$ = FlattenStringList($2);
-				}
-			| /*EMPTY*/		{ $$ = NULL; }
-	;
-
-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
-				{
-					$3->name = fmtId($3->name);
-					$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
-				}
-			| CAST default_expr AS Typename
-				{
-					$4->name = fmtId($4->name);
-					$$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
-				}
-			| '(' default_expr ')'
-				{	$$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
-			| name '(' default_expr ')'
-				{
-					$$ = makeList( makeString($1), makeString("("), -1);
-					$$ = nconc( $$, $3);
-					$$ = lappend( $$, makeString(")"));
-				}
-			| name '(' ')'
-				{
-					$$ = makeList( makeString($1), makeString("("), -1);
-					$$ = lappend( $$, makeString(")"));
-				}
-			| default_expr Op default_expr
-				{
-					if (!strcmp("<=", $2) || !strcmp(">=", $2))
-						elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
-					$$ = nconc( $1, lcons( makeString( $2), $3));
-				}
-			| Op default_expr
-				{	$$ = lcons( makeString( $1), $2); }
-			| default_expr Op
-				{	$$ = lappend( $1, makeString( $2)); }
-			/* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
-			| CURRENT_DATE
-				{	$$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
-			| CURRENT_TIME
-				{	$$ = lcons( makeString( "'now'::time"), NIL); }
-			| CURRENT_TIME '(' Iconst ')'
-				{
-					if ($3 != 0)
-						elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
-					$$ = lcons( makeString( "'now'::time"), NIL);
-				}
-			| CURRENT_TIMESTAMP
-				{	$$ = lcons( makeString( "now()"), NIL); }
-			| CURRENT_TIMESTAMP '(' Iconst ')'
-				{
-					if ($3 != 0)
-						elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
-					$$ = lcons( makeString( "now()"), NIL);
-				}
-			| CURRENT_USER
-				{	$$ = lcons( makeString( "CURRENT_USER"), NIL); }
-		;
-
-opt_constraint:  NOT NULL_P						{ $$ = TRUE; }
-			| NOT NULL_P UNIQUE
-				{
-					elog(NOTICE,"UNIQUE clause ignored; not yet implemented",NULL);
-					$$ = TRUE;
-				}
-			| NOTNULL							{ $$ = TRUE; }
-			| UNIQUE
-				{
-					elog(NOTICE,"UNIQUE clause ignored; not yet implemented",NULL);
-					$$ = FALSE;
-				}
-			| PRIMARY KEY
-				{
-					elog(NOTICE,"PRIMARY KEY clause ignored; not yet implemented",NULL);
-					$$ = FALSE;
-				}
-			| REFERENCES ColId opt_column_list key_match key_actions
-				{
-					elog(NOTICE,"FOREIGN KEY clause ignored; not yet implemented",NULL);
-					$$ = FALSE;
-				}
-			| /* EMPTY */						{ $$ = FALSE; }
-		;
-
 
 /*****************************************************************************
  *
@@ -786,141 +664,318 @@ copy_delimiter:  USING DELIMITERS Sconst { $$ = $3;}
  *****************************************************************************/
 
 CreateStmt:  CREATE TABLE relation_name '(' OptTableElementList ')'
-				OptInherit OptConstraint OptArchiveType
+				OptInherit OptArchiveType
 				{
 					CreateStmt *n = makeNode(CreateStmt);
 					n->relname = $3;
 					n->tableElts = $5;
 					n->inhRelnames = $7;
-					n->constraints = $8;
+					n->constraints = NIL;
 					$$ = (Node *)n;
 				}
 		;
 
-OptTableElementList:  tableElementList			{ $$ = $1; }
-		| /* EMPTY */							{ $$ = NULL; }
+OptTableElementList:  OptTableElementList ',' OptTableElement
+												{ $$ = lappend($1, $3); }
+			| OptTableElement					{ $$ = lcons($1, NIL); }
+			| /*EMPTY*/							{ $$ = NULL; }
 		;
 
-tableElementList :
-		  tableElementList ',' columnDef
-				{ $$ = lappend($1, $3); }
-		| columnDef
-				{ $$ = lcons($1, NIL); }
+OptTableElement:  columnDef						{ $$ = $1; }
+			| TableConstraint					{ $$ = $1; }
 		;
 
-/*
- *	This was removed in 6.3, but we keep it so people can upgrade
- *	with old pg_dump scripts.
+columnDef:  ColId Typename ColQualList
+				{
+					ColumnDef *n = makeNode(ColumnDef);
+					n->colname = $1;
+					n->typename = $2;
+					n->defval = NULL;
+					n->is_not_null = FALSE;
+					n->constraints = $3;
+					$$ = (Node *)n;
+				}
+		;
+
+/* ColQualList decodes column-specific qualifiers.
+ * Seem to need to specify the explicit combinations
+ *  to eliminate reduce/reduce conflicts.
+ * I think this is because there are no explicit delimiters
+ *  (like commas) between clauses.
+ * - thomas 1997-12-03
  */
-OptArchiveType:  ARCHIVE '=' NONE						{ }
-		| /*EMPTY*/										{ }
+ColQualList:  ColConstraint ColConstraint ColConstraint ColConstraint
+				{ $$ = lappend(lappend(lappend(lcons($1, NIL), $2), $3), $4); }
+			| ColConstraint ColConstraint ColConstraint
+				{ $$ = lappend(lappend(lcons($1, NIL), $2), $3); }
+			| ColConstraint ColConstraint		{ $$ = lappend(lcons($1, NIL), $2); }
+			| ColConstraint						{ $$ = lcons($1, NIL); }
+			| /*EMPTY*/							{ $$ = NULL; }
 		;
 
-OptInherit:  INHERITS '(' relation_name_list ')'		{ $$ = $3; }
-		| /*EMPTY*/										{ $$ = NIL; }
+ColConstraint:
+		CONSTRAINT name ColConstraintElem
+				{
+						Constraint *n = (Constraint *)$3;
+						n->name = fmtId($2);
+						$$ = $3;
+				}
+		| ColConstraintElem
+				{ $$ = $1; }
 		;
 
-OptConstraint:	ConstraintList							{ $$ = $1; }
-		| /*EMPTY*/										{ $$ = NULL; }
+ColConstraintElem:  CHECK '(' constraint_expr ')'
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_CHECK;
+					n->name = NULL;
+					n->def = FlattenStringList($3);
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| DEFAULT default_expr
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_DEFAULT;
+					n->name = NULL;
+					n->def = FlattenStringList($2);
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| NOT NULL_P
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_NOTNULL;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| NOTNULL
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_NOTNULL;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| UNIQUE
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_UNIQUE;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| PRIMARY KEY
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_PRIMARY;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = NULL;
+					$$ = (Node *)n;
+				}
+			| REFERENCES ColId opt_column_list key_match key_actions
+				{
+					elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL);
+					$$ = NULL;
+				}
 		;
 
-ConstraintList:
-		  ConstraintList ',' ConstraintElem
-				{ $$ = lappend($1, $3); }
-		| ConstraintElem
-				{ $$ = lcons($1, NIL); }
+default_expr:  AexprConst
+				{	$$ = makeConstantList((A_Const *) $1); }
+			| NULL_P
+				{	$$ = 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
+				{
+					$3->name = fmtId($3->name);
+					$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
+				}
+			| CAST default_expr AS Typename
+				{
+					$4->name = fmtId($4->name);
+					$$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
+				}
+			| '(' default_expr ')'
+				{	$$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
+			| name '(' default_expr ')'
+				{
+					$$ = makeList( makeString($1), makeString("("), -1);
+					$$ = nconc( $$, $3);
+					$$ = lappend( $$, makeString(")"));
+				}
+			| name '(' ')'
+				{
+					$$ = makeList( makeString($1), makeString("("), -1);
+					$$ = lappend( $$, makeString(")"));
+				}
+			| default_expr Op default_expr
+				{
+					if (!strcmp("<=", $2) || !strcmp(">=", $2))
+						elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
+					$$ = nconc( $1, lcons( makeString( $2), $3));
+				}
+			| Op default_expr
+				{	$$ = lcons( makeString( $1), $2); }
+			| default_expr Op
+				{	$$ = lappend( $1, makeString( $2)); }
+			/* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
+			| CURRENT_DATE
+				{	$$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
+			| CURRENT_TIME
+				{	$$ = lcons( makeString( "'now'::time"), NIL); }
+			| CURRENT_TIME '(' Iconst ')'
+				{
+					if ($3 != 0)
+						elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
+					$$ = lcons( makeString( "'now'::time"), NIL);
+				}
+			| CURRENT_TIMESTAMP
+				{	$$ = lcons( makeString( "now()"), NIL); }
+			| CURRENT_TIMESTAMP '(' Iconst ')'
+				{
+					if ($3 != 0)
+						elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+					$$ = lcons( makeString( "now()"), NIL);
+				}
+			| CURRENT_USER
+				{	$$ = lcons( makeString( "CURRENT_USER"), NIL); }
 		;
 
-ConstraintElem:
-		CONSTRAINT name ConstraintDef
+/* ConstraintElem specifies constraint syntax which is not embedded into
+ *  a column definition. ColConstraintElem specifies the embedded form.
+ * - thomas 1997-12-03
+ */
+TableConstraint:  CONSTRAINT name ConstraintElem
 				{
-						$3->name = fmtId($2);
+						Constraint *n = (Constraint *)$3;
+						n->name = fmtId($2);
 						$$ = $3;
 				}
-		| ConstraintDef			{ $$ = $1; }
+		| ConstraintElem
+				{ $$ = $1; }
 		;
 
-ConstraintDef:	CHECK constraint_elem
+ConstraintElem:  CHECK '(' constraint_expr ')'
 				{
-					ConstraintDef *constr = palloc (sizeof(ConstraintDef));
-					constr->type = CONSTR_CHECK;
-					constr->name = NULL;
-					constr->def = FlattenStringList($2);
-					$$ = constr;
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_CHECK;
+					n->name = NULL;
+					n->def = FlattenStringList($3);
+					$$ = (Node *)n;
 				}
 		| UNIQUE '(' columnList ')'
-				{	elog(NOTICE,"CREATE TABLE/UNIQUE clause ignored; not yet implemented",NULL); }
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_UNIQUE;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = $3;
+					$$ = (Node *)n;
+				}
 		| PRIMARY KEY '(' columnList ')'
-				{	elog(NOTICE,"CREATE TABLE/PRIMARY KEY clause ignored; not yet implemented",NULL); }
+				{
+					Constraint *n = makeNode(Constraint);
+					n->contype = CONSTR_PRIMARY;
+					n->name = NULL;
+					n->def = NULL;
+					n->keys = $4;
+					$$ = (Node *)n;
+				}
 		| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
 				{	elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL); }
 		;
 
-constraint_elem:  AexprConst
+constraint_expr:  AexprConst
 				{	$$ = makeConstantList((A_Const *) $1); }
-			| Pnull
+			| NULL_P
 				{	$$ = lcons( makeString("NULL"), NIL); }
 			| ColId
 				{
 					$$ = lcons( makeString(fmtId($1)), NIL);
 				}
-			| '-' constraint_elem %prec UMINUS
+			| '-' constraint_expr %prec UMINUS
 				{	$$ = lcons( makeString( "-"), $2); }
-			| constraint_elem '+' constraint_elem
+			| constraint_expr '+' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "+"), $3)); }
-			| constraint_elem '-' constraint_elem
+			| constraint_expr '-' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "-"), $3)); }
-			| constraint_elem '/' constraint_elem
+			| constraint_expr '/' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "/"), $3)); }
-			| constraint_elem '*' constraint_elem
+			| constraint_expr '*' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "*"), $3)); }
-			| constraint_elem '=' constraint_elem
+			| constraint_expr '=' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "="), $3)); }
-			| constraint_elem '<' constraint_elem
+			| constraint_expr '<' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "<"), $3)); }
-			| constraint_elem '>' constraint_elem
+			| constraint_expr '>' constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( ">"), $3)); }
-			| ':' constraint_elem
+			| ':' constraint_expr
 				{	$$ = lcons( makeString( ":"), $2); }
-			| ';' constraint_elem
+			| ';' constraint_expr
 				{	$$ = lcons( makeString( ";"), $2); }
-			| '|' constraint_elem
+			| '|' constraint_expr
 				{	$$ = lcons( makeString( "|"), $2); }
-			| constraint_elem TYPECAST Typename
+			| constraint_expr TYPECAST Typename
 				{
 					$3->name = fmtId($3->name);
 					$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
 				}
-			| CAST constraint_elem AS Typename
+			| CAST constraint_expr AS Typename
 				{
 					$4->name = fmtId($4->name);
 					$$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
 				}
-			| '(' constraint_elem ')'
+			| '(' constraint_expr ')'
 				{	$$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
-			| name '(' constraint_elem ')'
+			| name '(' constraint_expr ')'
 				{
 					$$ = makeList( makeString($1), makeString("("), -1);
 					$$ = nconc( $$, $3);
 					$$ = lappend( $$, makeString(")"));
 				}
-			| constraint_elem Op constraint_elem
+			| constraint_expr Op constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( $2), $3)); }
-			| constraint_elem AND constraint_elem
+			| constraint_expr AND constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "AND"), $3)); }
-			| constraint_elem OR constraint_elem
+			| constraint_expr OR constraint_expr
 				{	$$ = nconc( $1, lcons( makeString( "OR"), $3)); }
-			| Op constraint_elem
+			| Op constraint_expr
 				{	$$ = lcons( makeString( $1), $2); }
-			| constraint_elem Op
+			| constraint_expr Op
 				{	$$ = lappend( $1, makeString( $2)); }
-			| constraint_elem IS TRUE_P
+			| constraint_expr IS TRUE_P
 				{	$$ = lappend( $1, makeString( "IS TRUE")); }
-			| constraint_elem IS FALSE_P
+			| constraint_expr IS FALSE_P
 				{	$$ = lappend( $1, makeString( "IS FALSE")); }
-			| constraint_elem IS NOT TRUE_P
+			| constraint_expr IS NOT TRUE_P
 				{	$$ = lappend( $1, makeString( "IS NOT TRUE")); }
-			| constraint_elem IS NOT FALSE_P
+			| constraint_expr IS NOT FALSE_P
 				{	$$ = lappend( $1, makeString( "IS NOT FALSE")); }
 		;
 
@@ -944,6 +999,18 @@ key_reference:  NO ACTION				{ $$ = NULL; }
 		| SET NULL_P					{ $$ = NULL; }
 		;
 
+OptInherit:  INHERITS '(' relation_name_list ')'		{ $$ = $3; }
+		| /*EMPTY*/										{ $$ = NIL; }
+		;
+
+/*
+ *	"ARCHIVE" keyword was removed in 6.3, but we keep it for now
+ *  so people can upgrade with old pg_dump scripts. - momjian 1997-11-20(?)
+ */
+OptArchiveType:  ARCHIVE '=' NONE						{ }
+		| /*EMPTY*/										{ }
+		;
+
 
 /*****************************************************************************
  *
@@ -1133,7 +1200,7 @@ def_rest:  def_name definition
 		;
 
 def_type:  OPERATOR							{ $$ = OPERATOR; }
-		| Type								{ $$ = TYPE_P; }
+		| TYPE_P							{ $$ = TYPE_P; }
 		| AGGREGATE							{ $$ = AGGREGATE; }
 		;
 
@@ -1537,7 +1604,7 @@ RemoveStmt:  DROP remove_type name
 				}
 		;
 
-remove_type:  Type								{  $$ = TYPE_P; }
+remove_type:  TYPE_P							{  $$ = TYPE_P; }
 		| INDEX									{  $$ = INDEX; }
 		| RULE									{  $$ = RULE; }
 		| VIEW									{  $$ = VIEW; }
@@ -2694,7 +2761,7 @@ opt_interval:  datetime							{ $$ = lcons($1, NIL); }
 
 a_expr_or_null:  a_expr
 				{ $$ = $1;}
-		| Pnull
+		| NULL_P
 				{
 					A_Const *n = makeNode(A_Const);
 					n->val.type = T_Null;
@@ -2845,7 +2912,7 @@ a_expr:  attr opt_indirection
 					t->setof = FALSE;
 
 					if ($3 != 0)
-						elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
+						elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
 
 					$$ = (Node *)n;
 				}
@@ -2880,7 +2947,7 @@ a_expr:  attr opt_indirection
 					t->setof = FALSE;
 
 					if ($3 != 0)
-						elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
+						elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
 
 					$$ = (Node *)n;
 				}
@@ -3566,9 +3633,6 @@ SpecialRuleRelation:  CURRENT
 				}
 		;
 
-Type:	TYPE_P;
-Pnull:	NULL_P;
-
 %%
 
 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)