Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 537e92e

Browse files
committed
Fix ALTER COLUMN TYPE to preserve the tablespace and reloptions of indexes
it affects. The original coding neglected tablespace entirely (causing the indexes to move to the database's default tablespace) and for an index belonging to a UNIQUE or PRIMARY KEY constraint, it would actually try to assign the parent table's reloptions to the index :-(. Per bug #3672 and subsequent investigation. 8.0 and 8.1 did not have reloptions, but the tablespace bug is present.
1 parent bf673f2 commit 537e92e

File tree

3 files changed

+132
-12
lines changed

3 files changed

+132
-12
lines changed

src/backend/utils/adt/ruleutils.c

+100-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.263 2007/07/17 05:02:02 neilc Exp $
12+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.264 2007/10/13 15:55:40 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -28,6 +28,7 @@
2828
#include "catalog/pg_operator.h"
2929
#include "catalog/pg_trigger.h"
3030
#include "commands/defrem.h"
31+
#include "commands/tablespace.h"
3132
#include "executor/spi.h"
3233
#include "funcapi.h"
3334
#include "nodes/makefuncs.h"
@@ -126,12 +127,13 @@ static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
126127
static void decompile_column_index_array(Datum column_index_array, Oid relId,
127128
StringInfo buf);
128129
static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
129-
static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
130+
static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
130131
int prettyFlags);
131132
static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
132133
int prettyFlags);
133134
static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
134135
int prettyFlags);
136+
static Oid get_constraint_index(Oid constraintId);
135137
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
136138
int prettyFlags);
137139
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
@@ -577,14 +579,19 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
577579
* In the extended version, there is a colno argument as well as pretty bool.
578580
* if colno == 0, we want a complete index definition.
579581
* if colno > 0, we only want the Nth index key's variable or expression.
582+
*
583+
* Note that the SQL-function versions of this omit any info about the
584+
* index tablespace; this is intentional because pg_dump wants it that way.
585+
* However pg_get_indexdef_string() includes index tablespace if not default.
580586
* ----------
581587
*/
582588
Datum
583589
pg_get_indexdef(PG_FUNCTION_ARGS)
584590
{
585591
Oid indexrelid = PG_GETARG_OID(0);
586592

587-
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, 0)));
593+
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
594+
false, 0)));
588595
}
589596

590597
Datum
@@ -596,18 +603,20 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS)
596603
int prettyFlags;
597604

598605
prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
599-
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, prettyFlags)));
606+
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
607+
false, prettyFlags)));
600608
}
601609

602610
/* Internal version that returns a palloc'd C string */
603611
char *
604612
pg_get_indexdef_string(Oid indexrelid)
605613
{
606-
return pg_get_indexdef_worker(indexrelid, 0, 0);
614+
return pg_get_indexdef_worker(indexrelid, 0, true, 0);
607615
}
608616

609617
static char *
610-
pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
618+
pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
619+
int prettyFlags)
611620
{
612621
HeapTuple ht_idx;
613622
HeapTuple ht_idxrel;
@@ -798,8 +807,17 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
798807
}
799808

800809
/*
801-
* XXX we don't include the tablespace ... this is for pg_dump
810+
* If it's in a nondefault tablespace, say so, but only if requested
802811
*/
812+
if (showTblSpc)
813+
{
814+
Oid tblspc;
815+
816+
tblspc = get_rel_tablespace(indexrelid);
817+
if (OidIsValid(tblspc))
818+
appendStringInfo(&buf, " TABLESPACE %s",
819+
quote_identifier(get_tablespace_name(tblspc)));
820+
}
803821

804822
/*
805823
* If it's a partial index, decompile and append the predicate
@@ -1014,6 +1032,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
10141032
{
10151033
Datum val;
10161034
bool isnull;
1035+
Oid indexId;
10171036

10181037
/* Start off the constraint definition */
10191038
if (conForm->contype == CONSTRAINT_PRIMARY)
@@ -1032,15 +1051,24 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
10321051

10331052
appendStringInfo(&buf, ")");
10341053

1035-
if (fullCommand && OidIsValid(conForm->conrelid))
1054+
indexId = get_constraint_index(constraintId);
1055+
1056+
/* XXX why do we only print these bits if fullCommand? */
1057+
if (fullCommand && OidIsValid(indexId))
10361058
{
1037-
char *options = flatten_reloptions(conForm->conrelid);
1059+
char *options = flatten_reloptions(indexId);
1060+
Oid tblspc;
10381061

10391062
if (options)
10401063
{
10411064
appendStringInfo(&buf, " WITH (%s)", options);
10421065
pfree(options);
10431066
}
1067+
1068+
tblspc = get_rel_tablespace(indexId);
1069+
if (OidIsValid(tblspc))
1070+
appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1071+
quote_identifier(get_tablespace_name(tblspc)));
10441072
}
10451073

