at2v2-skip-nowork.patch

text/plain

Filename: at2v2-skip-nowork.patch
Type: text/plain
Part: 4
Message: Re: 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: unified
File+
doc/src/sgml/ref/alter_table.sgml 0 0
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 5c94a9f..1f6cafd 100644
*** a/doc/src/sgml/ref/alter_table.sgml
--- b/doc/src/sgml/ref/alter_table.sgml
***************
*** 345,353 **** ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
        for details on the available parameters.  Note that the table contents
        will not be modified immediately by this command; depending on the
        parameter you might need to rewrite the table to get the desired effects.
!       That can be done with <xref linkend="SQL-CLUSTER">
!       or one of the forms of <command>ALTER
!       TABLE</> that forces a table rewrite.
       </para>
  
       <note>
--- 345,353 ----
        for details on the available parameters.  Note that the table contents
        will not be modified immediately by this command; depending on the
        parameter you might need to rewrite the table to get the desired effects.
!       That can be done with <link linkend="SQL-VACUUM">VACUUM
!       FULL</>, <xref linkend="SQL-CLUSTER"> or one of the forms
!       of <command>ALTER TABLE</> that forces a table rewrite.
       </para>
  
       <note>
***************
*** 688,701 **** ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
     </para>
  
     <para>
!     Adding a column with a non-null default or changing the type of an
!     existing column will require the entire table and indexes to be rewritten.
!     This might take a significant amount of time for a large table; and it will
!     temporarily require double the disk space.  Adding or removing a system
      <literal>oid</> column likewise requires rewriting the entire table.
     </para>
  
     <para>
      Adding a <literal>CHECK</> or <literal>NOT NULL</> constraint requires
      scanning the table to verify that existing rows meet the constraint.
     </para>
--- 688,712 ----
     </para>
  
     <para>
!     Adding a column with a non-null default will rewrite the entire table and
!     all indexes.  Changing the type of an existing column will do the same
!     unless a binary-coercible cast implements the type conversion.  Refer to
!     <xref linkend="SQL-CREATECAST"> for further information.  A rewrite might
!     take a significant amount of time for a large table, and it will temporarily
!     require double the disk space.  Adding or removing a system
      <literal>oid</> column likewise requires rewriting the entire table.
     </para>
  
     <para>
+     Similar to the behavior of <link linkend="SQL-VACUUM">VACUUM FULL</>, the
+     rewriting process eliminates any dead space in the table.  Prior
+     to <productname>PostgreSQL</> 9.0, <literal>SET DATA TYPE</>
+     outpaced <literal>VACUUM FULL</> at this task, so it was useful even absent
+     the need for a column type change.  This speed advantage no longer holds,
+     and <literal>SET DATA TYPE</> may not even rewrite the table.
+    </para>
+ 
+    <para>
      Adding a <literal>CHECK</> or <literal>NOT NULL</> constraint requires
      scanning the table to verify that existing rows meet the constraint.
     </para>
***************
*** 719,739 **** ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
     </para>
  
     <para>
-     The fact that <literal>SET DATA TYPE</> requires rewriting the whole table
-     is sometimes an advantage, because the rewriting process eliminates
-     any dead space in the table.  For example, to reclaim the space occupied
-     by a dropped column immediately, the fastest way is:
- <programlisting>
- ALTER TABLE table ALTER COLUMN anycol TYPE anytype;
- </programlisting>
-     where <literal>anycol</> is any remaining table column and
-     <literal>anytype</> is the same type that column already has.
-     This results in no semantically-visible change in the table,
-     but the command forces rewriting, which gets rid of no-longer-useful
-     data.
-    </para>
- 
-    <para>
      The <literal>USING</literal> option of <literal>SET DATA TYPE</> can actually
      specify any expression involving the old values of the row; that is, it
      can refer to other columns as well as the one being converted.  This allows
--- 730,735 ----
diff --git a/src/backend/commands/tablecindex 63e2538..d9cb4a2 100644
*** 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"
***************
*** 3481,3498 **** 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.
--- 3482,3512 ----
  
  	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 cases that should have
