at2-skip-nowork.patch

text/plain

Filename: at2-skip-nowork.patch
Type: text/plain
Part: 0
Message: ALTER TYPE 2: skip already-provable no-work rewrites

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
src/backend/commands/tablecmds.c 93 0
src/backend/parser/parse_coerce.c 60 0
src/include/parser/parse_coerce.h 7 0
src/test/regress/expected/alter_table.out 7 0
src/test/regress/expected/rowtypes.out 3 0
src/test/regress/sql/alter_table.sql 2 0
src/test/regress/sql/rowtypes.sql 3 0
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 71,76 ****
--- 71,77 ----
  #include "storage/smgr.h"
  #include "utils/acl.h"
  #include "utils/builtins.h"
+ #include "utils/datum.h"
  #include "utils/fmgroids.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
***************
*** 140,147 **** typedef struct AlteredTableInfo
  	/* Information saved by Phases 1/2 for Phase 3: */
  	List	   *constraints;	/* List of NewConstraint */
  	List	   *newvals;		/* List of NewColumnValue */
  	bool		new_notnull;	/* T if we added new NOT NULL constraints */
- 	bool		new_changeoids; /* T if we added/dropped the OID column */
  	Oid			newTableSpace;	/* new tablespace; 0 means no change */
  	/* Objects to rebuild after completing ALTER TYPE operations */
  	List	   *changedConstraintOids;	/* OIDs of constraints to rebuild */
--- 141,149 ----
  	/* Information saved by Phases 1/2 for Phase 3: */
  	List	   *constraints;	/* List of NewConstraint */
  	List	   *newvals;		/* List of NewColumnValue */
+ 	bool		new_bits;		/* Could stored tuple or OID bits change? */
+ 	bool		mayerror;		/* Could the newval expressions throw errors? */
  	bool		new_notnull;	/* T if we added new NOT NULL constraints */
  	Oid			newTableSpace;	/* new tablespace; 0 means no change */
  	/* Objects to rebuild after completing ALTER TYPE operations */
  	List	   *changedConstraintOids;	/* OIDs of constraints to rebuild */
***************
*** 3184,3190 **** ATRewriteTables(List **wqueue, LOCKMODE lockmode)
  		 * We only need to rewrite the table if at least one column needs to
  		 * be recomputed, or we are adding/removing the OID column.
  		 */
! 		if (tab->newvals != NIL || tab->new_changeoids)
  		{
  			/* Build a temporary relation and copy data */
  			Relation	OldHeap;
--- 3186,3192 ----
  		 * We only need to rewrite the table if at least one column needs to
  		 * be recomputed, or we are adding/removing the OID column.
  		 */
! 		if (tab->new_bits)
  		{
  			/* Build a temporary relation and copy data */
  			Relation	OldHeap;
***************
*** 3250,3256 **** ATRewriteTables(List **wqueue, LOCKMODE lockmode)
  			 * Test the current data within the table against new constraints
  			 * generated by ALTER TABLE commands, but don't rebuild data.
  			 */
! 			if (tab->constraints != NIL || tab->new_notnull)
  				ATRewriteTable(tab, InvalidOid, lockmode);
  
  			/*
--- 3252,3258 ----
  			 * Test the current data within the table against new constraints
  			 * generated by ALTER TABLE commands, but don't rebuild data.
  			 */
! 			if (tab->mayerror || tab->constraints != NIL || tab->new_notnull)
  				ATRewriteTable(tab, InvalidOid, lockmode);
  
  			/*
***************
*** 3310,3316 **** ATRewriteTables(List **wqueue, LOCKMODE lockmode)
  /*
   * ATRewriteTable: scan or rewrite one table
   *
!  * OIDNewHeap is InvalidOid if we don't need to rewrite
   */
  static void
  ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
--- 3312,3319 ----
  /*
   * ATRewriteTable: scan or rewrite one table
   *
!  * OIDNewHeap is InvalidOid if we don't need to rewrite.  If the only new
!  * constraints are foreign key constraints, we do nothing here.
   */
  static void
  ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
***************
*** 3319,3325 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
  	Relation	newrel;
  	TupleDesc	oldTupDesc;
  	TupleDesc	newTupDesc;
! 	bool		needscan = false;
  	List	   *notnull_attrs;
  	int			i;
  	ListCell   *l;
--- 3322,3328 ----
  	Relation	newrel;
  	TupleDesc	oldTupDesc;
  	TupleDesc	newTupDesc;
! 	bool		needscan = tab->mayerror;
  	List	   *notnull_attrs;
  	int			i;
  	ListCell   *l;
***************
*** 3365,3383 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
  	}
  
  	/*
- 	 * If we need to rewrite the table, the operation has to be propagated to
- 	 * tables that use this table's rowtype as a column type.
- 	 *
- 	 * (Eventually this will probably become true for scans as well, but at
- 	 * the moment a composite type does not enforce any constraints, so it's
- 	 * not necessary/appropriate to enforce them just during ALTER.)
- 	 */
- 	if (newrel)
- 		find_composite_type_dependencies(oldrel->rd_rel->reltype,
- 										 RelationGetRelationName(oldrel),
- 										 NULL);
- 
- 	/*
  	 * Generate the constraint and default execution states
  	 */
  
--- 3368,3373 ----
***************
*** 3430,3435 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
--- 3420,3426 ----
  			needscan = true;
  	}
  
+ 	/* newrel && !needscan arises when only adding OIDs. */
  	if (newrel || needscan)
  	{
  		ExprContext *econtext;
***************
*** 3494,3511 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
  
  		while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
  		{
! 			if (newrel)
  			{
  				Oid			tupOid = InvalidOid;
  
! 				/* Extract data from old tuple */
! 				heap_deform_tuple(tuple, oldTupDesc, values, isnull);
! 				if (oldTupDesc->tdhasoid)
! 					tupOid = HeapTupleGetOid(tuple);
! 
! 				/* Set dropped attributes to null in new tuple */
! 				foreach(lc, dropped_attrs)
! 					isnull[lfirst_int(lc)] = true;
  
  				/*
  				 * Process supplied expressions to replace selected columns.
--- 3485,3515 ----
  
  		while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
  		{
! 			/*
! 			 * If we're rewriting or verifying, compute new tuple values using
! 			 * each transformation expression.  When rewriting, also form a new
! 			 * physical tuple.  In Assert-enabled builds, check for false
! 			 * negatives of tab->new_bits by comparing the data.
! 			 */
! 			if (newrel || tab->mayerror)
  			{
  				Oid			tupOid = InvalidOid;
  
! 				if (newrel
! #ifdef USE_ASSERT_CHECKING
! 					|| assert_enabled
! #endif
! 					)
! 				{
! 					/* Extract data from old tuple */
! 					heap_deform_tuple(tuple, oldTupDesc, values, isnull);
! 					if (oldTupDesc->tdhasoid)
! 						tupOid = HeapTupleGetOid(tuple);
! 
! 					/* Set dropped attributes to null in new tuple */
! 					foreach(lc, dropped_attrs)
! 						isnull[lfirst_int(lc)] = true;
! 				}
  
  				/*
  				 * Process supplied expressions to replace selected columns.
***************
*** 3522,3538 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
  														  econtext,
  													 &isnull[ex->attnum - 1],
  														  NULL);
  				}
  
! 				/*
! 				 * Form the new tuple. Note that we don't explicitly pfree it,
! 				 * since the per-tuple memory context will be reset shortly.
! 				 */
! 				tuple = heap_form_tuple(newTupDesc, values, isnull);
  
! 				/* Preserve OID, if any */
! 				if (newTupDesc->tdhasoid)
! 					HeapTupleSetOid(tuple, tupOid);
  			}
  
  			/* Now check any constraints on the possibly-changed tuple */
--- 3526,3569 ----
  														  econtext,
  													 &isnull[ex->attnum - 1],
  														  NULL);
+ 
+ #ifdef USE_ASSERT_CHECKING
+ 					if (assert_enabled)
+ 					{
+ 						Datum		oldval = values[ex->attnum - 1];
+ 						bool		oldisnull = isnull[ex->attnum - 1];
+ 						Form_pg_attribute f = newTupDesc->attrs[ex->attnum - 1];
+ 
+ 						if (f->attbyval && f->attlen == -1)
+ 							oldval = PointerGetDatum(PG_DETOAST_DATUM(oldval));
+ 
+ 						/*
+ 						 * We don't detect the gross error of new_bits == true when
+ 						 * the typlen actually changed.  attbyval could differ in
+ 						 * theory, but we assume it does not.
+ 						 */
+ 						Assert(tab->new_bits ||
+ 							   (isnull[ex->attnum - 1] == oldisnull
+ 								&& (oldisnull ||
+ 									datumIsEqual(oldval,
+ 												 values[ex->attnum - 1],
+ 												 f->attbyval, f->attlen))));
+ 					}
+ #endif
  				}
  
! 				if (newrel)
! 				{
! 					/*
! 					 * Form the new tuple. Note that we don't explicitly pfree it,
! 					 * since the per-tuple memory context will be reset shortly.
! 					 */
! 					tuple = heap_form_tuple(newTupDesc, values, isnull);
  
! 					/* Preserve OID, if any */
! 					if (newTupDesc->tdhasoid)
! 						HeapTupleSetOid(tuple, tupOid);
! 				}
  			}
  
  			/* Now check any constraints on the possibly-changed tuple */
***************
*** 4283,4288 **** ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
--- 4314,4321 ----
  			newval->expr = defval;
  
  			tab->newvals = lappend(tab->newvals, newval);
+ 			tab->new_bits = true;
+ 			tab->mayerror = true;
  		}
  
  		/*
***************
*** 4299,4305 **** ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
  	 * table to fix that.
  	 */
  	if (isOid)
! 		tab->new_changeoids = true;
  
  	/*
  	 * Add needed dependency entries for the new column.
--- 4332,4338 ----
  	 * table to fix that.
  	 */
  	if (isOid)
! 		tab->new_bits = true;
  
  	/*
  	 * Add needed dependency entries for the new column.
***************
*** 4970,4976 **** ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
  		tab = ATGetQueueEntry(wqueue, rel);
  
  		/* Tell Phase 3 to physically remove the OID column */
! 		tab->new_changeoids = true;
  	}
  }
  
--- 5003,5009 ----
  		tab = ATGetQueueEntry(wqueue, rel);
  
  		/* Tell Phase 3 to physically remove the OID column */
! 		tab->new_bits = true;
  	}
  }
  
***************
*** 4994,5000 **** ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
  	/* suppress schema rights check when rebuilding existing index */
  	check_rights = !is_rebuild;
  	/* skip index build if phase 3 will have to rewrite table anyway */
! 	skip_build = (tab->newvals != NIL);
  	/* suppress notices when rebuilding existing index */
  	quiet = is_rebuild;
  
--- 5027,5033 ----
  	/* suppress schema rights check when rebuilding existing index */
  	check_rights = !is_rebuild;
  	/* skip index build if phase 3 will have to rewrite table anyway */
! 	skip_build = tab->new_bits;
  	/* suppress notices when rebuilding existing index */
  	quiet = is_rebuild;
  
***************
*** 6293,6298 **** ATPrepAlterColumnType(List **wqueue,
--- 6326,6333 ----
  
  	if (tab->relkind == RELKIND_RELATION)
  	{
+ 		CoerceExemptions exempt;
+ 
  		/*
  		 * Set up an expression to transform the old data value to the new type.
  		 * If a USING option was given, transform and use that expression, else
***************
*** 6353,6358 **** ATPrepAlterColumnType(List **wqueue,
--- 6388,6394 ----
  					(errcode(ERRCODE_DATATYPE_MISMATCH),
  					 errmsg("column \"%s\" cannot be cast to type %s",
  							colName, format_type_be(targettype))));
+ 		exempt = GetCoerceExemptions(transform, 1, attnum);
  
  		/*
  		 * Add a work queue item to make ATRewriteTable update the column
***************
*** 6363,6368 **** ATPrepAlterColumnType(List **wqueue,
--- 6399,6423 ----
  		newval->expr = (Expr *) transform;
  
  		tab->newvals = lappend(tab->newvals, newval);
+ 		if (!(exempt & COERCE_EXEMPT_NOCHANGE))
+ 			tab->new_bits = true;
+ 		if (!(exempt & COERCE_EXEMPT_NOERROR))
+ 			tab->mayerror = true;
+ 
+ 		/*
+ 		 * If we need to rewrite the table to update tuple values or scan
+ 		 * it to verify tuple values, tables using this table's rowtype as
+ 		 * a column type would need the same treatment.
+ 		 */
+ 		find_composite_type_dependencies(rel->rd_rel->reltype,
+ 										 RelationGetRelationName(rel),
+ 										 NULL);
+ 	}
+ 	else if (tab->relkind == RELKIND_COMPOSITE_TYPE)
+ 	{
+ 		find_composite_type_dependencies(rel->rd_rel->reltype,
+ 										 NULL,
+ 										 RelationGetRelationName(rel));
  	}
  	else if (tab->relkind == RELKIND_FOREIGN_TABLE)
  	{
***************
*** 6372,6388 **** ATPrepAlterColumnType(List **wqueue,
  					 errmsg("ALTER TYPE USING is not supported on foreign tables")));
  	}
  
- 	if (tab->relkind == RELKIND_COMPOSITE_TYPE)
- 	{
- 		/*
- 		 * For composite types, do this check now.  Tables will check
- 		 * it later when the table is being rewritten.
- 		 */
- 		find_composite_type_dependencies(rel->rd_rel->reltype,
- 										 NULL,
- 										 RelationGetRelationName(rel));
- 	}
- 
  	ReleaseSysCache(tuple);
  
  	/*
--- 6427,6432 ----
*** a/src/backend/parser/parse_coerce.c
--- b/src/backend/parser/parse_coerce.c
***************
*** 19,24 ****
--- 19,25 ----
  #include "catalog/pg_inherits_fn.h"
  #include "catalog/pg_proc.h"
  #include "catalog/pg_type.h"
+ #include "commands/typecmds.h"
  #include "nodes/makefuncs.h"
  #include "nodes/nodeFuncs.h"
  #include "parser/parse_coerce.h"
***************
*** 1805,1810 **** IsBinaryCoercible(Oid srctype, Oid targettype)
--- 1806,1870 ----
  }
  
  
+ /* GetCoerceExemptions()
+  *		Assess invariants of a coercion expression.
+  *
+  * Various common expressions arising from type coercion are subject to
+  * optimizations.  For example, a simple varchar -> text cast will never change
+  * the underlying data (always-noop) and never yield an error (never-error).  A
+  * varchar(8) -> varchar(4) will never change the data, but it may yield an
+  * error.  Given a varno and varattno denoting "the" source datum, determine
+  * which invariants hold for an expression by walking it per these rules:
+  *
+  *	1. A Var with the varno/varattno in question has both invariants.
+  *	2. A RelabelType node inherits the invariants of its sole argument.
+  *	3. A CoerceToDomain node inherits any always-noop invariant from its sole
+  *		argument.  When GetDomainConstraints() == NIL, it also inherits
+  *		never-error.  Otherwise, never-error becomes false.
+  *	4. All other nodes have neither invariant.
+  *
+  * Returns a bit string that may contain the following bits:
+  *	COERCE_EXEMPT_NOCHANGE: expression result will always have the same binary
+  *				representation as a Var expression having the given varno and
+  *				varattno
+  *	COERCE_EXEMPT_NOERROR: expression will never throw an error
+  */
+ CoerceExemptions
+ GetCoerceExemptions(Node *expr,
+ 					Index varno, AttrNumber varattno)
+ {
+ 	CoerceExemptions ret = COERCE_EXEMPT_NOCHANGE | COERCE_EXEMPT_NOERROR;
+ 
+ 	Assert(expr != NULL);
+ 
+ 	for (;;)
+ 	{
+ 		if (IsA(expr, Var)
+ 			&& ((Var *) expr)->varno == varno
+ 			&& ((Var *) expr)->varattno == varattno)
+ 		{
+ 			return ret;
+ 		}
+ 		if (IsA(expr, RelabelType))
+ 		{
+ 			expr = (Node *) ((RelabelType *) expr)->arg;
+ 		}
+ 		else if (IsA(expr, CoerceToDomain))
+ 		{
+ 			CoerceToDomain *d = (CoerceToDomain *) expr;
+ 
+ 			if (GetDomainConstraints(d->resulttype) != NIL)
+ 				ret &= ~COERCE_EXEMPT_NOERROR;
+ 			expr = (Node *) d->arg;
+ 		}
+ 		else
+ 		{
+ 			return 0;
+ 		}
+ 	}
+ }
+ 
+ 
  /*
   * find_coercion_pathway
   *		Look for a coercion pathway between two types.
*** a/src/include/parser/parse_coerce.h
--- b/src/include/parser/parse_coerce.h
***************
*** 30,37 **** typedef enum CoercionPathType
--- 30,44 ----
  	COERCION_PATH_COERCEVIAIO	/* need a CoerceViaIO node */
  } CoercionPathType;
  
