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_range.o \
|
||||||
pg_shdepend.o \
|
pg_shdepend.o \
|
||||||
pg_subscription.o \
|
pg_subscription.o \
|
||||||
|
pg_tablespace.o \
|
||||||
pg_type.o \
|
pg_type.o \
|
||||||
storage.o \
|
storage.o \
|
||||||
toasting.o
|
toasting.o
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ backend_sources += files(
|
|||||||
'pg_range.c',
|
'pg_range.c',
|
||||||
'pg_shdepend.c',
|
'pg_shdepend.c',
|
||||||
'pg_subscription.c',
|
'pg_subscription.c',
|
||||||
|
'pg_tablespace.c',
|
||||||
'pg_type.c',
|
'pg_type.c',
|
||||||
'storage.c',
|
'storage.c',
|
||||||
'toasting.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)
|
pg_tablespace_location(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid tablespaceOid = PG_GETARG_OID(0);
|
Oid tablespaceOid = PG_GETARG_OID(0);
|
||||||
char sourcepath[MAXPGPATH];
|
char *tablespaceLoc;
|
||||||
char targetpath[MAXPGPATH];
|
|
||||||
int rllen;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
/*
|
/* Get LOCATION string from its OID */
|
||||||
* It's useful to apply this function to pg_class.reltablespace, wherein
|
tablespaceLoc = get_tablespace_location(tablespaceOid);
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
PG_RETURN_TEXT_P(cstring_to_text(tablespaceLoc));
|
||||||
* 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -54,4 +54,6 @@ DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, TablespaceNameIndexId, p
|
|||||||
|
|
||||||
MAKE_SYSCACHE(TABLESPACEOID, pg_tablespace_oid_index, 4);
|
MAKE_SYSCACHE(TABLESPACEOID, pg_tablespace_oid_index, 4);
|
||||||
|
|
||||||
|
extern char *get_tablespace_location(Oid tablespaceOid);
|
||||||
|
|
||||||
#endif /* PG_TABLESPACE_H */
|
#endif /* PG_TABLESPACE_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user