! 		 * been WORK_REWRITE by comparing the data.
! 		 */
! 		if (newrel || tab->newvals != NIL)
  		{
  			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.
***************
*** 3509,3525 **** 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 */
--- 3523,3566 ----
  													  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 !newrel when the
+ 					 * typlen actually changed.  attbyval could differ in
+ 					 * theory, but we assume it does not.
+ 					 */
+ 					Assert(newrel ||
+ 						   (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 */
***************
*** 6303,6308 **** ATPrepAlterColumnType(List **wqueue,
--- 6344,6352 ----
  
  	if (tab->relkind == RELKIND_RELATION)
  	{
+ 		CoerceExemptions exempt;
+ 		WorkLevel	worklevel;
+ 
  		/*
  		 * 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
***************
*** 6363,6368 **** ATPrepAlterColumnType(List **wqueue,
--- 6407,6413 ----
  					(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
***************
*** 6373,6387 **** ATPrepAlterColumnType(List **wqueue,
  		newval->expr = (Expr *) transform;
  
  		tab->newvals = lappend(tab->newvals, newval);
! 		tab->worklevel = WORK_REWRITE;
  
  		/*
  		 * If we need to rewrite or scan this table, tables using its 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)
  	{
--- 6418,6440 ----
  		newval->expr = (Expr *) transform;
  
  		tab->newvals = lappend(tab->newvals, newval);
! 		if (!(exempt & COERCE_EXEMPT_NOCHANGE))
! 			worklevel = WORK_REWRITE;
! 		else if (!(exempt & COERCE_EXEMPT_NOERROR))
! 			worklevel = WORK_SCAN;
! 		else					/* both bits set */
! 			worklevel = WORK_NONE;
  
  		/*
  		 * If we need to rewrite or scan this table, tables using its rowtype as
  		 * a column type would need the same treatment.
  		 */
! 		if (worklevel != WORK_NONE)
! 			find_composite_type_dependencies(rel->rd_rel->reltype,
! 											 RelationGetRelationName(rel),
! 											 NULL);
! 
! 		tab->worklevel = Max(tab->worklevel, worklevel);
  	}
  	else if (tab->relkind == RELKIND_COMPOSITE_TYPE)
  	{
diff --git a/src/backend/parser/parse_cindex 5b0dc14..b27e5d2 100644
*** 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,1871 ----
  }
  
  
+ /* 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 (COERCE_EXEMPT_NOCHANGE) and never yield an error
+  * (COERCE_EXEMPT_NOERROR).  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 COERCE_EXEMPT_NOCHANGE invariant from
+  *		its sole argument.  When GetDomainConstraints() == NIL, it also inherits
+  *		COERCE_EXEMPT_NOERROR.  Otherwise, COERCE_EXEMPT_NOERROR 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.
diff --git a/src/include/parser/parse_coindex ceaff2f..4303acf 100644
*** 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);
  
diff --git a/src/test/regress/expected/aindex f2cfc07..dd6365c 100644
*** a/src/test/regress/expected/alter_table.out
--- b/src/test/regress/expected/alter_table.out
***************
*** 1479,1485 **** drop table another;
  -- table's row type
  create table tab1 (a int, b text);
  create table tab2 (x int, y tab1);
! 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;
--- 1479,1486 ----
  -- table's row type
  create table tab1 (a int, b text);
  create table tab2 (x int, y tab1);
! alter table tab1 alter column b type varchar;
! alter table tab1 alter column b type varchar(1); -- 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;
***************
*** 1757,1801 **** 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.
--- 1758,1770 ----
  -- 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.
***************
*** 1959,2016 **** 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"
--- 1928,1937 ----
***************
*** 2121,2142 **** 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"
--- 2042,2047 ----
***************
*** 2186,2245 **** 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
--- 2091,2108 ----
  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
***************
*** 2854,2875 **** 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"
--- 2717,2722 ----
***************
*** 2890,2912 **** 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"
--- 2737,2742 ----
diff --git a/src/test/regress/sql/alter_table.sqindex 1818010..baa3935 100644
*** a/src/test/regress/sql/alter_table.sql
--- b/src/test/regress/sql/alter_table.sql
***************
*** 1095,1101 **** drop table another;
  -- table's row type
  create table tab1 (a int, b text);
  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;
--- 1095,1102 ----
  -- table's row type
  create table tab1 (a int, b text);
  create table tab2 (x int, y tab1);
! alter table tab1 alter column b type varchar;
! alter table tab1 alter column b type varchar(1); -- 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;