if (info == XLOG_SMGR_CREATE)
{
xl_smgr_create *xlrec = (xl_smgr_create *) rec;
- char *path = relpathperm(xlrec->rlocator, xlrec->forkNum);
- appendStringInfoString(buf, path);
- pfree(path);
+ appendStringInfoString(buf,
+ relpathperm(xlrec->rlocator, xlrec->forkNum).str);
}
else if (info == XLOG_SMGR_TRUNCATE)
{
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
- char *path = relpathperm(xlrec->rlocator, MAIN_FORKNUM);
- appendStringInfo(buf, "%s to %u blocks flags %d", path,
+ appendStringInfo(buf, "%s to %u blocks flags %d",
+ relpathperm(xlrec->rlocator, MAIN_FORKNUM).str,
xlrec->blkno, xlrec->flags);
- pfree(path);
}
}
appendStringInfo(buf, "; %s:", label);
for (i = 0; i < nrels; i++)
{
- char *path = relpathperm(xlocators[i], MAIN_FORKNUM);
-
- appendStringInfo(buf, " %s", path);
- pfree(path);
+ appendStringInfo(buf, " %s",
+ relpathperm(xlocators[i], MAIN_FORKNUM).str);
}
}
}
report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno,
BlockNumber blkno, bool present)
{
- char *path = relpathperm(locator, forkno);
+ RelPathStr path = relpathperm(locator, forkno);
if (present)
elog(elevel, "page %u of relation %s is uninitialized",
- blkno, path);
+ blkno, path.str);
else
elog(elevel, "page %u of relation %s does not exist",
- blkno, path);
- pfree(path);
+ blkno, path.str);
}
/* Log a reference to an invalid page */
hentry->key.forkno == forkno &&
hentry->key.blkno >= minblkno)
{
- if (message_level_is_interesting(DEBUG2))
- {
- char *path = relpathperm(hentry->key.locator, forkno);
-
- elog(DEBUG2, "page %u of relation %s has been dropped",
- hentry->key.blkno, path);
- pfree(path);
- }
+ elog(DEBUG2, "page %u of relation %s has been dropped",
+ hentry->key.blkno,
+ relpathperm(hentry->key.locator, forkno).str);
if (hash_search(invalid_page_tab,
&hentry->key,
{
if (hentry->key.locator.dbOid == dbid)
{
- if (message_level_is_interesting(DEBUG2))
- {
- char *path = relpathperm(hentry->key.locator, hentry->key.forkno);
-
- elog(DEBUG2, "page %u of relation %s has been dropped",
- hentry->key.blkno, path);
- pfree(path);
- }
+ elog(DEBUG2, "page %u of relation %s has been dropped",
+ hentry->key.blkno,
+ relpathperm(hentry->key.locator, hentry->key.forkno).str);
if (hash_search(invalid_page_tab,
&hentry->key,
GetIncrementalFilePath(Oid dboid, Oid spcoid, RelFileNumber relfilenumber,
ForkNumber forknum, unsigned segno)
{
- char *path;
+ RelPathStr path;
char *lastslash;
char *ipath;
path = GetRelationPath(dboid, spcoid, relfilenumber, INVALID_PROC_NUMBER,
forknum);
- lastslash = strrchr(path, '/');
+ lastslash = strrchr(path.str, '/');
Assert(lastslash != NULL);
*lastslash = '\0';
if (segno > 0)
- ipath = psprintf("%s/INCREMENTAL.%s.%u", path, lastslash + 1, segno);
+ ipath = psprintf("%s/INCREMENTAL.%s.%u", path.str, lastslash + 1, segno);
else
- ipath = psprintf("%s/INCREMENTAL.%s", path, lastslash + 1);
-
- pfree(path);
+ ipath = psprintf("%s/INCREMENTAL.%s", path.str, lastslash + 1);
return ipath;
}
GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
{
RelFileLocatorBackend rlocator;
- char *rpath;
+ RelPathStr rpath;
bool collides;
ProcNumber procNumber;
/* Check for existing file of same name */
rpath = relpath(rlocator, MAIN_FORKNUM);
- if (access(rpath, F_OK) == 0)
+ if (access(rpath.str, F_OK) == 0)
{
/* definite collision */
collides = true;
*/
collides = false;
}
-
- pfree(rpath);
} while (collides);
return rlocator.locator.relNumber;
* (errcontext callbacks shouldn't be risking any such thing, but
* people have been known to forget that rule.)
*/
- char *relpath = relpathbackend(src->smgr_rlocator.locator,
+ RelPathStr relpath = relpathbackend(src->smgr_rlocator.locator,
src->smgr_rlocator.backend,
forkNum);
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s",
- blkno, relpath)));
+ blkno, relpath.str)));
}
/*
else if (reloid == InvalidOid)
elog(ERROR, "could not map filenumber \"%s\" to relation OID",
relpathperm(change->data.tp.rlocator,
- MAIN_FORKNUM));
+ MAIN_FORKNUM).str);
relation = RelationIdGetRelation(reloid);
elog(ERROR, "could not open relation with OID %u (for filenumber \"%s\")",
reloid,
relpathperm(change->data.tp.rlocator,
- MAIN_FORKNUM));
+ MAIN_FORKNUM).str);
if (!RelationIsLogicallyLogged(relation))
goto change_done;
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s; zeroing out page",
io_first_block + j,
- relpath(operation->smgr->smgr_rlocator, forknum))));
+ relpath(operation->smgr->smgr_rlocator, forknum).str)));
memset(bufBlock, 0, BLCKSZ);
}
else
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s",
io_first_block + j,
- relpath(operation->smgr->smgr_rlocator, forknum))));
+ relpath(operation->smgr->smgr_rlocator, forknum).str)));
}
/* Terminate I/O and set BM_VALID. */
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend relation %s beyond %u blocks",
- relpath(bmr.smgr->smgr_rlocator, fork),
+ relpath(bmr.smgr->smgr_rlocator, fork).str,
MaxBlockNumber)));
/*
if (valid && !PageIsNew((Page) buf_block))
ereport(ERROR,
(errmsg("unexpected data beyond EOF in block %u of relation %s",
- existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)),
+ existing_hdr->tag.blockNum,
+ relpath(bmr.smgr->smgr_rlocator, fork).str),
errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
/*
{
BufferDesc *buf;
int32 loccount;
- char *path;
char *result;
ProcNumber backend;
uint32 buf_state;
}
/* theoretically we should lock the bufhdr here */
- path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
- BufTagGetForkNum(&buf->tag));
buf_state = pg_atomic_read_u32(&buf->state);
result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
- buffer, path,
+ buffer,
+ relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
+ BufTagGetForkNum(&buf->tag)).str,
buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
BUF_STATE_GET_REFCOUNT(buf_state), loccount);
- pfree(path);
return result;
}
if (buf_state & BM_IO_ERROR)
{
/* Buffer is pinned, so we can read tag without spinlock */
- char *path;
-
- path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
- BufTagGetForkNum(&buf_hdr->tag));
ereport(WARNING,
(errcode(ERRCODE_IO_ERROR),
errmsg("could not write block %u of %s",
- buf_hdr->tag.blockNum, path),
+ buf_hdr->tag.blockNum,
+ relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
+ BufTagGetForkNum(&buf_hdr->tag)).str),
errdetail("Multiple failures --- write error might be permanent.")));
- pfree(path);
}
}
/* Buffer is pinned, so we can read the tag without locking the spinlock */
if (bufHdr != NULL)
- {
- char *path = relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
- BufTagGetForkNum(&bufHdr->tag));
-
errcontext("writing block %u of relation %s",
- bufHdr->tag.blockNum, path);
- pfree(path);
- }
+ bufHdr->tag.blockNum,
+ relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
+ BufTagGetForkNum(&bufHdr->tag)).str);
}
/*
BufferDesc *bufHdr = (BufferDesc *) arg;
if (bufHdr != NULL)
- {
- char *path = relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
- MyProcNumber,
- BufTagGetForkNum(&bufHdr->tag));
-
errcontext("writing block %u of relation %s",
- bufHdr->tag.blockNum, path);
- pfree(path);
- }
+ bufHdr->tag.blockNum,
+ relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
+ MyProcNumber,
+ BufTagGetForkNum(&bufHdr->tag)).str);
}
/*
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend relation %s beyond %u blocks",
- relpath(bmr.smgr->smgr_rlocator, fork),
+ relpath(bmr.smgr->smgr_rlocator, fork).str,
MaxBlockNumber)));
for (uint32 i = 0; i < extend_by; i++)
bufHdr->tag.blockNum,
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
MyProcNumber,
- BufTagGetForkNum(&bufHdr->tag)),
+ BufTagGetForkNum(&bufHdr->tag)).str,
LocalRefCount[i]);
/* Remove entry from hashtable */
bufHdr->tag.blockNum,
relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
MyProcNumber,
- BufTagGetForkNum(&bufHdr->tag)),
+ BufTagGetForkNum(&bufHdr->tag)).str,
LocalRefCount[i]);
/* Remove entry from hashtable */
hresult = (LocalBufferLookupEnt *)
mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
{
MdfdVec *mdfd;
- char *path;
+ RelPathStr path;
File fd;
if (isRedo && reln->md_num_open_segs[forknum] > 0)
path = relpath(reln->smgr_rlocator, forknum);
- fd = PathNameOpenFile(path, _mdfd_open_flags() | O_CREAT | O_EXCL);
+ fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL);
if (fd < 0)
{
int save_errno = errno;
if (isRedo)
- fd = PathNameOpenFile(path, _mdfd_open_flags());
+ fd = PathNameOpenFile(path.str, _mdfd_open_flags());
if (fd < 0)
{
/* be sure to report the error reported by create, not open */
errno = save_errno;
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not create file \"%s\": %m", path)));
+ errmsg("could not create file \"%s\": %m", path.str)));
}
}
- pfree(path);
-
_fdvec_resize(reln, forknum, 1);
mdfd = &reln->md_seg_fds[forknum][0];
mdfd->mdfd_vfd = fd;
static void
mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
{
- char *path;
+ RelPathStr path;
int ret;
int save_errno;
if (!RelFileLocatorBackendIsTemp(rlocator))
{
/* Prevent other backends' fds from holding on to the disk space */
- ret = do_truncate(path);
+ ret = do_truncate(path.str);
/* Forget any pending sync requests for the first segment */
save_errno = errno;
/* Next unlink the file, unless it was already found to be missing */
if (ret >= 0 || errno != ENOENT)
{
- ret = unlink(path);
+ ret = unlink(path.str);
if (ret < 0 && errno != ENOENT)
{
save_errno = errno;
ereport(WARNING,
(errcode_for_file_access(),
- errmsg("could not remove file \"%s\": %m", path)));
+ errmsg("could not remove file \"%s\": %m", path.str)));
errno = save_errno;
}
}
else
{
/* Prevent other backends' fds from holding on to the disk space */
- ret = do_truncate(path);
+ ret = do_truncate(path.str);
/* Register request to unlink first segment later */
save_errno = errno;
*/
if (ret >= 0 || errno != ENOENT)
{
- char *segpath = (char *) palloc(strlen(path) + 12);
+ char *segpath = (char *) palloc(strlen(path.str) + 12);
BlockNumber segno;
for (segno = 1;; segno++)
{
- sprintf(segpath, "%s.%u", path, segno);
+ sprintf(segpath, "%s.%u", path.str, segno);
if (!RelFileLocatorBackendIsTemp(rlocator))
{
}
pfree(segpath);
}
-
- pfree(path);
}
/*
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend file \"%s\" beyond %u blocks",
- relpath(reln->smgr_rlocator, forknum),
+ relpath(reln->smgr_rlocator, forknum).str,
InvalidBlockNumber)));
v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend file \"%s\" beyond %u blocks",
- relpath(reln->smgr_rlocator, forknum),
+ relpath(reln->smgr_rlocator, forknum).str,
InvalidBlockNumber)));
while (remblocks > 0)
mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
{
MdfdVec *mdfd;
- char *path;
+ RelPathStr path;
File fd;
/* No work if already open */
path = relpath(reln->smgr_rlocator, forknum);
- fd = PathNameOpenFile(path, _mdfd_open_flags());
+ fd = PathNameOpenFile(path.str, _mdfd_open_flags());
if (fd < 0)
{
if ((behavior & EXTENSION_RETURN_NULL) &&
FILE_POSSIBLY_DELETED(errno))
- {
- pfree(path);
return NULL;
- }
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not open file \"%s\": %m", path)));
+ errmsg("could not open file \"%s\": %m", path.str)));
}
- pfree(path);
-
_fdvec_resize(reln, forknum, 1);
mdfd = &reln->md_seg_fds[forknum][0];
mdfd->mdfd_vfd = fd;
return;
ereport(ERROR,
(errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
- relpath(reln->smgr_rlocator, forknum),
+ relpath(reln->smgr_rlocator, forknum).str,
nblocks, curnblk)));
}
if (nblocks == curnblk)
static char *
_mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
{
- char *path,
- *fullpath;
+ RelPathStr path;
+ char *fullpath;
path = relpath(reln->smgr_rlocator, forknum);
if (segno > 0)
- {
- fullpath = psprintf("%s.%u", path, segno);
- pfree(path);
- }
+ fullpath = psprintf("%s.%u", path.str, segno);
else
- fullpath = path;
+ fullpath = pstrdup(path.str);
return fullpath;
}
int
mdunlinkfiletag(const FileTag *ftag, char *path)
{
- char *p;
+ RelPathStr p;
/* Compute the path. */
p = relpathperm(ftag->rlocator, MAIN_FORKNUM);
- strlcpy(path, p, MAXPGPATH);
- pfree(p);
+ strlcpy(path, p.str, MAXPGPATH);
/* Try to unlink the file. */
return unlink(path);
calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum)
{
int64 totalsize = 0;
- char *relationpath;
+ RelPathStr relationpath;
char pathname[MAXPGPATH];
unsigned int segcount = 0;
if (segcount == 0)
snprintf(pathname, MAXPGPATH, "%s",
- relationpath);
+ relationpath.str);
else
snprintf(pathname, MAXPGPATH, "%s.%u",
- relationpath, segcount);
+ relationpath.str, segcount);
if (stat(pathname, &fst) < 0)
{
Form_pg_class relform;
RelFileLocator rlocator;
ProcNumber backend;
- char *path;
+ RelPathStr path;
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
if (!HeapTupleIsValid(tuple))
path = relpathbackend(rlocator, backend, MAIN_FORKNUM);
- PG_RETURN_TEXT_P(cstring_to_text(path));
+ PG_RETURN_TEXT_P(cstring_to_text(path.str));
}
static char *
datasegpath(RelFileLocator rlocator, ForkNumber forknum, BlockNumber segno)
{
- char *path;
+ RelPathStr path;
char *segpath;
path = relpathperm(rlocator, forknum);
if (segno > 0)
{
- segpath = psprintf("%s.%u", path, segno);
- pfree(path);
+ segpath = psprintf("%s.%u", path.str, segno);
return segpath;
}
else
- return path;
+ return pstrdup(path.str);
}
/*
/*
* GetRelationPath - construct path to a relation's file
*
- * Result is a palloc'd string.
+ * The result is returned in-place as a struct, to make it suitable for use in
+ * critical sections etc.
*
* Note: ideally, procNumber would be declared as type ProcNumber, but
* relpath.h would have to include a backend-only header to do that; doesn't
* seem worth the trouble considering ProcNumber is just int anyway.
*/
-char *
+RelPathStr
GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
int procNumber, ForkNumber forkNumber)
{
- char *path;
+ RelPathStr rp;
if (spcOid == GLOBALTABLESPACE_OID)
{
Assert(dbOid == 0);
Assert(procNumber == INVALID_PROC_NUMBER);
if (forkNumber != MAIN_FORKNUM)
- path = psprintf("global/%u_%s",
- relNumber, forkNames[forkNumber]);
+ sprintf(rp.str, "global/%u_%s",
+ relNumber, forkNames[forkNumber]);
else
- path = psprintf("global/%u", relNumber);
+ sprintf(rp.str, "global/%u",
+ relNumber);
}
else if (spcOid == DEFAULTTABLESPACE_OID)
{
if (procNumber == INVALID_PROC_NUMBER)
{
if (forkNumber != MAIN_FORKNUM)
- path = psprintf("base/%u/%u_%s",
- dbOid, relNumber,
- forkNames[forkNumber]);
+ {
+ sprintf(rp.str, "base/%u/%u_%s",
+ dbOid, relNumber,
+ forkNames[forkNumber]);
+ }
else
- path = psprintf("base/%u/%u",
- dbOid, relNumber);
+ sprintf(rp.str, "base/%u/%u",
+ dbOid, relNumber);
}
else
{
if (forkNumber != MAIN_FORKNUM)
- path = psprintf("base/%u/t%d_%u_%s",
- dbOid, procNumber, relNumber,
- forkNames[forkNumber]);
+ sprintf(rp.str, "base/%u/t%d_%u_%s",
+ dbOid, procNumber, relNumber,
+ forkNames[forkNumber]);
else
- path = psprintf("base/%u/t%d_%u",
- dbOid, procNumber, relNumber);
+ sprintf(rp.str, "base/%u/t%d_%u",
+ dbOid, procNumber, relNumber);
}
}
else
if (procNumber == INVALID_PROC_NUMBER)
{
if (forkNumber != MAIN_FORKNUM)
- path = psprintf("%s/%u/%s/%u/%u_%s",
- PG_TBLSPC_DIR, spcOid,
- TABLESPACE_VERSION_DIRECTORY,
- dbOid, relNumber,
- forkNames[forkNumber]);
+ sprintf(rp.str, "%s/%u/%s/%u/%u_%s",
+ PG_TBLSPC_DIR, spcOid,
+ TABLESPACE_VERSION_DIRECTORY,
+ dbOid, relNumber,
+ forkNames[forkNumber]);
else
- path = psprintf("%s/%u/%s/%u/%u",
- PG_TBLSPC_DIR, spcOid,
- TABLESPACE_VERSION_DIRECTORY,
- dbOid, relNumber);
+ sprintf(rp.str, "%s/%u/%s/%u/%u",
+ PG_TBLSPC_DIR, spcOid,
+ TABLESPACE_VERSION_DIRECTORY,
+ dbOid, relNumber);
}
else
{
if (forkNumber != MAIN_FORKNUM)
- path = psprintf("%s/%u/%s/%u/t%d_%u_%s",
- PG_TBLSPC_DIR, spcOid,
- TABLESPACE_VERSION_DIRECTORY,
- dbOid, procNumber, relNumber,
- forkNames[forkNumber]);
+ sprintf(rp.str, "%s/%u/%s/%u/t%d_%u_%s",
+ PG_TBLSPC_DIR, spcOid,
+ TABLESPACE_VERSION_DIRECTORY,
+ dbOid, procNumber, relNumber,
+ forkNames[forkNumber]);
else
- path = psprintf("%s/%u/%s/%u/t%d_%u",
- PG_TBLSPC_DIR, spcOid,
- TABLESPACE_VERSION_DIRECTORY,
- dbOid, procNumber, relNumber);
+ sprintf(rp.str, "%s/%u/%s/%u/t%d_%u",
+ PG_TBLSPC_DIR, spcOid,
+ TABLESPACE_VERSION_DIRECTORY,
+ dbOid, procNumber, relNumber);
}
}
- return path;
+
+ Assert(strnlen(rp.str, REL_PATH_STR_MAXLEN + 1) <= REL_PATH_STR_MAXLEN);
+
+ return rp;
}
extern ForkNumber forkname_to_number(const char *forkName);
extern int forkname_chars(const char *str, ForkNumber *fork);
+
+/*
+ * Unfortunately, there's no easy way to derive PROCNUMBER_CHARS from
+ * MAX_BACKENDS. MAX_BACKENDS is 2^18-1. Crosschecked in test_relpath().
+ */
+#define PROCNUMBER_CHARS 6
+
+/*
+ * The longest possible relation path lengths is from the following format:
+ * sprintf(rp.path, "%s/%u/%s/%u/t%d_%u",
+ * PG_TBLSPC_DIR, spcOid,
+ * TABLESPACE_VERSION_DIRECTORY,
+ * dbOid, procNumber, relNumber);
+ *
+ * Note this does *not* include the trailing null-byte, to make it easier to
+ * combine it with other lengths.
+ */
+#define REL_PATH_STR_MAXLEN \
+ ( \
+ sizeof(PG_TBLSPC_DIR) - 1 \
+ + sizeof((char)'/') \
+ + OIDCHARS /* spcOid */ \
+ + sizeof((char)'/') \
+ + sizeof(TABLESPACE_VERSION_DIRECTORY) - 1 \
+ + sizeof((char)'/') \
+ + OIDCHARS /* dbOid */ \
+ + sizeof((char)'/') \
+ + sizeof((char)'t') /* temporary table indicator */ \
+ + PROCNUMBER_CHARS /* procNumber */ \
+ + sizeof((char)'_') \
+ + OIDCHARS /* relNumber */ \
+ + sizeof((char)'_') \
+ + FORKNAMECHARS /* forkNames[forkNumber] */ \
+ )
+
+/*
+ * String of the exact length required to represent a relation path. We return
+ * this struct, instead of char[REL_PATH_STR_MAXLEN + 1], as the pointer would
+ * decay to a plain char * too easily, possibly preventing the compiler from
+ * detecting invalid references to the on-stack return value of
+ * GetRelationPath().
+ */
+typedef struct RelPathStr
+{
+ char str[REL_PATH_STR_MAXLEN + 1];
+} RelPathStr;
+
+
/*
* Stuff for computing filesystem pathnames for relations.
*/
extern char *GetDatabasePath(Oid dbOid, Oid spcOid);
-extern char *GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
- int procNumber, ForkNumber forkNumber);
+extern RelPathStr GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
+ int procNumber, ForkNumber forkNumber);
/*
* Wrapper macros for GetRelationPath. Beware of multiple
18
(1 row)
+-- relpath tests
+CREATE FUNCTION test_relpath()
+ RETURNS void
+ AS :'regresslib'
+ LANGUAGE C;
+SELECT test_relpath();
+ test_relpath
+--------------
+
+(1 row)
+
#include "optimizer/plancat.h"
#include "parser/parse_coerce.h"
#include "port/atomics.h"
+#include "postmaster/postmaster.h" /* for MAX_BACKENDS */
#include "storage/spin.h"
#include "utils/array.h"
#include "utils/builtins.h"
PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
}
+
+/*
+ * Sanity checks for functions in relpath.h
+ */
+PG_FUNCTION_INFO_V1(test_relpath);
+Datum
+test_relpath(PG_FUNCTION_ARGS)
+{
+ RelPathStr rpath;
+
+ /*
+ * Verify that PROCNUMBER_CHARS and MAX_BACKENDS stay in sync.
+ * Unfortunately I don't know how to express that in a way suitable for a
+ * static assert.
+ */
+ if ((int) ceil(log10(MAX_BACKENDS)) != PROCNUMBER_CHARS)
+ elog(WARNING, "mismatch between MAX_BACKENDS and PROCNUMBER_CHARS");
+
+ /* verify that the max-length relpath is generated ok */
+ rpath = GetRelationPath(OID_MAX, OID_MAX, OID_MAX, MAX_BACKENDS - 1,
+ INIT_FORKNUM);
+
+ if (strlen(rpath.str) != REL_PATH_STR_MAXLEN)
+ elog(WARNING, "maximum length relpath is if length %zu instead of %zu",
+ strlen(rpath.str), REL_PATH_STR_MAXLEN);
+
+ PG_RETURN_VOID();
+}
-- test stratnum support functions
SELECT gist_stratnum_common(7);
SELECT gist_stratnum_common(3);
+
+
+-- relpath tests
+CREATE FUNCTION test_relpath()
+ RETURNS void
+ AS :'regresslib'
+ LANGUAGE C;
+SELECT test_relpath();
RelMapping
RelOptInfo
RelOptKind
+RelPathStr
RelStatsInfo
RelToCheck
RelToCluster