diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5790f87..6f5ffb3 100644
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
***************
*** 1420,1425 **** index_build(Relation heapRelation,
--- 1420,1435 ----
procedure = indexRelation->rd_am->ambuild;
Assert(RegProcedureIsValid(procedure));
+ if (indexInfo->ii_ToastForRelName != NULL)
+ ereport(DEBUG1,
+ (errmsg("building TOAST index for table \"%s\"",
+ indexInfo->ii_ToastForRelName)));
+ else
+ ereport(DEBUG1,
+ (errmsg("building index \"%s\" on table \"%s\"",
+ RelationGetRelationName(indexRelation),
+ RelationGetRelationName(heapRelation))));
+
/*
* Switch to the table owner's userid, so that any index functions are run
* as that user. Also lock down security-restricted operations and
***************
*** 2412,2418 **** IndexGetRelation(Oid indexId)
* reindex_index - This routine is used to recreate a single index
*/
void
! reindex_index(Oid indexId, bool skip_constraint_checks)
{
Relation iRel,
heapRelation,
--- 2422,2429 ----
* reindex_index - This routine is used to recreate a single index
*/
void
! reindex_index(Oid indexId, const char *toastFor,
! bool skip_constraint_checks)
{
Relation iRel,
heapRelation,
***************
*** 2470,2475 **** reindex_index(Oid indexId, bool skip_constraint_checks)
--- 2481,2489 ----
indexInfo->ii_ExclusionStrats = NULL;
}
+ /* Pass the name of relation this TOAST index serves, if any. */
+ indexInfo->ii_ToastForRelName = toastFor;
+
/* We'll build a new physical relation for the index */
RelationSetNewRelfilenode(iRel, InvalidTransactionId);
***************
*** 2529,2534 **** reindex_index(Oid indexId, bool skip_constraint_checks)
--- 2543,2551 ----
* reindex_relation - This routine is used to recreate all indexes
* of a relation (and optionally its toast relation too, if any).
*
+ * If this is a TOAST relation, toastFor may bear the parent relation name,
+ * facilitating improved messages.
+ *
* If heap_rebuilt is true, then the relation was just completely rebuilt by
* an operation such as VACUUM FULL or CLUSTER, and therefore its indexes are
* inconsistent with it. This makes things tricky if the relation is a system
***************
*** 2548,2554 **** reindex_index(Oid indexId, bool skip_constraint_checks)
* CommandCounterIncrement will occur after each index rebuild.
*/
bool
! reindex_relation(Oid relid, bool toast_too, bool heap_rebuilt)
{
Relation rel;
Oid toast_relid;
--- 2565,2572 ----
* CommandCounterIncrement will occur after each index rebuild.
*/
bool
! reindex_relation(Oid relid, const char *toastFor,
! bool toast_too, bool heap_rebuilt)
{
Relation rel;
Oid toast_relid;
***************
*** 2625,2631 **** reindex_relation(Oid relid, bool toast_too, bool heap_rebuilt)
if (is_pg_class)
RelationSetIndexList(rel, doneIndexes, InvalidOid);
! reindex_index(indexOid, heap_rebuilt);
CommandCounterIncrement();
--- 2643,2649 ----
if (is_pg_class)
RelationSetIndexList(rel, doneIndexes, InvalidOid);
! reindex_index(indexOid, toastFor, heap_rebuilt);
CommandCounterIncrement();
***************
*** 2648,2658 **** reindex_relation(Oid relid, bool toast_too, bool heap_rebuilt)
if (is_pg_class)
RelationSetIndexList(rel, indexIds, ClassOidIndexId);
- /*
- * Close rel, but continue to hold the lock.
- */
- heap_close(rel, NoLock);
-
result = (indexIds != NIL);
/*
--- 2666,2671 ----
***************
*** 2660,2666 **** reindex_relation(Oid relid, bool toast_too, bool heap_rebuilt)
* still hold the lock on the master table.
*/
if (toast_too && OidIsValid(toast_relid))
! result |= reindex_relation(toast_relid, false, false);
return result;
}
--- 2673,2685 ----
* still hold the lock on the master table.
*/
if (toast_too && OidIsValid(toast_relid))
! result |= reindex_relation(toast_relid, RelationGetRelationName(rel),
! false, false);
!
! /*
! * Close rel, but continue to hold the lock.
! */
! heap_close(rel, NoLock);
return result;
}
diff --git a/src/backend/catalog/tindex 142beae..031471b 100644
*** a/src/backend/catalog/toasting.c
--- b/src/backend/catalog/toasting.c
***************
*** 36,43 **** extern Oid binary_upgrade_next_toast_pg_class_oid;
Oid binary_upgrade_next_toast_pg_type_oid = InvalidOid;
! static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
! Datum reloptions);
static bool needs_toast_table(Relation rel);
--- 36,43 ----
Oid binary_upgrade_next_toast_pg_type_oid = InvalidOid;
! static bool create_toast_table(Relation rel, const char *finalRelName,
! Oid toastOid, Oid toastIndexOid, Datum reloptions);
static bool needs_toast_table(Relation rel);
***************
*** 46,51 **** static bool needs_toast_table(Relation rel);
--- 46,54 ----
* If the table needs a toast table, and doesn't already have one,
* then create a toast table for it.
*
+ * make_new_heap fills finalRelName, so messages display the permanent table
+ * name, not the rewrite-temporary name. Most callers should pass NULL.
+ *
* reloptions for the toast table can be passed, too. Pass (Datum) 0
* for default reloptions.
*
***************
*** 54,60 **** static bool needs_toast_table(Relation rel);
* to end with CommandCounterIncrement if it makes any changes.
*/
void
! AlterTableCreateToastTable(Oid relOid, Datum reloptions)
{
Relation rel;
--- 57,64 ----
* to end with CommandCounterIncrement if it makes any changes.
*/
void
! AlterTableCreateToastTable(Oid relOid, const char *finalRelName,
! Datum reloptions)
{
Relation rel;
***************
*** 66,72 **** AlterTableCreateToastTable(Oid relOid, Datum reloptions)
rel = heap_open(relOid, AccessExclusiveLock);
/* create_toast_table does all the work */
! (void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions);
heap_close(rel, NoLock);
}
--- 70,77 ----
rel = heap_open(relOid, AccessExclusiveLock);
/* create_toast_table does all the work */
! (void) create_toast_table(rel, finalRelName,
! InvalidOid, InvalidOid, reloptions);
heap_close(rel, NoLock);
}
***************
*** 92,98 **** BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
relName)));
/* create_toast_table does all the work */
! if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0))
elog(ERROR, "\"%s\" does not require a toast table",
relName);
--- 97,103 ----
relName)));
/* create_toast_table does all the work */
! if (!create_toast_table(rel, NULL, toastOid, toastIndexOid, (Datum) 0))
elog(ERROR, "\"%s\" does not require a toast table",
relName);
***************
*** 104,114 **** BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
* create_toast_table --- internal workhorse
*
* rel is already opened and exclusive-locked
* toastOid and toastIndexOid are normally InvalidOid, but during
* bootstrap they can be nonzero to specify hand-assigned OIDs
*/
static bool
! create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptions)
{
Oid relOid = RelationGetRelid(rel);
HeapTuple reltup;
--- 109,121 ----
* create_toast_table --- internal workhorse
*
* rel is already opened and exclusive-locked
+ * finalRelName is normally NULL; make_new_heap overrides it
* toastOid and toastIndexOid are normally InvalidOid, but during
* bootstrap they can be nonzero to specify hand-assigned OIDs
*/
static bool
! create_toast_table(Relation rel, const char *finalRelName,
! Oid toastOid, Oid toastIndexOid, Datum reloptions)
{
Oid relOid = RelationGetRelid(rel);
HeapTuple reltup;
***************
*** 255,260 **** create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
--- 262,269 ----
indexInfo->ii_ExclusionOps = NULL;
indexInfo->ii_ExclusionProcs = NULL;
indexInfo->ii_ExclusionStrats = NULL;
+ indexInfo->ii_ToastForRelName
+ = finalRelName != NULL ? finalRelName : RelationGetRelationName(rel);
indexInfo->ii_Unique = true;
indexInfo->ii_ReadyForInserts = true;
indexInfo->ii_Concurrent = false;
diff --git a/src/backend/commands/cluindex 19c3cf9..25f5a3d 100644
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
***************
*** 681,687 **** make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
if (isNull)
reloptions = (Datum) 0;
! AlterTableCreateToastTable(OIDNewHeap, reloptions);
ReleaseSysCache(tuple);
}
--- 681,688 ----
if (isNull)
reloptions = (Datum) 0;
! AlterTableCreateToastTable(OIDNewHeap, RelationGetRelationName(OldHeap),
! reloptions);
ReleaseSysCache(tuple);
}
***************
*** 1395,1401 **** finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
* so no chance to reclaim disk space before commit. We do not need a
* final CommandCounterIncrement() because reindex_relation does it.
*/
! reindex_relation(OIDOldHeap, false, true);
/* Destroy new heap with old filenode */
object.classId = RelationRelationId;
--- 1396,1402 ----
* so no chance to reclaim disk space before commit. We do not need a
* final CommandCounterIncrement() because reindex_relation does it.
*/
! reindex_relation(OIDOldHeap, NULL, false, true);
/* Destroy new heap with old filenode */
object.classId = RelationRelationId;
diff --git a/src/backend/commands/indindex f809a26..b84e2b2 100644
*** a/src/backend/commands/indexcmds.c
--- b/src/backend/commands/indexcmds.c
***************
*** 1597,1603 **** ReindexIndex(RangeVar *indexRelation)
ReleaseSysCache(tuple);
! reindex_index(indOid, false);
}
/*
--- 1597,1603 ----
ReleaseSysCache(tuple);
! reindex_index(indOid, NULL, false);
}
/*
***************
*** 1629,1635 **** ReindexTable(RangeVar *relation)
ReleaseSysCache(tuple);
! if (!reindex_relation(heapOid, true, false))
ereport(NOTICE,
(errmsg("table \"%s\" has no indexes",
relation->relname)));
--- 1629,1635 ----
ReleaseSysCache(tuple);
! if (!reindex_relation(heapOid, NULL, true, false))
ereport(NOTICE,
(errmsg("table \"%s\" has no indexes",
relation->relname)));
***************
*** 1742,1748 **** ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
StartTransactionCommand();
/* functions in indexes may want a snapshot set */
PushActiveSnapshot(GetTransactionSnapshot());
! if (reindex_relation(relid, true, false))
ereport(NOTICE,
(errmsg("table \"%s.%s\" was reindexed",
get_namespace_name(get_rel_namespace(relid)),
--- 1742,1748 ----
StartTransactionCommand();
/* functions in indexes may want a snapshot set */
PushActiveSnapshot(GetTransactionSnapshot());
! if (reindex_relation(relid, NULL, true, false))
ereport(NOTICE,
(errmsg("table \"%s.%s\" was reindexed",
get_namespace_name(get_rel_namespace(relid)),
diff --git a/src/backend/commands/tableindex f3bd565..7c4488e 100644
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 1076,1082 **** ExecuteTruncate(TruncateStmt *stmt)
/*
* Reconstruct the indexes to match, and we're done.
*/
! reindex_relation(heap_relid, true, false);
}
}
--- 1076,1082 ----
/*
* Reconstruct the indexes to match, and we're done.
*/
! reindex_relation(heap_relid, NULL, true, false);
}
}
***************
*** 2981,2987 **** ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
(tab->subcmds[AT_PASS_ADD_COL] ||
tab->subcmds[AT_PASS_ALTER_TYPE] ||
tab->subcmds[AT_PASS_COL_ATTRS]))
! AlterTableCreateToastTable(tab->relid, (Datum) 0);
}
}
--- 2981,2987 ----
(tab->subcmds[AT_PASS_ADD_COL] ||
tab->subcmds[AT_PASS_ALTER_TYPE] ||
tab->subcmds[AT_PASS_COL_ATTRS]))
! AlterTableCreateToastTable(tab->relid, NULL, (Datum) 0);
}
}
***************
*** 3443,3448 **** ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
--- 3443,3457 ----
List *dropped_attrs = NIL;
ListCell *lc;
+ if (newrel)
+ ereport(DEBUG1,
+ (errmsg("rewriting table \"%s\"",
+ RelationGetRelationName(oldrel))));
+ else
+ ereport(DEBUG1,
+ (errmsg("verifying table \"%s\"",
+ RelationGetRelationName(oldrel))));
+
econtext = GetPerTupleExprContext(estate);
/*
***************
*** 3836,3841 **** ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
--- 3845,3854 ----
* Eventually, we'd like to propagate the check or rewrite operation
* into other such tables, but for now, just error out if we find any.
*
+ * CHECK, NOT NULL and DEFAULT constraints and the "oid" system column do
+ * not (currently) follow the row type, so they require no attention here.
+ * The non-propagation of DEFAULT and NOT NULL make ADD COLUMN safe, too.
+ *
* Caller should provide either a table name or a type name (not both) to
* report in the error message, if any.
*
***************
*** 5789,5794 **** validateForeignKeyConstraint(Constraint *fkconstraint,
--- 5802,5811 ----
HeapTuple tuple;
Trigger trig;
+ ereport(DEBUG1,
+ (errmsg("validating foreign key constraint \"%s\"",
+ fkconstraint->conname)));
+
/*
* Build a trigger call structure; we'll need it either way.
*/
diff --git a/src/backend/executor/execMindex 600f7e0..56b10a3 100644
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
***************
*** 2307,2313 **** OpenIntoRel(QueryDesc *queryDesc)
(void) heap_reloptions(RELKIND_TOASTVALUE, reloptions, true);
! AlterTableCreateToastTable(intoRelationId, reloptions);
/*
* And open the constructed table for writing.
--- 2307,2313 ----
(void) heap_reloptions(RELKIND_TOASTVALUE, reloptions, true);
! AlterTableCreateToastTable(intoRelationId, NULL, reloptions);
/*
* And open the constructed table for writing.
diff --git a/src/backend/tcop/utility.index 9500037..e6416e4 100644
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 540,546 **** standard_ProcessUtility(Node *parsetree,
(void) heap_reloptions(RELKIND_TOASTVALUE, toast_options,
true);
! AlterTableCreateToastTable(relOid, toast_options);
}
else if (IsA(stmt, CreateForeignTableStmt))
{
--- 540,546 ----
(void) heap_reloptions(RELKIND_TOASTVALUE, toast_options,
true);
! AlterTableCreateToastTable(relOid, NULL, toast_options);
}
else if (IsA(stmt, CreateForeignTableStmt))
{
diff --git a/src/include/catalog/index 2804c63..12656fa 100644
*** a/src/include/catalog/index.h
--- b/src/include/catalog/index.h
***************
*** 70,77 **** extern double IndexBuildHeapScan(Relation heapRelation,
extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
! extern void reindex_index(Oid indexId, bool skip_constraint_checks);
! extern bool reindex_relation(Oid relid, bool toast_too, bool heap_rebuilt);
extern bool ReindexIsProcessingHeap(Oid heapOid);
extern bool ReindexIsProcessingIndex(Oid indexOid);
--- 70,79 ----
extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
! extern void reindex_index(Oid indexId, const char *toastFor,
! bool skip_constraint_checks);
! extern bool reindex_relation(Oid relid, const char *toastFor,
! bool toast_too, bool heap_rebuilt);
extern bool ReindexIsProcessingHeap(Oid heapOid);
extern bool ReindexIsProcessingIndex(Oid indexOid);
diff --git a/src/include/catalog/tindex de3623a..7bd2bdd 100644
*** a/src/include/catalog/toasting.h
--- b/src/include/catalog/toasting.h
***************
*** 17,23 ****
/*
* toasting.c prototypes
*/
! extern void AlterTableCreateToastTable(Oid relOid, Datum reloptions);
extern void BootstrapToastTable(char *relName,
Oid toastOid, Oid toastIndexOid);
--- 17,24 ----
/*
* toasting.c prototypes
*/
! extern void AlterTableCreateToastTable(Oid relOid, const char *finalRelName,
! Datum reloptions);
extern void BootstrapToastTable(char *relName,
Oid toastOid, Oid toastIndexOid);
diff --git a/src/include/nodes/execnoindex 546b581..46d9d1a 100644
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
***************
*** 64,69 **** typedef struct IndexInfo
--- 64,70 ----
Oid *ii_ExclusionOps; /* array with one entry per column */
Oid *ii_ExclusionProcs; /* array with one entry per column */
uint16 *ii_ExclusionStrats; /* array with one entry per column */
+ const char *ii_ToastForRelName; /* TOAST index only: name of main rel */
bool ii_Unique;
bool ii_ReadyForInserts;
bool ii_Concurrent;
diff --git a/src/test/regress/GNUmakindex 15b9ec4..c33ecb9 100644
diff --git a/src/test/regress/expecindex 3d126bb..282de46 100644
*** a/src/test/regress/expected/alter_table.out
--- b/src/test/regress/expected/alter_table.out
***************
*** 1477,1482 **** create table tab1 (a int, b text);
--- 1477,1648 ----
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;
+ 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
+ --
+ -- ALTER COLUMN ... SET DATA TYPE optimizations
+ --
+ SET client_min_messages = debug1; -- Track rewrites.
+ -- Model a type change that throws the semantics of dependent expressions.
+ CREATE DOMAIN trickint AS int;
+ CREATE FUNCTION touchy_f(trickint) RETURNS int4 LANGUAGE sql AS 'SELECT 100';
+ CREATE FUNCTION touchy_f(int4) RETURNS int4 LANGUAGE sql AS 'SELECT $1';
+ CREATE DOMAIN lendom AS varchar(8);
+ CREATE DOMAIN checkdom AS text CHECK (VALUE LIKE '<%');
+ CREATE TABLE parent (keycol numeric PRIMARY KEY);
+ DEBUG: building TOAST index for table "parent"
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "parent_pkey" for table "parent"
+ DEBUG: building index "parent_pkey" on table "parent"
+ INSERT INTO parent VALUES (0.12), (1.12);
+ CREATE TABLE t (
+ integral int4 NOT NULL,
+ rational numeric(9,4) UNIQUE NOT NULL REFERENCES parent,
+ string varchar(4) NOT NULL,
+ strarr varchar(2)[] NOT NULL,
+ CHECK (touchy_f(integral) < 10),
+ EXCLUDE (integral WITH =)
+ );
+ DEBUG: building TOAST index for table "t"
+ NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_rational_key" for table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ NOTICE: CREATE TABLE / EXCLUDE will create implicit index "t_integral_excl" for table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ CREATE INDEX ON t USING gin (strarr);
+ DEBUG: building index "t_strarr_idx" on table "t"
+ INSERT INTO t VALUES (1, 0.12, '', '{ab,cd}'), (2, 1.12, '', '{ef,gh}');
+ -- Comments "rewrite", "verify" and "noop" signify whether ATRewriteTables
+ -- rewrites, scans or does nothing to the table proper. An "-e" suffix denotes
+ -- an error outcome.
+ ALTER TABLE t ALTER integral TYPE trickint; -- verify-e
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ ERROR: check constraint "t_integral_check" is violated by some row
+ ALTER TABLE t DROP CONSTRAINT t_integral_check;
+ ALTER TABLE t ALTER integral TYPE abstime USING integral::abstime; -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ ALTER TABLE t ALTER integral TYPE oid USING integral::int4; -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ ALTER TABLE t ALTER integral TYPE regtype; -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ ALTER TABLE t ALTER rational TYPE numeric(7,4); -- verify
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: validating foreign key constraint "t_rational_fkey"
+ ALTER TABLE t ALTER rational TYPE numeric(8,4); -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: validating foreign key constraint "t_rational_fkey"
+ ALTER TABLE t ALTER rational TYPE numeric(8,1); -- rewrite-e
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: validating foreign key constraint "t_rational_fkey"
+ ERROR: insert or update on table "t" violates foreign key constraint "t_rational_fkey"
+ DETAIL: Key (rational)=(0.1) is not present in table "parent".
+ ALTER TABLE t ALTER string TYPE varchar(6); -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ ALTER TABLE t ALTER string TYPE lendom; -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ ALTER TABLE t ALTER string TYPE xml USING string::xml; -- verify
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ ALTER TABLE t ALTER string TYPE checkdom; -- verify
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ ALTER TABLE t ALTER string TYPE text USING 'foo'::varchar; -- rewrite
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ ALTER TABLE t ALTER strarr TYPE varchar(4)[]; -- noop
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ ALTER TABLE t ADD CONSTRAINT u0 UNIQUE (integral), -- build index exactly once
+ ALTER integral TYPE int8; -- rewrite
+ NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "u0" for table "t"
+ DEBUG: building TOAST index for table "t"
+ DEBUG: rewriting table "t"
+ DEBUG: building index "t_rational_key" on table "t"
+ DEBUG: building index "t_strarr_idx" on table "t"
+ DEBUG: building index "t_integral_excl" on table "t"
+ DEBUG: building index "u0" on table "t"
+ -- Data and catalog end state. We omit the columns that bear unstable OIDs.
+ SELECT * FROM t ORDER BY 1;
+ integral | rational | string | strarr
+ ----------+----------+--------+---------
+ 1 | 0.1200 | foo | {ab,cd}
+ 2 | 1.1200 | foo | {ef,gh}
+ (2 rows)
+
+ SELECT relname, indclass FROM pg_index JOIN pg_class c ON c.oid = indexrelid
+ WHERE indrelid = 't'::regclass ORDER BY 1;
+ relname | indclass
+ -----------------+----------
+ t_integral_excl | 10029
+ t_rational_key | 10037
+ t_strarr_idx | 10103
+ u0 | 10029
+ (4 rows)
+
+ SELECT relname, attname, atttypid, atttypmod
+ FROM pg_attribute JOIN pg_class c ON c.oid = attrelid
+ WHERE attnum > 0 AND
+ attrelid IN (SELECT indexrelid FROM pg_index WHERE indrelid = 't'::regclass)
+ ORDER BY 1, 2;
+ relname | attname | atttypid | atttypmod
+ -----------------+----------+----------+-----------
+ t_integral_excl | integral | 20 | -1
+ t_rational_key | rational | 1700 | 524296
+ t_strarr_idx | strarr | 1043 | -1
+ u0 | integral | 20 | -1
+ (4 rows)
+
+ -- Done. Retain the table under a less-generic name.
+ ALTER TABLE t RENAME TO alter_type_test;
+ RESET client_min_messages;
--
-- lock levels
--
diff --git a/src/test/regress/expected/big_alternew file mode 100644
index 0000000..1609c01
diff --git a/src/test/regress/sql/alter_table.sql b/index 4895768..8e5090e 100644
*** a/src/test/regress/sql/alter_table.sql
--- b/src/test/regress/sql/alter_table.sql
***************
*** 1094,1099 **** drop table another;
--- 1094,1166 ----
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; -- fails
+ alter table tab1 drop a;
+ alter table tab1 set with oids; -- fails
+
+ --
+ -- ALTER COLUMN ... SET DATA TYPE optimizations
+ --
+ SET client_min_messages = debug1; -- Track rewrites.
+
+ -- Model a type change that throws the semantics of dependent expressions.
+ CREATE DOMAIN trickint AS int;
+ CREATE FUNCTION touchy_f(trickint) RETURNS int4 LANGUAGE sql AS 'SELECT 100';
+ CREATE FUNCTION touchy_f(int4) RETURNS int4 LANGUAGE sql AS 'SELECT $1';
+ CREATE DOMAIN lendom AS varchar(8);
+ CREATE DOMAIN checkdom AS text CHECK (VALUE LIKE '<%');
+
+ CREATE TABLE parent (keycol numeric PRIMARY KEY);
+ INSERT INTO parent VALUES (0.12), (1.12);
+
+ CREATE TABLE t (
+ integral int4 NOT NULL,
+ rational numeric(9,4) UNIQUE NOT NULL REFERENCES parent,
+ string varchar(4) NOT NULL,
+ strarr varchar(2)[] NOT NULL,
+ CHECK (touchy_f(integral) < 10),
+ EXCLUDE (integral WITH =)
+ );
+ CREATE INDEX ON t USING gin (strarr);
+ INSERT INTO t VALUES (1, 0.12, '', '{ab,cd}'), (2, 1.12, '', '{ef,gh}');
+
+ -- Comments "rewrite", "verify" and "noop" signify whether ATRewriteTables
+ -- rewrites, scans or does nothing to the table proper. An "-e" suffix denotes
+ -- an error outcome.
+ ALTER TABLE t ALTER integral TYPE trickint; -- verify-e
+ ALTER TABLE t DROP CONSTRAINT t_integral_check;
+ ALTER TABLE t ALTER integral TYPE abstime USING integral::abstime; -- noop
+ ALTER TABLE t ALTER integral TYPE oid USING integral::int4; -- noop
+ ALTER TABLE t ALTER integral TYPE regtype; -- noop
+ ALTER TABLE t ALTER rational TYPE numeric(7,4); -- verify
+ ALTER TABLE t ALTER rational TYPE numeric(8,4); -- noop
+ ALTER TABLE t ALTER rational TYPE numeric(8,1); -- rewrite-e
+ ALTER TABLE t ALTER string TYPE varchar(6); -- noop
+ ALTER TABLE t ALTER string TYPE lendom; -- noop
+ ALTER TABLE t ALTER string TYPE xml USING string::xml; -- verify
+ ALTER TABLE t ALTER string TYPE checkdom; -- verify
+ ALTER TABLE t ALTER string TYPE text USING 'foo'::varchar; -- rewrite
+ ALTER TABLE t ALTER strarr TYPE varchar(4)[]; -- noop
+ ALTER TABLE t ADD CONSTRAINT u0 UNIQUE (integral), -- build index exactly once
+ ALTER integral TYPE int8; -- rewrite
+
+ -- Data and catalog end state. We omit the columns that bear unstable OIDs.
+ SELECT * FROM t ORDER BY 1;
+
+ SELECT relname, indclass FROM pg_index JOIN pg_class c ON c.oid = indexrelid
+ WHERE indrelid = 't'::regclass ORDER BY 1;
+
+ SELECT relname, attname, atttypid, atttypmod
+ FROM pg_attribute JOIN pg_class c ON c.oid = attrelid
+ WHERE attnum > 0 AND
+ attrelid IN (SELECT indexrelid FROM pg_index WHERE indrelid = 't'::regclass)
+ ORDER BY 1, 2;
+
+ -- Done. Retain the table under a less-generic name.
+ ALTER TABLE t RENAME TO alter_type_test;
+ RESET client_min_messages;
--
-- lock levels
diff --git a/src/test/regress/sql/big_alternew file mode 100644
index 0000000..3824d96