diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
index b55bd6d23c2..c33e13a6704 100644
--- a/contrib/pg_upgrade/info.c
+++ b/contrib/pg_upgrade/info.c
@@ -193,15 +193,21 @@ get_db_infos(ClusterInfo *cluster)
int i_datname,
i_oid,
i_spclocation;
+ char query[QUERY_ALLOC];
- res = executeQueryOrDie(conn,
- "SELECT d.oid, d.datname, t.spclocation "
- "FROM pg_catalog.pg_database d "
- " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
- " ON d.dattablespace = t.oid "
- "WHERE d.datallowconn = true "
+ snprintf(query, sizeof(query),
+ "SELECT d.oid, d.datname, %s "
+ "FROM pg_catalog.pg_database d "
+ " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
+ " ON d.dattablespace = t.oid "
+ "WHERE d.datallowconn = true "
/* we don't preserve pg_database.oid so we sort by name */
- "ORDER BY 2");
+ "ORDER BY 2",
+ /* 9.2 removed the spclocation column */
+ (GET_MAJOR_VERSION(old_cluster.major_version) <= 901) ?
+ "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation");
+
+ res = executeQueryOrDie(conn, "%s", query);
i_oid = PQfnumber(res, "oid");
i_datname = PQfnumber(res, "datname");
@@ -265,7 +271,7 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
snprintf(query, sizeof(query),
"SELECT c.oid, n.nspname, c.relname, "
- " c.relfilenode, t.spclocation "
+ " c.relfilenode, %s "
"FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
" ON c.relnamespace = n.oid "
" LEFT OUTER JOIN pg_catalog.pg_tablespace t "
@@ -280,6 +286,9 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
" relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) )) "
/* we preserve pg_class.oid so we sort by it to match old/new */
"ORDER BY 1;",
+ /* 9.2 removed the spclocation column */
+ (GET_MAJOR_VERSION(old_cluster.major_version) <= 901) ?
+ "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation",
/* see the comment at the top of old_8_3_create_sequence_script() */
(GET_MAJOR_VERSION(old_cluster.major_version) <= 803) ?
"" : ", 'S'",
diff --git a/contrib/pg_upgrade/tablespace.c b/contrib/pg_upgrade/tablespace.c
index 08d227c10a0..df2285f3669 100644
--- a/contrib/pg_upgrade/tablespace.c
+++ b/contrib/pg_upgrade/tablespace.c
@@ -44,12 +44,18 @@ get_tablespace_paths(void)
PGresult *res;
int tblnum;
int i_spclocation;
+ char query[QUERY_ALLOC];
- res = executeQueryOrDie(conn,
- "SELECT spclocation "
- "FROM pg_catalog.pg_tablespace "
- "WHERE spcname != 'pg_default' AND "
- " spcname != 'pg_global'");
+ snprintf(query, sizeof(query),
+ "SELECT %s "
+ "FROM pg_catalog.pg_tablespace "
+ "WHERE spcname != 'pg_default' AND "
+ " spcname != 'pg_global'",
+ /* 9.2 removed the spclocation column */
+ (GET_MAJOR_VERSION(old_cluster.major_version) <= 901) ?
+ "t.spclocation" : "pg_catalog.pg_tablespace_location(oid) AS spclocation");
+
+ res = executeQueryOrDie(conn, "%s", query);
if ((os_info.num_tablespaces = PQntuples(res)) != 0)
os_info.tablespaces = (char **) pg_malloc(
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 8156c35916a..b8cc16f72a9 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5391,13 +5391,6 @@
Owner of the tablespace, usually the user who created it
-
- spclocation
- text
-
- Location (directory path) of the tablespace
-
-
spcacl
aclitem[]
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index ddfb29a4338..e7f7fe0e889 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -13611,6 +13611,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
pg_tablespace_databases
+
+ pg_tablespace_location
+
+
pg_typeof
@@ -13758,6 +13762,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
setof oid
get the set of database OIDs that have objects in the tablespace
+
+ pg_tablespace_location(tablespace_oid)
+ text
+ get the path in the filesystem that this tablespace is located in
+
pg_typeof(any)
regtype
diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml
index 811934bd75b..1822f6d4abd 100644
--- a/doc/src/sgml/xaggr.sgml
+++ b/doc/src/sgml/xaggr.sgml
@@ -154,7 +154,7 @@ SELECT attrelid::regclass, array_accum(attname)
attrelid | array_accum
---------------+---------------------------------------
- pg_tablespace | {spcname,spcowner,spclocation,spcacl}
+ pg_tablespace | {spcname,spcowner,spcacl,spcoptions}
(1 row)
SELECT attrelid::regclass, array_accum(atttypid::regtype)
@@ -164,7 +164,7 @@ SELECT attrelid::regclass, array_accum(atttypid::regtype)
attrelid | array_accum
---------------+---------------------------
- pg_tablespace | {name,oid,text,aclitem[]}
+ pg_tablespace | {name,oid,aclitem[],text[]}
(1 row)
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index d223f8c9649..93592fabef1 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -314,8 +314,6 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
values[Anum_pg_tablespace_spcowner - 1] =
ObjectIdGetDatum(ownerId);
- values[Anum_pg_tablespace_spclocation - 1] =
- CStringGetTextDatum(location);
nulls[Anum_pg_tablespace_spcacl - 1] = true;
nulls[Anum_pg_tablespace_spcoptions - 1] = true;
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 63ec6fd9d4e..4453e818c00 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include "catalog/catalog.h"
#include "catalog/pg_tablespace.h"
@@ -261,6 +262,44 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
}
+/*
+ * pg_tablespace_location - get location for a tablespace
+ */
+Datum
+pg_tablespace_location(PG_FUNCTION_ARGS)
+{
+ Oid tablespaceOid = PG_GETARG_OID(0);
+ char sourcepath[MAXPGPATH];
+ char targetpath[MAXPGPATH];
+ int rllen;
+
+ /*
+ * Return empty string for our two default tablespace
+ */
+ if (tablespaceOid == DEFAULTTABLESPACE_OID ||
+ tablespaceOid == GLOBALTABLESPACE_OID)
+ PG_RETURN_TEXT_P(cstring_to_text(""));
+
+#if defined(HAVE_READLINK) || defined(WIN32)
+ /*
+ * Find the location of the tablespace by reading the symbolic link that is
+ * in pg_tblspc/.
+ */
+ snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
+ rllen =readlink(sourcepath, targetpath, sizeof(targetpath));
+ if (rllen < 0 || rllen >= sizeof(targetpath))
+ ereport(ERROR,
+ (errmsg("could not read symbolic link \"%s\": %m", sourcepath)));
+ targetpath[rllen] = '\0';
+
+ PG_RETURN_TEXT_P(cstring_to_text(targetpath));
+#else
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("tablespaces are not supported on this platform")));
+#endif
+}
+
/*
* pg_sleep - delay for N seconds
*/
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 04d655a504b..f37b7514e47 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -997,7 +997,16 @@ dumpTablespaces(PGconn *conn)
* Get all tablespaces except built-in ones (which we assume are named
* pg_xxx)
*/
- if (server_version >= 90000)
+ if (server_version >= 90200)
+ res = executeQuery(conn, "SELECT oid, spcname, "
+ "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
+ "pg_catalog.pg_tablespace_location(oid), spcacl, "
+ "array_to_string(spcoptions, ', '),"
+ "pg_catalog.shobj_description(oid, 'pg_tablespace') "
+ "FROM pg_catalog.pg_tablespace "
+ "WHERE spcname !~ '^pg_' "
+ "ORDER BY 1");
+ else if (server_version >= 90000)
res = executeQuery(conn, "SELECT oid, spcname, "
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
"spclocation, spcacl, "
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 2ff6d7dc997..dcafdd2c1ae 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -139,13 +139,22 @@ describeTablespaces(const char *pattern, bool verbose)
initPQExpBuffer(&buf);
- printfPQExpBuffer(&buf,
- "SELECT spcname AS \"%s\",\n"
- " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
- " spclocation AS \"%s\"",
- gettext_noop("Name"),
- gettext_noop("Owner"),
- gettext_noop("Location"));
+ if (pset.sversion >= 90200)
+ printfPQExpBuffer(&buf,
+ "SELECT spcname AS \"%s\",\n"
+ " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
+ " pg_catalog.pg_tablespace_location(oid) AS \"%s\"",
+ gettext_noop("Name"),
+ gettext_noop("Owner"),
+ gettext_noop("Location"));
+ else
+ printfPQExpBuffer(&buf,
+ "SELECT spcname AS \"%s\",\n"
+ " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
+ " spclocation AS \"%s\"",
+ gettext_noop("Name"),
+ gettext_noop("Owner"),
+ gettext_noop("Location"));
if (verbose)
{
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 95c424b81fa..14e177dc482 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201112061
+#define CATALOG_VERSION_NO 201112071
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 7451a12908a..924cb1f601c 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2686,6 +2686,9 @@ DESCR("statistics: reset collected statistics for a single table or index in the
DATA(insert OID = 3777 ( pg_stat_reset_single_function_counters PGNSP PGUID 12 1 0 0 0 f f f f f v 1 0 2278 "26" _null_ _null_ _null_ _null_ pg_stat_reset_single_function_counters _null_ _null_ _null_ ));
DESCR("statistics: reset collected statistics for a single function in the current database");
+DATA(insert OID = 3778 ( pg_tablespace_location PGNSP PGUID 12 1 0 0 0 f f f t f s 1 0 25 "26" _null_ _null_ _null_ _null_ pg_tablespace_location _null_ _null_ _null_ ));
+DESCR("tablespace location");
+
DATA(insert OID = 1946 ( encode PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 25 "17 25" _null_ _null_ _null_ _null_ binary_encode _null_ _null_ _null_ ));
DESCR("convert bytea value into some ascii-only text string");
DATA(insert OID = 1947 ( decode PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 17 "25 25" _null_ _null_ _null_ _null_ binary_decode _null_ _null_ _null_ ));
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index a1f5688c464..b35e32fabf0 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -32,7 +32,6 @@ CATALOG(pg_tablespace,1213) BKI_SHARED_RELATION
{
NameData spcname; /* tablespace name */
Oid spcowner; /* owner of tablespace */
- text spclocation; /* physical location (VAR LENGTH) */
aclitem spcacl[1]; /* access permissions (VAR LENGTH) */
text spcoptions[1]; /* per-tablespace options */
} FormData_pg_tablespace;
@@ -49,15 +48,14 @@ typedef FormData_pg_tablespace *Form_pg_tablespace;
* ----------------
*/
-#define Natts_pg_tablespace 5
+#define Natts_pg_tablespace 4
#define Anum_pg_tablespace_spcname 1
#define Anum_pg_tablespace_spcowner 2
-#define Anum_pg_tablespace_spclocation 3
-#define Anum_pg_tablespace_spcacl 4
-#define Anum_pg_tablespace_spcoptions 5
+#define Anum_pg_tablespace_spcacl 3
+#define Anum_pg_tablespace_spcoptions 4
-DATA(insert OID = 1663 ( pg_default PGUID "" _null_ _null_ ));
-DATA(insert OID = 1664 ( pg_global PGUID "" _null_ _null_ ));
+DATA(insert OID = 1663 ( pg_default PGUID _null_ _null_ ));
+DATA(insert OID = 1664 ( pg_global PGUID _null_ _null_ ));
#define DEFAULTTABLESPACE_OID 1663
#define GLOBALTABLESPACE_OID 1664
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 17550e0b3fd..994dc5368b1 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -469,6 +469,7 @@ extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
+extern Datum pg_tablespace_location(PG_FUNCTION_ARGS);
extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);
extern Datum pg_sleep(PG_FUNCTION_ARGS);
extern Datum pg_get_keywords(PG_FUNCTION_ARGS);