*** ./src.orig/./backend/utils/adt/format_type.c	Thu Aug  3 18:47:02 2006
--- ./src/./backend/utils/adt/format_type.c	Thu Aug  3 19:54:02 2006
***************
*** 396,401 ****
--- 396,404 ----
  		typname = NameStr(typeform->typname);
  
  		buf = quote_qualified_identifier(nspname, typname);
+ 
+ 		if ( with_typemod ) 
+ 			buf = psnprintf(strlen(buf) + MAX_INT32_LEN + 3 , "%s(%d)", buf, typemod);
  	}
  
  	if (is_array)
*** ./src.orig/./backend/parser/gram.y	Thu Aug  3 18:47:09 2006
--- ./src/./backend/parser/gram.y	Thu Aug  3 19:54:13 2006
***************
*** 108,113 ****
--- 108,114 ----
  static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
  static Node *doNegate(Node *n, int location);
  static void doNegateFloat(Value *v);
+ static int4 MakeTypeModFromExpr(List *l);
  
  %}
  
***************
*** 326,332 ****
  %type <str>		Sconst comment_text
  %type <str>		RoleId opt_granted_by opt_boolean ColId_or_Sconst
  %type <list>	var_list var_list_or_default
! %type <str>		ColId ColLabel var_name type_name param_name
  %type <node>	var_value zone_value
  
  %type <keyword> unreserved_keyword func_name_keyword
--- 327,333 ----
  %type <str>		Sconst comment_text
  %type <str>		RoleId opt_granted_by opt_boolean ColId_or_Sconst
  %type <list>	var_list var_list_or_default
! %type <str>		ColId ColLabel var_name type_function_name param_name
  %type <node>	var_value zone_value
  
  %type <keyword> unreserved_keyword func_name_keyword
***************
*** 3823,3829 ****
  /*
   * Ideally param_name should be ColId, but that causes too many conflicts.
   */
! param_name:	function_name
  		;
  
  func_return:
--- 3824,3831 ----
  /*
   * Ideally param_name should be ColId, but that causes too many conflicts.
   */
! param_name:	type_function_name
! 			| function_name
  		;
  
  func_return:
***************
*** 3839,3848 ****
  
  /*
   * We would like to make the %TYPE productions here be ColId attrs etc,
!  * but that causes reduce/reduce conflicts.  type_name is next best choice.
   */
  func_type:	Typename								{ $$ = $1; }
! 			| type_name attrs '%' TYPE_P
  				{
  					$$ = makeNode(TypeName);
  					$$->names = lcons(makeString($1), $2);
--- 3841,3851 ----
  
  /*
   * We would like to make the %TYPE productions here be ColId attrs etc,
!  * but that causes reduce/reduce conflicts.  type_function_name or
!  * function_name is next best choice.
   */
  func_type:	Typename								{ $$ = $1; }
! 			| type_function_name attrs '%' TYPE_P
  				{
  					$$ = makeNode(TypeName);
  					$$->names = lcons(makeString($1), $2);
***************
*** 3850,3856 ****
  					$$->typmod = -1;
  					$$->location = @1;
  				}
! 			| SETOF type_name attrs '%' TYPE_P
  				{
  					$$ = makeNode(TypeName);
  					$$->names = lcons(makeString($2), $3);
--- 3853,3876 ----
  					$$->typmod = -1;
  					$$->location = @1;
  				}
! 			| SETOF type_function_name attrs '%' TYPE_P
! 				{
! 					$$ = makeNode(TypeName);
! 					$$->names = lcons(makeString($2), $3);
! 					$$->pct_type = true;
! 					$$->typmod = -1;
! 					$$->setof = TRUE;
! 					$$->location = @2;
! 				}
! 			| function_name attrs '%' TYPE_P
! 				{
! 					$$ = makeNode(TypeName);
! 					$$->names = lcons(makeString($1), $2);
! 					$$->pct_type = true;
! 					$$->typmod = -1;
! 					$$->location = @1;
! 				}
! 			| SETOF function_name attrs '%' TYPE_P
  				{
  					$$ = makeNode(TypeName);
  					$$->names = lcons(makeString($2), $3);
***************
*** 6254,6267 ****
  					{  $$ = NIL; }
  		;
  
- /*
-  * XXX ideally, the production for a qualified typename should be ColId attrs
-  * (there's no obvious reason why the first name should need to be restricted)
-  * and should be an alternative of GenericType (so that it can be used to
-  * specify a type for a literal in AExprConst).  However doing either causes
-  * reduce/reduce conflicts that I haven't been able to find a workaround
-  * for.  FIXME later.
-  */
  SimpleTypename:
  			GenericType								{ $$ = $1; }
  			| Numeric								{ $$ = $1; }
--- 6274,6279 ----
***************
*** 6292,6304 ****
  					}
  					$$->typmod = INTERVAL_TYPMOD($3, $5);
  				}
