mirror of
https://github.com/postgres/postgres.git
synced 2025-11-15 03:41:20 +03:00
Split out innards of pg_tablespace_location()
This creates a src/backend/catalog/pg_tablespace.c supporting file containing a new function get_tablespace_location(), which lets the code underlying pg_tablespace_location() be reused for other purposes. Author: Manni Wood <manni.wood@enterprisedb.com> Author: Nishant Sharma <nishant.sharma@enterprisedb.com> Reviewed-by: Vaibhav Dalvi <vaibhav.dalvi@enterprisedb.com> Reviewed-by: Ian Lawrence Barwick <barwick@gmail.com> Reviewed-by: Jim Jones <jim.jones@uni-muenster.de> Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de> Discussion: https://postgr.es/m/CAKWEB6rmnmGKUA87Zmq-s=b3Scsnj02C0kObQjnbL2ajfPWGEw@mail.gmail.com
This commit is contained in:
@@ -44,6 +44,7 @@ OBJS = \
|
||||
pg_range.o \
|
||||
pg_shdepend.o \
|
||||
pg_subscription.o \
|
||||
pg_tablespace.o \
|
||||
pg_type.o \
|
||||
storage.o \
|
||||
toasting.o
|
||||
|
||||
@@ -31,6 +31,7 @@ backend_sources += files(
|
||||
'pg_range.c',
|
||||
'pg_shdepend.c',
|
||||
'pg_subscription.c',
|
||||
'pg_tablespace.c',
|
||||
'pg_type.c',
|
||||
'storage.c',
|
||||
'toasting.c',
|
||||
|
||||
90
src/backend/catalog/pg_tablespace.c
Normal file
90
src/backend/catalog/pg_tablespace.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_tablespace.c
|
||||
* routines to support manipulation of the pg_tablespace relation
|
||||
*
|
||||
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/catalog/pg_tablespace.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "catalog/pg_tablespace.h"
|
||||
#include "commands/tablespace.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
|
||||
/*
|
||||
* get_tablespace_location
|
||||
* Get a tablespace's location as a C-string, by its OID
|
||||
*/
|
||||
char *
|
||||
get_tablespace_location(Oid tablespaceOid)
|
||||
{
|
||||
char sourcepath[MAXPGPATH];
|
||||
char targetpath[MAXPGPATH];
|
||||
int rllen;
|
||||
struct stat st;
|
||||
|
||||
/*
|
||||
* It's useful to apply this to pg_class.reltablespace, wherein zero means
|
||||
* "the database's default tablespace". So, rather than throwing an error
|
||||
* for zero, we choose to assume that's what is meant.
|
||||
*/
|
||||
if (tablespaceOid == InvalidOid)
|
||||
tablespaceOid = MyDatabaseTableSpace;
|
||||
|
||||
/*
|
||||
* Return empty string for the cluster's default tablespaces
|
||||
*/
|
||||
if (tablespaceOid == DEFAULTTABLESPACE_OID ||
|
||||
tablespaceOid == GLOBALTABLESPACE_OID)
|
||||
return pstrdup("");
|
||||
|
||||
/*
|
||||
* Find the location of the tablespace by reading the symbolic link that
|
||||
* is in pg_tblspc/<oid>.
|
||||
*/
|
||||
snprintf(sourcepath, sizeof(sourcepath), "%s/%u", PG_TBLSPC_DIR, tablespaceOid);
|
||||
|
||||
/*
|
||||
* Before reading the link, check if the source path is a link or a
|
||||
* junction point. Note that a directory is possible for a tablespace
|
||||
* created with allow_in_place_tablespaces enabled. If a directory is
|
||||
* found, a relative path to the data directory is returned.
|
||||
*/
|
||||
if (lstat(sourcepath, &st) < 0)
|
||||
ereport(ERROR,
|
||||
errcode_for_file_access(),
|
||||
errmsg("could not stat file \"%s\": %m",
|
||||
sourcepath));
|
||||
|
||||
if (!S_ISLNK(st.st_mode))
|
||||
return pstrdup(sourcepath);
|
||||
|
||||
/*
|
||||
* In presence of a link or a junction point, return the path pointed to.
|
||||
*/
|
||||
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 (rllen >= sizeof(targetpath))
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("symbolic link \"%s\" target is too long",
|
||||
sourcepath));
|
||||
targetpath[rllen] = '\0';
|
||||
|
||||
return pstrdup(targetpath);
|
||||
}
|
||||
@@ -315,66 +315,12 @@ Datum
|
||||
pg_tablespace_location(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid tablespaceOid = PG_GETARG_OID(0);
|
||||
char sourcepath[MAXPGPATH];
|
||||
char targetpath[MAXPGPATH];
|
||||
int rllen;
|
||||
struct stat st;
|
||||
char *tablespaceLoc;
|
||||
|
||||
/*
|
||||
* It's useful to apply this function to pg_class.reltablespace, wherein
|
||||
* zero means "the database's default tablespace". So, rather than
|
||||
* throwing an error for zero, we choose to assume that's what is meant.
|
||||
*/
|
||||
if (tablespaceOid == InvalidOid)
|
||||
tablespaceOid = MyDatabaseTableSpace;
|
||||
/* Get LOCATION string from its OID */
|
||||
tablespaceLoc = get_tablespace_location(tablespaceOid);
|
||||
|
||||
/*
|
||||
* Return empty string for the cluster's default tablespaces
|
||||
*/
|
||||
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), "%s/%u", PG_TBLSPC_DIR, tablespaceOid);
|
||||
|
||||
/*
|
||||
* Before reading the link, check if the source path is a link or a
|
||||
* junction point. Note that a directory is possible for a tablespace
|
||||
* created with allow_in_place_tablespaces enabled. If a directory is
|
||||
* found, a relative path to the data directory is returned.
|
||||
*/
|
||||
if (lstat(sourcepath, &st) < 0)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not stat file \"%s\": %m",
|
||||
sourcepath)));
|
||||
}
|
||||
|
||||
if (!S_ISLNK(st.st_mode))
|
||||
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
|
||||
|
||||
/*
|
||||
* In presence of a link or a junction point, return the path pointing to.
|
||||
*/
|
||||
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 (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));
|
||||
PG_RETURN_TEXT_P(cstring_to_text(tablespaceLoc));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -54,4 +54,6 @@ DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, p
|
||||
|
||||
MAKE_SYSCACHE(TABLESPACEOID, pg_tablespace_oid_index, 4);
|
||||
|
||||
extern char *get_tablespace_location(Oid tablespaceOid);
|
||||
|
||||
#endif /* PG_TABLESPACE_H */
|
||||
|
||||
Reference in New Issue
Block a user