+ /* Bits in the return value of GetCoerceExemptions. */
+ typedef int CoerceExemptions;
+ 
+ #define COERCE_EXEMPT_NOCHANGE	0x1		/* expression never changes storage */
+ #define COERCE_EXEMPT_NOERROR	0x2		/* expression never throws an error */
  
  extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
+ extern CoerceExemptions GetCoerceExemptions(Node *expr,
+ 					Index varno, AttrNumber varattno);
  extern bool IsPreferredType(TYPCATEGORY category, Oid type);
  extern TYPCATEGORY TypeCategory(Oid type);
  
*** a/src/test/regress/expected/alter_table.out
--- b/src/test/regress/expected/alter_table.out
***************
*** 1479,1489 **** alter table tab1 alter column b type varchar; -- fails
  ERROR:  cannot alter table "tab1" because column "tab2"."y" uses its rowtype
  alter table tab1 add check (b <> 'foo');
  alter table tab1 add c int not null;
! alter table tab1 add d int not null default 1; -- fails
! ERROR:  cannot alter table "tab1" because column "tab2"."y" uses its rowtype
  alter table tab1 drop a;
! alter table tab1 set with oids;	-- fails
! ERROR:  cannot alter table "tab1" because column "tab2"."y" uses its rowtype
  --
  -- Deeper alter-column-type tests
  --
--- 1479,1487 ----
  ERROR:  cannot alter table "tab1" because column "tab2"."y" uses its rowtype
  alter table tab1 add check (b <> 'foo');
  alter table tab1 add c int not null;
! alter table tab1 add d int not null default 1;
  alter table tab1 drop a;
! alter table tab1 set with oids;
  --
  -- Deeper alter-column-type tests
  --
***************
*** 1754,1798 **** FROM pg_trigger WHERE tgrelid = 't'::regclass ORDER BY tgname;
  -- though mostly not stated here.
  -- Constraint failures induced by a no-work type change.
  ALTER TABLE t ALTER constraint0 TYPE trickint;						-- verify-e
! DEBUG:  Rewriting table "t"
  ERROR:  check constraint "t_constraint0_check" is violated by some row
  ALTER TABLE t ALTER constraint1 TYPE trickint;						-- noop-e
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
  DEBUG:  Rebuilding index "t_touchy_f_idx"
  ERROR:  could not create unique index "t_touchy_f_idx"
  DETAIL:  Key (touchy_f(constraint1))=(100) is duplicated.
  ALTER TABLE t ALTER constraint2 TYPE trickint;						-- noop-e
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
  DEBUG:  Rebuilding index "t_expr_idx"
  ERROR:  could not create unique index "t_expr_idx"
  DETAIL:  Key ((1))=(1) is duplicated.
--- 1752,1764 ----
  -- though mostly not stated here.
  -- Constraint failures induced by a no-work type change.
  ALTER TABLE t ALTER constraint0 TYPE trickint;						-- verify-e
! DEBUG:  Verifying table "t"
  ERROR:  check constraint "t_constraint0_check" is violated by some row
  ALTER TABLE t ALTER constraint1 TYPE trickint;						-- noop-e
  DEBUG:  Rebuilding index "t_touchy_f_idx"
  ERROR:  could not create unique index "t_touchy_f_idx"
  DETAIL:  Key (touchy_f(constraint1))=(100) is duplicated.
  ALTER TABLE t ALTER constraint2 TYPE trickint;						-- noop-e
  DEBUG:  Rebuilding index "t_expr_idx"
  ERROR:  could not create unique index "t_expr_idx"
  DETAIL:  Key ((1))=(1) is duplicated.