- 			| type_name attrs
- 				{
- 					$$ = makeNode(TypeName);
- 					$$->names = lcons(makeString($1), $2);
- 					$$->typmod = -1;
- 					$$->location = @1;
- 				}
  		;
  
  /* We have a separate ConstTypename to allow defaulting fixed-length
--- 6304,6309 ----
***************
*** 6308,6327 ****
   * where there is an obvious better choice to make.
   * Note that ConstInterval is not included here since it must
   * be pushed up higher in the rules to accomodate the postfix
!  * options (e.g. INTERVAL '1' YEAR).
   */
  ConstTypename:
! 			GenericType								{ $$ = $1; }
! 			| Numeric								{ $$ = $1; }
  			| ConstBit								{ $$ = $1; }
  			| ConstCharacter						{ $$ = $1; }
  			| ConstDatetime							{ $$ = $1; }
  		;
  
  GenericType:
! 			type_name
  				{
  					$$ = makeTypeName($1);
  					$$->location = @1;
  				}
  		;
--- 6313,6354 ----
   * where there is an obvious better choice to make.
   * Note that ConstInterval is not included here since it must
   * be pushed up higher in the rules to accomodate the postfix
!  * options (e.g. INTERVAL '1' YEAR). Likewise, we have to handle
!  * the generic-type-name case in AExprConst to avoid premature
!  * reduce/reduce conflicts against function names.
   */
  ConstTypename:
! 			Numeric									{ $$ = $1; }
  			| ConstBit								{ $$ = $1; }
  			| ConstCharacter						{ $$ = $1; }
  			| ConstDatetime							{ $$ = $1; }
  		;
  
  GenericType:
! 			type_function_name
  				{
  					$$ = makeTypeName($1);
+ 					$$->typmod = -1;
+ 					$$->location = @1;
+ 				}
+ 			| type_function_name attrs
+ 				{
+ 					$$ = makeNode(TypeName);
+ 					$$->names = lcons(makeString($1), $2);
+ 					$$->typmod = -1;
+ 					$$->location = @1;
+ 				}
+ 			| type_function_name '(' expr_list ')'
+ 				{
+ 					$$ = makeTypeName($1);
+ 					$$->typmod = MakeTypeModFromExpr( $3 );
+ 					$$->location = @1;
+ 				}
+ 			| type_function_name attrs '(' expr_list ')'
+ 				{
+ 					$$ = makeNode(TypeName);
+ 					$$->names = lcons(makeString($1), $2);
+ 					$$->typmod = MakeTypeModFromExpr( $4 );
  					$$->location = @1;
  				}
  		;
***************
*** 8275,8286 ****
  /*
   * The production for a qualified func_name has to exactly match the
   * production for a qualified columnref, because we cannot tell which we
!  * are parsing until we see what comes after it ('(' for a func_name,
   * anything else for a columnref).  Therefore we allow 'indirection' which
   * may contain subscripts, and reject that case in the C code.  (If we
   * ever implement SQL99-like methods, such syntax may actually become legal!)
   */
! func_name:	function_name
  					{ $$ = list_make1(makeString($1)); }
  			| relation_name indirection
  					{ $$ = check_func_name(lcons(makeString($1), $2)); }
--- 8302,8315 ----
  /*
   * The production for a qualified func_name has to exactly match the
   * production for a qualified columnref, because we cannot tell which we
!  * are parsing until we see what comes after it ('(' or Sconst for a func_name,
   * anything else for a columnref).  Therefore we allow 'indirection' which
   * may contain subscripts, and reject that case in the C code.  (If we
   * ever implement SQL99-like methods, such syntax may actually become legal!)
   */
! func_name:	type_function_name
! 					{ $$ = list_make1(makeString($1)); }
! 			| function_name
  					{ $$ = list_make1(makeString($1)); }
  			| relation_name indirection
  					{ $$ = check_func_name(lcons(makeString($1), $2)); }
***************
*** 8338,8343 ****
--- 8367,8390 ----
  					n->val.val.str = $2;
  					$$ = (Node *)n;
  				}
+ 			| func_name Sconst
+ 				{
+ 					A_Const *n = makeNode(A_Const);
+ 					n->typename = makeTypeNameFromNameList( $1 );
+ 					n->typename->typmod = -1;
+ 					n->val.type = T_String;
+ 					n->val.val.str = $2;
+ 					$$ = (Node *)n;
+ 				}
+ 			| func_name '(' expr_list ')' Sconst
+ 				{
+ 					A_Const *n = makeNode(A_Const);
+ 					n->typename = makeTypeNameFromNameList( $1 );
+ 					n->typename->typmod = MakeTypeModFromExpr( $3 );
+ 					n->val.type = T_String;
+ 					n->val.val.str = $5;
+ 					$$ = (Node *)n;
+ 				}
  			| ConstInterval Sconst opt_interval
  				{
  					A_Const *n = makeNode(A_Const);
***************
*** 8414,8431 ****
  			| col_name_keyword						{ $$ = pstrdup($1); }
  		;
  
! /* Type identifier --- names that can be type names.
   */
! type_name:	IDENT									{ $$ = $1; }
  			| unreserved_keyword					{ $$ = pstrdup($1); }
- 		;
  
  /* Function identifier --- names that can be function names.
   */
! function_name:
! 			IDENT									{ $$ = $1; }
! 			| unreserved_keyword					{ $$ = pstrdup($1); }
! 			| func_name_keyword						{ $$ = pstrdup($1); }
  		;
  
  /* Column label --- allowed labels in "AS" clauses.
--- 8461,8474 ----
  			| col_name_keyword						{ $$ = pstrdup($1); }
  		;
  
! /* Type/function identifier --- names that can be type or function names.
   */
! type_function_name:	IDENT							{ $$ = $1; }
  			| unreserved_keyword					{ $$ = pstrdup($1); }
  
  /* Function identifier --- names that can be function names.
   */
! function_name: func_name_keyword					{ $$ = pstrdup($1); }
  		;
  
  /* Column label --- allowed labels in "AS" clauses.
***************
*** 9290,9295 ****
--- 9333,9363 ----
  		strcpy(newval+1, oldval);
  		v->val.str = newval;
  	}
+ }
+ 
+ static int4
+ MakeTypeModFromExpr(List *l) {
+ 	A_Const	*tm;
+ 	int4 typmod;
+ 
+ 	if ( list_length(l)!=1 )
+ 		ereport(ERROR,
+ 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 				errmsg("Invalid type modifier")));
+ 
+ 	tm = (A_Const*)lfirst( list_head(l) );
+ 
+ 	if ( tm->type != T_A_Const || tm->val.type != T_Integer )
+ 		ereport(ERROR,
+ 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 				errmsg("Invalid type modifier")));
+ 
+ 	typmod = tm->val.val.ival;
+ 	if (typmod < 0)
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 					 errmsg("Invalid type modifier")));
+ 	return typmod;
  }
  
  /*
