diff -ur postgresql-8.2/src/backend/parser/analyze.c postgresql-8.2-serial/src/backend/parser/analyze.c
--- postgresql-8.2/src/backend/parser/analyze.c	2006-04-30 20:30:39.000000000 +0200
+++ postgresql-8.2-serial/src/backend/parser/analyze.c	2006-06-11 23:36:22.000000000 +0200
@@ -825,40 +825,17 @@
 transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
 						  ColumnDef *column)
 {
-	bool		is_serial;
 	bool		saw_nullable;
 	Constraint *constraint;
 	ListCell   *clist;
 
 	cxt->columns = lappend(cxt->columns, column);
 
-	/* Check for SERIAL pseudo-types */
-	is_serial = false;
-	if (list_length(column->typename->names) == 1)
-	{
-		char	   *typname = strVal(linitial(column->typename->names));
-
-		if (strcmp(typname, "serial") == 0 ||
-			strcmp(typname, "serial4") == 0)
-		{
-			is_serial = true;
-			column->typename->names = NIL;
-			column->typename->typeid = INT4OID;
-		}
-		else if (strcmp(typname, "bigserial") == 0 ||
-				 strcmp(typname, "serial8") == 0)
-		{
-			is_serial = true;
-			column->typename->names = NIL;
-			column->typename->typeid = INT8OID;
-		}
-	}
-
 	/* Do necessary work on the column type declaration */
 	transformColumnType(pstate, column);
 
 	/* Special actions for SERIAL pseudo-types */
-	if (is_serial)
+	if (column->is_serial)
 	{
 		Oid			snamespaceid;
 		char	   *snamespace;
@@ -898,7 +875,7 @@
 		 */
 		seqstmt = makeNode(CreateSeqStmt);
 		seqstmt->sequence = makeRangeVar(snamespace, sname);
-		seqstmt->options = NIL;
+		seqstmt->options = column->seq_opts;
 
 		cxt->blist = lappend(cxt->blist, seqstmt);
 
diff -ur postgresql-8.2/src/backend/parser/gram.y postgresql-8.2-serial/src/backend/parser/gram.y
--- postgresql-8.2/src/backend/parser/gram.y	2006-05-27 19:38:45.000000000 +0200
+++ postgresql-8.2-serial/src/backend/parser/gram.y	2006-06-11 23:42:02.000000000 +0200
@@ -275,6 +275,7 @@
 %type <boolean> opt_instead opt_analyze
 %type <boolean> index_opt_unique opt_verbose opt_full
 %type <boolean> opt_freeze opt_default opt_recheck
+%type <boolean>	ColIdGen ColOptIdGen
 %type <defelt>	opt_binary opt_oids copy_delimiter
 
 %type <boolean> copy_from opt_hold
@@ -284,8 +285,8 @@
 
 %type <node>	fetch_direction select_limit_value select_offset_value
 
-%type <list>	OptSeqList
-%type <defelt>	OptSeqElem
+%type <list>	OptSeqList OptSerialSeqList
+%type <defelt>	OptSeqElem OptSerialSeqElem
 
 %type <istmt>	insert_rest
 
@@ -313,7 +314,7 @@
 %type <range>	relation_expr_opt_alias
 %type <target>	target_el insert_target_el update_target_el insert_column_item
 
-%type <typnam>	Typename SimpleTypename ConstTypename
+%type <typnam>	Typename SimpleTypename SerialTypename ConstTypename
 				GenericType Numeric opt_float
 				Character ConstCharacter
 				CharacterWithLength CharacterWithoutLength
@@ -357,10 +358,10 @@
 
 /* ordinary key words in alphabetical order */
 %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
-	AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
+	AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
 	ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
 
-	BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
+	BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BIGSERIAL BINARY BIT
 	BOOLEAN_P BOTH BY
 
 	CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P
@@ -380,11 +381,11 @@
 	FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
 	FREEZE FROM FULL FUNCTION
 
-	GLOBAL GRANT GRANTED GREATEST GROUP_P
+	GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P
 
 	HANDLER HAVING HEADER_P HOLD HOUR_P
 
-	IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
+	IDENTITY IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
 	INDEX INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
 	INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
 	INTERVAL INTO INVOKER IS ISNULL ISOLATION
@@ -417,7 +418,7 @@
 	ROLE ROLLBACK ROW ROWS RULE
 
 	SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
-	SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
+	SERIAL SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
 	SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
 	STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
 	SYSID SYSTEM_P
@@ -1798,17 +1799,83 @@
 			| TableConstraint					{ $$ = $1; }
 		;
 
-columnDef:	ColId Typename ColQualList
+/*
+ * SERIAL is special, handle it here. Possible cases:
+ * ColID SERIAL
+ * ColID SERIAL GENERATED {ALWAYS | BY DEFAULT}
+ * ColID SERIAL GENERATED [ALWAYS | BY DEFAULT] AS IDENTITY(...)
+ */
+columnDef:	ColId SerialTypename GENERATED ColOptIdGen AS IDENTITY '(' OptSerialSeqList ')' ColQualList
+				{
+					ColumnDef *n = makeNode(ColumnDef);
+					n->colname = $1;
+					n->typename = $2;
+					n->constraints = $10;
+					n->is_local = true;
+					n->is_serial = true;
+					n->force_default = $4;
+					n->seq_opts = $8;
+					$$ = (Node *)n;
+				}
+			| ColId SerialTypename GENERATED ColIdGen ColQualList
+				{
+					ColumnDef *n = makeNode(ColumnDef);
+					n->colname = $1;
+					n->typename = $2;
+					n->constraints = $5;
+					n->is_local = true;
+					n->is_serial = true;
+					n->force_default = $4;
+					n->seq_opts = NIL;
+					$$ = (Node *)n;
+				}
+			| ColId SerialTypename ColQualList
+				{
+					ColumnDef *n = makeNode(ColumnDef);
+					n->colname = $1;
+					n->typename = $2;
+					n->constraints = $3;
+					n->is_local = true;
+					n->is_serial = true;
+					n->force_default = false;
+					n->seq_opts = NIL;
+					$$ = (Node *)n;
+				}
+			| ColId Typename ColQualList
 				{
 					ColumnDef *n = makeNode(ColumnDef);
 					n->colname = $1;
 					n->typename = $2;
 					n->constraints = $3;
 					n->is_local = true;
+					n->is_serial = false;
+					n->force_default = false;
+					n->seq_opts = NIL;
 					$$ = (Node *)n;
 				}
 		;
 
+SerialTypename:	SERIAL
+				{
+					$$ = SystemTypeName("int4");
+				}
+			| BIGSERIAL
+				{
+					$$ = SystemTypeName("int8");
+				}
+		;
+
+ColOptIdGen:
+		ALWAYS										{ $$ = true; }
+			| BY DEFAULT								{ $$ = false; }
+			| /*EMPTY*/								{ $$ = false; }
+		;
+
+ColIdGen:
+		ALWAYS										{ $$ = true; }
+			| BY DEFAULT								{ $$ = false; }
+		;
+
 ColQualList:
 			ColQualList ColConstraint				{ $$ = lappend($1, $2); }
 			| /*EMPTY*/								{ $$ = NIL; }
@@ -2319,6 +2386,48 @@
 				}
 		;
 
+OptSerialSeqList: OptSerialSeqList OptSerialSeqElem					{ $$ = lappend($1, $2); }
+			| /*EMPTY*/								{ $$ = NIL; }
+		;
+
+OptSerialSeqElem: CYCLE
+				{
+					$$ = makeDefElem("cycle", (Node *)makeInteger(TRUE));
+				}
+			| NO CYCLE
+				{
+					$$ = makeDefElem("cycle", (Node *)makeInteger(FALSE));
+				}
+			| INCREMENT opt_by NumericOnly
+				{
+					$$ = makeDefElem("increment", (Node *)$3);
+				}
+			| MAXVALUE NumericOnly
+				{
+					$$ = makeDefElem("maxvalue", (Node *)$2);
+				}
+			| MINVALUE NumericOnly
+				{
+					$$ = makeDefElem("minvalue", (Node *)$2);
+				}
+			| NO MAXVALUE
+				{
+					$$ = makeDefElem("maxvalue", NULL);
+				}
+			| NO MINVALUE
+				{
+					$$ = makeDefElem("minvalue", NULL);
+				}
+			| START opt_with NumericOnly
+				{
+					$$ = makeDefElem("start", (Node *)$3);
+				}
+			| RESTART opt_with NumericOnly
+				{
+					$$ = makeDefElem("restart", (Node *)$3);
+				}
+		;
+
 opt_by:		BY				{}
 			| /* empty */	{}
 	  ;
@@ -8349,6 +8458,7 @@
 			| AGGREGATE
 			| ALSO
 			| ALTER
+			| ALWAYS
 			| ASSERTION
 			| ASSIGNMENT
 			| AT
@@ -8408,6 +8518,7 @@
 			| FORCE
 			| FORWARD
 			| FUNCTION
+			| GENERATED
 			| GLOBAL
 			| GRANTED
 			| HANDLER
@@ -8561,6 +8672,7 @@
  */
 col_name_keyword:
 			  BIGINT
+			| BIGSERIAL
 			| BIT
 			| BOOLEAN_P
 			| CHAR_P
@@ -8589,6 +8701,7 @@
 			| PRECISION
 			| REAL
 			| ROW
+			| SERIAL
 			| SETOF
 			| SMALLINT
 			| SUBSTRING
@@ -8676,6 +8789,7 @@
 			| GRANT
 			| GROUP_P
 			| HAVING
+			| IDENTITY
 			| IN_P
 			| INITIALLY
 			| INTERSECT
diff -ur postgresql-8.2/src/backend/parser/keywords.c postgresql-8.2-serial/src/backend/parser/keywords.c
--- postgresql-8.2/src/backend/parser/keywords.c	2006-03-05 16:58:32.000000000 +0100
+++ postgresql-8.2-serial/src/backend/parser/keywords.c	2006-06-11 23:29:39.000000000 +0200
@@ -41,6 +41,7 @@
 	{"all", ALL},
 	{"also", ALSO},
 	{"alter", ALTER},
+	{"always", ALWAYS},
 	{"analyse", ANALYSE},		/* British spelling */
 	{"analyze", ANALYZE},
 	{"and", AND},
@@ -58,6 +59,7 @@
 	{"begin", BEGIN_P},
 	{"between", BETWEEN},
 	{"bigint", BIGINT},
+	{"bigserial", BIGSERIAL},
 	{"binary", BINARY},
 	{"bit", BIT},
 	{"boolean", BOOLEAN_P},
@@ -150,6 +152,7 @@
 	{"from", FROM},
 	{"full", FULL},
 	{"function", FUNCTION},
+	{"generated", GENERATED},
 	{"global", GLOBAL},
 	{"grant", GRANT},
 	{"granted", GRANTED},
@@ -160,6 +163,7 @@
 	{"header", HEADER_P},
 	{"hold", HOLD},
 	{"hour", HOUR_P},
+	{"identity", IDENTITY},
 	{"if", IF_P},
 	{"ilike", ILIKE},
 	{"immediate", IMMEDIATE},
@@ -297,6 +301,9 @@
 	{"security", SECURITY},
 	{"select", SELECT},
 	{"sequence", SEQUENCE},
+	{"serial", SERIAL},
+	{"serial4", SERIAL},
+	{"serial8", BIGSERIAL},
 	{"serializable", SERIALIZABLE},
 	{"session", SESSION},
 	{"session_user", SESSION_USER},
diff -ur postgresql-8.2/src/include/nodes/parsenodes.h postgresql-8.2-serial/src/include/nodes/parsenodes.h
--- postgresql-8.2/src/include/nodes/parsenodes.h	2006-04-30 20:30:40.000000000 +0200
+++ postgresql-8.2-serial/src/include/nodes/parsenodes.h	2006-06-11 23:37:15.000000000 +0200
@@ -394,6 +394,9 @@
 	char	   *cooked_default; /* nodeToString representation */
 	List	   *constraints;	/* other constraints on column */
 	RangeVar   *support;		/* supporting relation, if any */
+	bool		is_serial;	/* the column is SERIAL */
+	bool		force_default;	/* the column is SERIAL GENERATED ALWAYS */
+	List	   *seq_opts;		/* the column is SERIAL ... AS IDENTITY(...) */
 } ColumnDef;
 
 /*