10461074
break;
@@ -1356,7 +1384,69 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
13561384
}
13571385

13581386

1359-
/* ----------
1387+
/*
1388+
* get_constraint_index
1389+
* Given the OID of a unique or primary-key constraint, return the
1390+
* OID of the underlying unique index.
1391+
*
1392+
* Return InvalidOid if the index couldn't be found; this suggests the
1393+
* given OID is bogus, but we leave it to caller to decide what to do.
1394+
*/
1395+
static Oid
1396+
get_constraint_index(Oid constraintId)
1397+
{
1398+
Oid indexId = InvalidOid;
1399+
Relation depRel;
1400+
ScanKeyData key[3];
1401+
SysScanDesc scan;
1402+
HeapTuple tup;
1403+
1404+
/* Search the dependency table for the dependent index */
1405+
depRel = heap_open(DependRelationId, AccessShareLock);
1406+
1407+
ScanKeyInit(&key[0],
1408+
Anum_pg_depend_refclassid,
1409+
BTEqualStrategyNumber, F_OIDEQ,
1410+
ObjectIdGetDatum(ConstraintRelationId));
1411+
ScanKeyInit(&key[1],
1412+
Anum_pg_depend_refobjid,
1413+
BTEqualStrategyNumber, F_OIDEQ,
1414+
ObjectIdGetDatum(constraintId));
1415+
ScanKeyInit(&key[2],
1416+
Anum_pg_depend_refobjsubid,
1417+
BTEqualStrategyNumber, F_INT4EQ,
1418+
Int32GetDatum(0));
1419+
1420+
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1421+
SnapshotNow, 3, key);
1422+
1423+
while (HeapTupleIsValid(tup = systable_getnext(scan)))
1424+
{
1425+
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1426+
1427+
/*
1428+
* We assume any internal dependency of an index on the constraint
1429+
* must be what we are looking for. (The relkind test is just
1430+
* paranoia; there shouldn't be any such dependencies otherwise.)
1431+
*/
1432+
if (deprec->classid == RelationRelationId &&
1433+
deprec->objsubid == 0 &&
1434+
deprec->deptype == DEPENDENCY_INTERNAL &&
1435+
get_rel_relkind(deprec->objid) == RELKIND_INDEX)
1436+
{
1437+
indexId = deprec->objid;
1438+
break;
1439+
}
1440+
}
1441+
1442+
systable_endscan(scan);
1443+
heap_close(depRel, AccessShareLock);
1444+
1445+
return indexId;
1446+
}
1447+
1448+
1449+
/*
13601450
* deparse_expression - General utility for deparsing expressions
13611451
*
13621452
* calls deparse_expression_pretty with all prettyPrinting disabled

src/backend/utils/cache/lsyscache.c

+30-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.152 2007/05/11 17:57:12 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.153 2007/10/13 15:55:40 tgl Exp $
1111
*
1212
* NOTES
1313
* Eventually, the index information should go through here, too.
@@ -1611,6 +1611,35 @@ get_rel_relkind(Oid relid)
16111611
return '\0';
16121612
}
16131613

1614+
/*
1615+
* get_rel_tablespace
1616+
*
1617+
* Returns the pg_tablespace OID associated with a given relation.
1618+
*
1619+
* Note: InvalidOid might mean either that we couldn't find the relation,
1620+
* or that it is in the database's default tablespace.
1621+
*/
1622+
Oid
1623+
get_rel_tablespace(Oid relid)
1624+
{
1625+
HeapTuple tp;
1626+
1627+
tp = SearchSysCache(RELOID,
1628+
ObjectIdGetDatum(relid),
1629+
0, 0, 0);
1630+
if (HeapTupleIsValid(tp))
1631+
{
1632+
Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1633+
Oid result;
1634+
1635+
result = reltup->reltablespace;
1636+
ReleaseSysCache(tp);
1637+
return result;
1638+
}
1639+
else
1640+
return InvalidOid;
1641+
}
1642+
16141643

16151644
/* ---------- TYPE CACHE ---------- */
16161645

src/include/utils/lsyscache.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.119 2007/06/06 23:00:47 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.120 2007/10/13 15:55:40 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -86,6 +86,7 @@ extern char *get_rel_name(Oid relid);
8686
extern Oid get_rel_namespace(Oid relid);
8787
extern Oid get_rel_type_id(Oid relid);
8888
extern char get_rel_relkind(Oid relid);
89+
extern Oid get_rel_tablespace(Oid relid);
8990
extern bool get_typisdefined(Oid typid);
9091
extern int16 get_typlen(Oid typid);
9192
extern bool get_typbyval(Oid typid);

0 commit comments

Comments
 (0)