***************
*** 1956,2013 **** DEBUG:  Rebuilding index "t_constraint4_key"
  DEBUG:  Validating foreign key constraint "child_keycol_fkey"
  -- Type-specific tests.
  ALTER TABLE t ALTER integral TYPE abstime USING integral::abstime;	-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
  DEBUG:  Rebuilding index "t_integral_key"
  ALTER TABLE t ALTER integral TYPE oid USING integral::int4;			-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
  DEBUG:  Rebuilding index "t_integral_key"
  ALTER TABLE t ALTER integral TYPE regtype;							-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
  DEBUG:  Rebuilding index "t_integral_key"
  ALTER TABLE t ALTER integral TYPE int8;								-- rewrite
  DEBUG:  Rewriting table "t"
--- 1922,1931 ----
***************
*** 2118,2139 **** DEBUG:  Rebuilding index "t_constraint4_key"
  DEBUG:  Rebuilding index "t_integral_key"
  DEBUG:  Rebuilding index "t_rational_key"
  ALTER TABLE t ALTER rational TYPE numeric;							-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
  DEBUG:  Rebuilding index "t_rational_key"
  ALTER TABLE t ALTER rational TYPE numeric(5,4);						-- verify-e
  DEBUG:  Rewriting table "t"
--- 2036,2041 ----
***************
*** 2183,2242 **** ALTER TABLE t ALTER string TYPE shortdom;							-- rewrite-e
  DEBUG:  Rewriting table "t"
  ERROR:  value too long for type character varying(1)
  ALTER TABLE t ALTER string TYPE checkdom;							-- verify
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
  DEBUG:  Rebuilding index "t_string_idx1"
  DEBUG:  Rebuilding index "t_string_idx"
  ALTER TABLE t ALTER string TYPE faildom;							-- verify-e
! DEBUG:  Rewriting table "t"
  ERROR:  value for domain faildom violates check constraint "faildom_check"
  ALTER TABLE t ALTER string TYPE loosedom;							-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
  DEBUG:  Rebuilding index "t_string_idx"
  DEBUG:  Rebuilding index "t_string_idx1"
  ALTER TABLE t ALTER string TYPE text;								-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
  DEBUG:  Rebuilding index "t_string_idx1"
  DEBUG:  Rebuilding index "t_string_idx"
  ALTER TABLE t ALTER string TYPE varchar(20);						-- rewrite-v
--- 2085,2102 ----
  DEBUG:  Rewriting table "t"
  ERROR:  value too long for type character varying(1)
  ALTER TABLE t ALTER string TYPE checkdom;							-- verify
  DEBUG:  Rebuilding index "t_string_idx1"
  DEBUG:  Rebuilding index "t_string_idx"
+ DEBUG:  Verifying table "t"
  ALTER TABLE t ALTER string TYPE faildom;							-- verify-e
! DEBUG:  Rebuilding index "t_string_idx"
! DEBUG:  Rebuilding index "t_string_idx1"
! DEBUG:  Verifying table "t"
  ERROR:  value for domain faildom violates check constraint "faildom_check"
  ALTER TABLE t ALTER string TYPE loosedom;							-- noop
  DEBUG:  Rebuilding index "t_string_idx"
  DEBUG:  Rebuilding index "t_string_idx1"
  ALTER TABLE t ALTER string TYPE text;								-- noop
  DEBUG:  Rebuilding index "t_string_idx1"
  DEBUG:  Rebuilding index "t_string_idx"
  ALTER TABLE t ALTER string TYPE varchar(20);						-- rewrite-v
***************
*** 2851,2872 **** DEBUG:  Rebuilding index "t_stamp_key"
  DEBUG:  Rebuilding index "t_timegap_key"
  DEBUG:  Rebuilding index "t_bits_key"
  ALTER TABLE t ALTER network TYPE inet;								-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
  DEBUG:  Rebuilding index "t_network_key"
  ALTER TABLE t ALTER network TYPE cidr;								-- rewrite-v
  DEBUG:  Rewriting table "t"
--- 2711,2716 ----
***************
*** 2887,2909 **** DEBUG:  Rebuilding index "t_timegap_key"
  DEBUG:  Rebuilding index "t_bits_key"
  DEBUG:  Rebuilding index "t_network_key"
  ALTER TABLE t ALTER document TYPE text;								-- noop
- DEBUG:  Rewriting table "t"
- DEBUG:  Rebuilding index "t_strarr_idx"
- DEBUG:  Rebuilding index "t_square_idx"
- DEBUG:  Rebuilding index "t_touchy_f_idx"
- DEBUG:  Rebuilding index "t_expr_idx"
- DEBUG:  Rebuilding index "t_constraint4_key"
- DEBUG:  Rebuilding index "t_integral_key"
- DEBUG:  Rebuilding index "t_rational_key"
- DEBUG:  Rebuilding index "t_string_idx1"
- DEBUG:  Rebuilding index "t_string_idx"
- DEBUG:  Rebuilding index "t_daytimetz_key"
- DEBUG:  Rebuilding index "t_daytime_key"
- DEBUG:  Rebuilding index "t_stamptz_key"
- DEBUG:  Rebuilding index "t_stamp_key"
- DEBUG:  Rebuilding index "t_timegap_key"
- DEBUG:  Rebuilding index "t_bits_key"
- DEBUG:  Rebuilding index "t_network_key"
  ALTER TABLE t ALTER document TYPE xml USING document::xml;			-- verify
  DEBUG:  Rewriting table "t"
  DEBUG:  Rebuilding index "t_strarr_idx"
--- 2731,2736 ----
*** a/src/test/regress/expected/rowtypes.out
--- b/src/test/regress/expected/rowtypes.out
***************
*** 82,91 **** select * from people;
   (Joe,Blow) | 01-10-1984
  (1 row)
  
! -- at the moment this will not work due to ALTER TABLE inadequacy:
  alter table fullname add column suffix text default '';
! ERROR:  cannot alter table "fullname" because column "people"."fn" uses its rowtype
! -- but this should work:
  alter table fullname add column suffix text default null;
  select * from people;
       fn      |     bd     
--- 82,91 ----
   (Joe,Blow) | 01-10-1984
  (1 row)
  
! -- accepted, but the default does not propagate
  alter table fullname add column suffix text default '';
! alter table fullname drop column suffix;
! -- same effect
  alter table fullname add column suffix text default null;
  select * from people;
       fn      |     bd     
*** a/src/test/regress/sql/alter_table.sql
--- b/src/test/regress/sql/alter_table.sql
***************
*** 1096,1104 **** create table tab2 (x int, y tab1);
  alter table tab1 alter column b type varchar; -- fails
  alter table tab1 add check (b <> 'foo');
  alter table tab1 add c int not null;
! alter table tab1 add d int not null default 1; -- fails
  alter table tab1 drop a;
! alter table tab1 set with oids;	-- fails
  
  --
  -- Deeper alter-column-type tests
--- 1096,1104 ----
  alter table tab1 alter column b type varchar; -- fails
  alter table tab1 add check (b <> 'foo');
  alter table tab1 add c int not null;
! alter table tab1 add d int not null default 1;
  alter table tab1 drop a;
! alter table tab1 set with oids;
  
  --
  -- Deeper alter-column-type tests
*** a/src/test/regress/sql/rowtypes.sql
--- b/src/test/regress/sql/rowtypes.sql
***************
*** 45,54 **** insert into people values ('(Joe,Blow)', '1984-01-10');
  
  select * from people;
  
! -- at the moment this will not work due to ALTER TABLE inadequacy:
  alter table fullname add column suffix text default '';
  
! -- but this should work:
  alter table fullname add column suffix text default null;
  
  select * from people;
--- 45,55 ----
  
  select * from people;
  
! -- accepted, but the default does not propagate
  alter table fullname add column suffix text default '';
+ alter table fullname drop column suffix;
  
! -- same effect
  alter table fullname add column suffix text default null;
  
  select * from people;