On Sun, Dec 4, 2011 at 18:07, Tom Lane <t...@sss.pgh.pa.us> wrote: > Andrew Dunstan <and...@dunslane.net> writes: >> On 12/04/2011 11:41 AM, Tom Lane wrote: >>> Hm, how portable is symlink-reading? If we can actually do that >>> without big headaches, then +1. > >> I wondered that, specifically about Windows junction points, but we seem >> to have support for it already in dirmod.c::pgreadlink(). Surely there's >> no other currently supported platform where it would even be a question? > > readlink is required by Single Unix Spec v2 (1997), which is what we've > been treating as our baseline expectation for Unix-oid platforms for > awhile now. Given that we dealt with the Windows side already, I don't > see a problem with making this assumption. At worst we'd end up needing > a couple more emulations in src/port, since surely there's *some* way to > do it on any platform with symlinks.
AFAICT, it should be as simple as the attached. Doesn't include the required fixes for pg_upgrade, I'll get on those next. -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
*** a/doc/src/sgml/catalogs.sgml --- b/doc/src/sgml/catalogs.sgml *************** *** 5392,5404 **** </row> <row> - <entry><structfield>spclocation</structfield></entry> - <entry><type>text</type></entry> - <entry></entry> - <entry>Location (directory path) of the tablespace</entry> - </row> - - <row> <entry><structfield>spcacl</structfield></entry> <entry><type>aclitem[]</type></entry> <entry></entry> --- 5392,5397 ---- *** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** *** 13612,13617 **** SELECT pg_type_is_visible('myschema.widget'::regtype); --- 13612,13621 ---- </indexterm> <indexterm> + <primary>pg_tablespace_location</primary> + </indexterm> + + <indexterm> <primary>pg_typeof</primary> </indexterm> *************** *** 13759,13764 **** SELECT pg_type_is_visible('myschema.widget'::regtype); --- 13763,13773 ---- <entry>get the set of database OIDs that have objects in the tablespace</entry> </row> <row> + <entry><literal><function>pg_tablespace_location(<parameter>tablespace_oid</parameter>)</function></literal></entry> + <entry><type>text</type></entry> + <entry>get the path in the filesystem that this tablespace is located in</entry> + </row> + <row> <entry><literal><function>pg_typeof(<parameter>any</parameter>)</function></literal></entry> <entry><type>regtype</type></entry> <entry>get the data type of any value</entry> *** a/doc/src/sgml/xaggr.sgml --- b/doc/src/sgml/xaggr.sgml *************** *** 154,160 **** SELECT attrelid::regclass, array_accum(attname) attrelid | array_accum ---------------+--------------------------------------- ! pg_tablespace | {spcname,spcowner,spclocation,spcacl} (1 row) SELECT attrelid::regclass, array_accum(atttypid::regtype) --- 154,160 ---- attrelid | array_accum ---------------+--------------------------------------- ! pg_tablespace | {spcname,spcowner,spcacl,spcoptions} (1 row) SELECT attrelid::regclass, array_accum(atttypid::regtype) *************** *** 164,170 **** SELECT attrelid::regclass, array_accum(atttypid::regtype) attrelid | array_accum ---------------+--------------------------- ! pg_tablespace | {name,oid,text,aclitem[]} (1 row) </programlisting> </para> --- 164,170 ---- attrelid | array_accum ---------------+--------------------------- ! pg_tablespace | {name,oid,aclitem[],text[]} (1 row) </programlisting> </para> *** a/src/backend/commands/tablespace.c --- b/src/backend/commands/tablespace.c *************** *** 314,321 **** 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; --- 314,319 ---- *** a/src/backend/utils/adt/misc.c --- b/src/backend/utils/adt/misc.c *************** *** 18,23 **** --- 18,24 ---- #include <signal.h> #include <dirent.h> #include <math.h> + #include <unistd.h> #include "catalog/catalog.h" #include "catalog/pg_tablespace.h" *************** *** 262,267 **** pg_tablespace_databases(PG_FUNCTION_ARGS) --- 263,298 ---- /* + * 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]; + + /* + * Return empty string for our two default tablespace + */ + if (tablespaceOid == DEFAULTTABLESPACE_OID || + tablespaceOid == GLOBALTABLESPACE_OID) + PG_RETURN_TEXT_P(cstring_to_text("")); + + /* + * Find the location of the tablespace by reading the symbolic link that is + * in pg_tblspc/<oid>. + */ + snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%d", tablespaceOid); + MemSet(targetpath, 0, sizeof(targetpath)); + if (readlink(sourcepath, targetpath, sizeof(targetpath)) == -1) + ereport(ERROR, + (errmsg("could not read symbolic link \"%s\": %m", sourcepath))); + + PG_RETURN_TEXT_P(cstring_to_text(targetpath)); + } + + /* * pg_sleep - delay for N seconds */ Datum *** a/src/bin/pg_dump/pg_dumpall.c --- b/src/bin/pg_dump/pg_dumpall.c *************** *** 997,1003 **** dumpTablespaces(PGconn *conn) * Get all tablespaces except built-in ones (which we assume are named * pg_xxx) */ ! if (server_version >= 90000) res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, " --- 997,1012 ---- * Get all tablespaces except built-in ones (which we assume are named * pg_xxx) */ ! 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, " *** a/src/bin/psql/describe.c --- b/src/bin/psql/describe.c *************** *** 139,151 **** 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 (verbose) { --- 139,160 ---- initPQExpBuffer(&buf); ! 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) { *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** *** 2670,2675 **** DESCR("statistics: reset collected statistics for a single table or index in the --- 2670,2678 ---- 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_ )); *** a/src/include/catalog/pg_tablespace.h --- b/src/include/catalog/pg_tablespace.h *************** *** 32,38 **** 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; --- 32,37 ---- *************** *** 49,63 **** typedef FormData_pg_tablespace *Form_pg_tablespace; * ---------------- */ ! #define Natts_pg_tablespace 5 #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 ! 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 --- 48,61 ---- * ---------------- */ ! #define Natts_pg_tablespace 4 #define Anum_pg_tablespace_spcname 1 #define Anum_pg_tablespace_spcowner 2 ! #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_ )); #define DEFAULTTABLESPACE_OID 1663 #define GLOBALTABLESPACE_OID 1664 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** *** 456,461 **** extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); --- 456,462 ---- 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);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers