diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4870209d46..0aafb3b139 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.263 2007/07/17 05:02:02 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.264 2007/10/13 15:55:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "catalog/pg_operator.h" #include "catalog/pg_trigger.h" #include "commands/defrem.h" +#include "commands/tablespace.h" #include "executor/spi.h" #include "funcapi.h" #include "nodes/makefuncs.h" @@ -126,12 +127,13 @@ static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags); static void decompile_column_index_array(Datum column_index_array, Oid relId, StringInfo buf); static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags); -static char *pg_get_indexdef_worker(Oid indexrelid, int colno, +static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, int prettyFlags); static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags); static char *pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags); +static Oid get_constraint_index(Oid constraintId); static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags); static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, @@ -577,6 +579,10 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) * In the extended version, there is a colno argument as well as pretty bool. * if colno == 0, we want a complete index definition. * if colno > 0, we only want the Nth index key's variable or expression. + * + * Note that the SQL-function versions of this omit any info about the + * index tablespace; this is intentional because pg_dump wants it that way. + * However pg_get_indexdef_string() includes index tablespace if not default. * ---------- */ Datum @@ -584,7 +590,8 @@ pg_get_indexdef(PG_FUNCTION_ARGS) { Oid indexrelid = PG_GETARG_OID(0); - PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, 0))); + PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, + false, 0))); } Datum @@ -596,18 +603,20 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS) int prettyFlags; prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0; - PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, prettyFlags))); + PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, + false, prettyFlags))); } /* Internal version that returns a palloc'd C string */ char * pg_get_indexdef_string(Oid indexrelid) { - return pg_get_indexdef_worker(indexrelid, 0, 0); + return pg_get_indexdef_worker(indexrelid, 0, true, 0); } static char * -pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags) +pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, + int prettyFlags) { HeapTuple ht_idx; HeapTuple ht_idxrel; @@ -798,8 +807,17 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags) } /* - * XXX we don't include the tablespace ... this is for pg_dump + * If it's in a nondefault tablespace, say so, but only if requested */ + if (showTblSpc) + { + Oid tblspc; + + tblspc = get_rel_tablespace(indexrelid); + if (OidIsValid(tblspc)) + appendStringInfo(&buf, " TABLESPACE %s", + quote_identifier(get_tablespace_name(tblspc))); + } /* * If it's a partial index, decompile and append the predicate @@ -1014,6 +1032,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, { Datum val; bool isnull; + Oid indexId; /* Start off the constraint definition */ if (conForm->contype == CONSTRAINT_PRIMARY) @@ -1032,15 +1051,24 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, appendStringInfo(&buf, ")"); - if (fullCommand && OidIsValid(conForm->conrelid)) + indexId = get_constraint_index(constraintId); + + /* XXX why do we only print these bits if fullCommand? */ + if (fullCommand && OidIsValid(indexId)) { - char *options = flatten_reloptions(conForm->conrelid); + char *options = flatten_reloptions(indexId); + Oid tblspc; if (options) { appendStringInfo(&buf, " WITH (%s)", options); pfree(options); } + + tblspc = get_rel_tablespace(indexId); + if (OidIsValid(tblspc)) + appendStringInfo(&buf, " USING INDEX TABLESPACE %s", + quote_identifier(get_tablespace_name(tblspc))); } break; @@ -1356,7 +1384,69 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS) } -/* ---------- +/* + * get_constraint_index + * Given the OID of a unique or primary-key constraint, return the + * OID of the underlying unique index. + * + * Return InvalidOid if the index couldn't be found; this suggests the + * given OID is bogus, but we leave it to caller to decide what to do. + */ +static Oid +get_constraint_index(Oid constraintId) +{ + Oid indexId = InvalidOid; + Relation depRel; + ScanKeyData key[3]; + SysScanDesc scan; + HeapTuple tup; + + /* Search the dependency table for the dependent index */ + depRel = heap_open(DependRelationId, AccessShareLock); + + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(ConstraintRelationId)); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(constraintId)); + ScanKeyInit(&key[2], + Anum_pg_depend_refobjsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(0)); + + scan = systable_beginscan(depRel, DependReferenceIndexId, true, + SnapshotNow, 3, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); + + /* + * We assume any internal dependency of an index on the constraint + * must be what we are looking for. (The relkind test is just + * paranoia; there shouldn't be any such dependencies otherwise.) + */ + if (deprec->classid == RelationRelationId && + deprec->objsubid == 0 && + deprec->deptype == DEPENDENCY_INTERNAL && + get_rel_relkind(deprec->objid) == RELKIND_INDEX) + { + indexId = deprec->objid; + break; + } + } + + systable_endscan(scan); + heap_close(depRel, AccessShareLock); + + return indexId; +} + + +/* * deparse_expression - General utility for deparsing expressions * * calls deparse_expression_pretty with all prettyPrinting disabled diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index d86a70521e..d82e7debf5 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.152 2007/05/11 17:57:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.153 2007/10/13 15:55:40 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -1611,6 +1611,35 @@ get_rel_relkind(Oid relid) return '\0'; } +/* + * get_rel_tablespace + * + * Returns the pg_tablespace OID associated with a given relation. + * + * Note: InvalidOid might mean either that we couldn't find the relation, + * or that it is in the database's default tablespace. + */ +Oid +get_rel_tablespace(Oid relid) +{ + HeapTuple tp; + + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (HeapTupleIsValid(tp)) + { + Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + Oid result; + + result = reltup->reltablespace; + ReleaseSysCache(tp); + return result; + } + else + return InvalidOid; +} + /* ---------- TYPE CACHE ---------- */ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 0a326cb9ba..b8297bd49c 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.119 2007/06/06 23:00:47 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.120 2007/10/13 15:55:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,6 +86,7 @@ extern char *get_rel_name(Oid relid); extern Oid get_rel_namespace(Oid relid); extern Oid get_rel_type_id(Oid relid); extern char get_rel_relkind(Oid relid); +extern Oid get_rel_tablespace(Oid relid); extern bool get_typisdefined(Oid typid); extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid);