From 228d17d6808d350507a2ef137c7bdb496dc765d3 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 24 Jun 2015 10:32:01 +0900 Subject: [PATCH 1/8] Extend pg_tablespace_location with if_not_exists option This is useful for code paths that prefer receive an empty response instead of an ERROR if tablespace specified does not exist. --- doc/src/sgml/func.sgml | 8 +++++-- src/backend/utils/adt/misc.c | 49 ++++++++++++++++++++++++++++++++++++------- src/include/catalog/pg_proc.h | 2 ++ src/include/utils/builtins.h | 1 + 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 650051b..7929e7e 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -15844,9 +15844,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); get the set of database OIDs that have objects in the tablespace - pg_tablespace_location(tablespace_oid) + pg_tablespace_location(tablespace_oid [, if_not_exists boolean]) text - get the path in the file system that this tablespace is located in + + Get the path in the file system that this tablespace is located in. + If if_not_exists is true, NULL + is returned if tablespace does not exist instead of an error. + pg_typeof(any) diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index c0495d9..dc19c2c 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -336,17 +336,24 @@ pg_tablespace_databases(PG_FUNCTION_ARGS) SRF_RETURN_DONE(funcctx); } - /* - * pg_tablespace_location - get location for a tablespace + * Wrapper function for pg_tablespace_location and + * pg_tablespace_location_extended. */ -Datum -pg_tablespace_location(PG_FUNCTION_ARGS) +static Datum +tablespace_location_wrapper(FunctionCallInfo fcinfo) { Oid tablespaceOid = PG_GETARG_OID(0); char sourcepath[MAXPGPATH]; char targetpath[MAXPGPATH]; int rllen; + bool if_not_exists = false; + + /* + * Check for IF NOT EXISTS option. + */ + if (PG_NARGS() == 2 && !PG_ARGISNULL(1)) + if_not_exists = PG_GETARG_BOOL(1); /* * It's useful to apply this function to pg_class.reltablespace, wherein @@ -373,15 +380,22 @@ pg_tablespace_location(PG_FUNCTION_ARGS) rllen = readlink(sourcepath, targetpath, sizeof(targetpath)); if (rllen < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read symbolic link \"%s\": %m", - sourcepath))); + { + if (if_not_exists && errno == ENOENT) + PG_RETURN_NULL(); + else + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read symbolic link \"%s\": %m", + sourcepath))); + } if (rllen >= sizeof(targetpath)) + { ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("symbolic link \"%s\" target is too long", sourcepath))); + } targetpath[rllen] = '\0'; PG_RETURN_TEXT_P(cstring_to_text(targetpath)); @@ -394,6 +408,25 @@ pg_tablespace_location(PG_FUNCTION_ARGS) } /* + * pg_tablespace_location - get location for a tablespace + */ +Datum +pg_tablespace_location(PG_FUNCTION_ARGS) +{ + return tablespace_location_wrapper(fcinfo); +} + +/* + * pg_tablespace_location - get location for a tablespace, with option to + * bypass errors in case of a non-existing tablespace. + */ +Datum +pg_tablespace_location_extended(PG_FUNCTION_ARGS) +{ + return tablespace_location_wrapper(fcinfo); +} + +/* * pg_sleep - delay for N seconds */ Datum diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 6b3d194..1f163f0 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2922,6 +2922,8 @@ DESCR("current trigger depth"); DATA(insert OID = 3778 ( pg_tablespace_location PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_tablespace_location _null_ _null_ _null_ )); DESCR("tablespace location"); +DATA(insert OID = 3579 ( pg_tablespace_location PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_tablespace_location_extended _null_ _null_ _null_ )); +DESCR("tablespace location"); DATA(insert OID = 1946 ( encode PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 25 "17 25" _null_ _null_ _null_ _null_ _null_ binary_encode _null_ _null_ _null_ )); DESCR("convert bytea value into some ascii-only text string"); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 51f25a2..ab78ec2 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -486,6 +486,7 @@ 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_tablespace_location_extended(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); -- 2.4.4