Add files to do read I/O on the cluster directory:

pg_stat_file()
	pg_read_file()
	pg_ls_dir()
	pg_reload_conf()
	pg_rotate_logfile()

Dave Page
Andreas Pflug
This commit is contained in:
Bruce Momjian 2005-08-12 03:25:13 +00:00
parent d95886e734
commit b609695b7a
9 changed files with 485 additions and 15 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.276 2005/08/02 16:11:56 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.277 2005/08/12 03:23:40 momjian Exp $
PostgreSQL documentation
-->
@ -9061,6 +9061,9 @@ SELECT set_config('log_statement_stats', 'off', false);
<indexterm zone="functions-admin">
<primary>pg_cancel_backend</primary>
</indexterm>
<indexterm zone="functions-admin">
<primary>pg_reload_conf</primary>
</indexterm>
<indexterm zone="functions-admin">
<primary>signal</primary>
@ -9068,7 +9071,7 @@ SELECT set_config('log_statement_stats', 'off', false);
</indexterm>
<para>
The function shown in <xref
The functions shown in <xref
linkend="functions-admin-signal-table"> sends control signals to
other server processes. Use of this function is restricted
to superusers.
@ -9090,26 +9093,36 @@ SELECT set_config('log_statement_stats', 'off', false);
<entry><type>int</type></entry>
<entry>Cancel a backend's current query</entry>
</row>
<row>
<entry>
<literal><function>pg_reload_conf</function>()</literal>
</entry>
<entry><type>int</type></entry>
<entry>Causes server processes to reload their configuration files</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
This function returns 1 if successful, 0 if not successful.
These functions return 1 if successful, 0 if not successful.
The process ID (<literal>pid</literal>) of an active backend can be found
from the <structfield>procpid</structfield> column in the
<structname>pg_stat_activity</structname> view, or by listing the <command>postgres</command>
processes on the server with <application>ps</>.
</para>
<para>
<function>pg_reload_conf</> sends a SIGHUP signal to the
postmaster, causing the reload of the configuration files
in all backend processes.
</para>
<indexterm zone="functions-admin">
<primary>pg_start_backup</primary>
</indexterm>
<indexterm zone="functions-admin">
<primary>pg_stop_backup</primary>
</indexterm>
<indexterm zone="functions-admin">
<primary>backup</primary>
</indexterm>
@ -9309,6 +9322,113 @@ SELECT set_config('log_statement_stats', 'off', false);
appropriate.
</para>
<para>
The functions shown in <xref
linkend="functions-admin-genfile"> provide native file access to
files on the machine hosting the server. Only files relative to
the cluster directory are allowed, and the logfile directory,
because the logfile directory might be stored outside the
cluster directory. Use of these functions is restricted to
superusers.
</para>
<table id="functions-admin-genfile">
<title>Generic File Access Functions</title>
<tgroup cols="3">
<thead>
<row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal><function>pg_file_length</function>(<parameter>filename_text</parameter>)</literal>
<indexterm zone="functions-admin">
<primary>pg_file_length</primary>
</indexterm>
</entry>
<entry><type>int8</type></entry>
<entry>Returns the file length</entry>
</row>
<row>
<entry>
<literal><function>pg_ls_dir</function>(<parameter>dirname_text</parameter>,<parameter>fullpath_bool</parameter>)</literal>
<indexterm zone="functions-admin">
<primary>pg_ls_dir</primary>
</indexterm>
</entry>
<entry><type>setof text</type></entry>
<entry>List the contents of a directory</entry>
</row>
<row>
<entry>
<literal><function>pg_read_file</function>(<parameter>filename_text</parameter>,
<parameter>offset_int8</parameter>,<parameter>length_int8</parameter>)</literal>
</entry>
<entry><type>text</type></entry>
<entry>Returns the contents of a text file</entry>
</row>
<row>
<entry>
<literal><function>pg_stat_file</function>(<parameter>filename_text</parameter>)</literal>
</entry>
<entry><type>record</type></entry>
<entry>Returns information about the file</entry>
</row>
</tbody>
</tgroup>
</table>
<indexterm zone="functions-admin">
<primary>pg_read_file</primary>
</indexterm>
<para>
<function>pg_read_file()</> returns part of a textfile, starting
at the given offset, returning length bytes. If offset is negative,
it is treated relative to the end of the file.
</para>
<indexterm zone="functions-admin">
<primary>pg_stat_file</primary>
</indexterm>
<para>
<function>pg_stat_file()</> returns a record containing the
length, last accessed timestamp, last modified timestamp,
creation timestamp, and a flag indicating if it is a directory.
</para>
<para>
The function shown in <xref
linkend="functions-admin-logfile"> forces the server
logfile to be rotated if <varname>redirect_stderr</>
is used for logging. Use of this functions is restricted
to superusers.
</para>
<table id="functions-admin-logfile">
<title>Backend Logfile Functions</title>
<tgroup cols="3">
<thead>
<row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal><function>pg_rotate_logfile</function>()</literal>
<indexterm zone="functions-admin">
<primary>pg_rotate_logfile</primary>
</indexterm>
</entry>
<entry><type>int</type></entry>
<entry>Rotate logfile</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
</chapter>

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.462 2005/08/11 21:11:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.463 2005/08/12 03:23:51 momjian Exp $
*
* NOTES
*
@ -3394,6 +3394,9 @@ sigusr1_handler(SIGNAL_ARGS)
}
}
if (CheckPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE) && SysLoggerPID != 0)
kill(SysLoggerPID, SIGUSR1);
PG_SETMASK(&UnBlockSig);
errno = save_errno;

View File

@ -18,7 +18,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.18 2005/07/21 18:06:12 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.19 2005/08/12 03:23:51 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -101,6 +101,7 @@ static CRITICAL_SECTION sysfileSection;
* Flags set by interrupt handlers for later service in the main loop.
*/
static volatile sig_atomic_t got_SIGHUP = false;
static volatile sig_atomic_t rotation_requested = false;
/* Local subroutines */
@ -117,6 +118,7 @@ static void logfile_rotate(bool time_based_rotation);
static char *logfile_getname(pg_time_t timestamp);
static void set_next_rotation_time(void);
static void sigHupHandler(SIGNAL_ARGS);
static void sigUsr1Handler(SIGNAL_ARGS);
/*
@ -200,7 +202,7 @@ SysLoggerMain(int argc, char *argv[])
pqsignal(SIGQUIT, SIG_IGN);
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, SIG_IGN);
pqsignal(SIGUSR1, sigUsr1Handler); /* request log rotation */
pqsignal(SIGUSR2, SIG_IGN);
/*
@ -235,7 +237,6 @@ SysLoggerMain(int argc, char *argv[])
/* main worker loop */
for (;;)
{
bool rotation_requested = false;
bool time_based_rotation = false;
#ifndef WIN32
@ -726,6 +727,8 @@ logfile_rotate(bool time_based_rotation)
char *filename;
FILE *fh;
rotation_requested = false;
/*
* When doing a time-based rotation, invent the new logfile name based
* on the planned rotation time, not current time, to avoid "slippage"
@ -876,3 +879,10 @@ sigHupHandler(SIGNAL_ARGS)
{
got_SIGHUP = true;
}
/* SIGUSR1: set flag to rotate logfile */
static void
sigUsr1Handler(SIGNAL_ARGS)
{
rotation_requested = true;
}

View File

@ -1,7 +1,7 @@
#
# Makefile for utils/adt
#
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.58 2005/07/29 14:46:57 momjian Exp $
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.59 2005/08/12 03:24:08 momjian Exp $
#
subdir = src/backend/utils/adt
@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
network.o mac.o inet_net_ntop.o inet_net_pton.o \
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o
like.o: like.c like_match.c

View File

@ -0,0 +1,258 @@
/*-------------------------------------------------------------------------
*
* genfile.c
*
*
* Copyright (c) 2004, PostgreSQL Global Development Group
*
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/genfile.c,v 1.1 2005/08/12 03:24:08 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "utils/builtins.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
extern char *Log_directory;
typedef struct
{
char *location;
DIR *dirdesc;
} directory_fctx;
/*
* Return an absolute path. Argument may be absolute or
* relative to the DataDir.
*/
static char *check_and_make_absolute(text *arg)
{
int datadir_len = strlen(DataDir);
int filename_len = VARSIZE(arg) - VARHDRSZ;
char *filename = palloc(filename_len + 1);
memcpy(filename, VARDATA(arg), filename_len);
filename[filename_len] = '\0';
canonicalize_path(filename);
filename_len = strlen(filename); /* recompute */
/*
* Prevent reference to the parent directory.
* "..a.." is a valid file name though.
*/
if (strcmp(filename, "..") == 0 || /* beginning */
strncmp(filename, "../", 3) == 0 || /* beginning */
strcmp(filename, "/..") == 0 || /* beginning */
strncmp(filename, "../", 3) == 0 || /* beginning */
strstr(filename, "/../") != NULL || /* middle */
strncmp(filename + filename_len - 3, "/..", 3) == 0) /* end */
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("Reference to a parent directory (\"..\") not allowed"))));
if (is_absolute_path(filename))
{
/* The log directory might be outside our datadir, but allow it */
if (is_absolute_path(Log_directory) &&
strncmp(filename, Log_directory, strlen(Log_directory)) == 0 &&
(filename[strlen(Log_directory)] == '/' ||
filename[strlen(Log_directory)] == '\0'))
return filename;
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("Absolute paths not allowed"))));
return NULL;
}
else
{
char *absname = palloc(datadir_len + filename_len + 2);
sprintf(absname, "%s/%s", DataDir, filename);
pfree(filename);
return absname;
}
}
Datum pg_read_file(PG_FUNCTION_ARGS)
{
int64 bytes_to_read = PG_GETARG_INT64(2);
int64 seek_offset = PG_GETARG_INT64(1);
char *buf = 0;
size_t nbytes;
FILE *file;
char *filename;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to read files"))));
filename = check_and_make_absolute(PG_GETARG_TEXT_P(0));
if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file %s for reading: %m", filename)));
PG_RETURN_NULL();
}
if (fseeko(file, (off_t)seek_offset,
(seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0)
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not seek in file %s: %m", filename)));
PG_RETURN_NULL();
}
if (bytes_to_read < 0)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("length cannot be negative")));
}
buf = palloc(bytes_to_read + VARHDRSZ);
nbytes = fread(VARDATA(buf), 1, bytes_to_read, file);
if (nbytes < 0)
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not read file %s: %m", filename)));
PG_RETURN_NULL();
}
VARATT_SIZEP(buf) = nbytes + VARHDRSZ;
pfree(filename);
FreeFile(file);
PG_RETURN_TEXT_P(buf);
}
Datum pg_stat_file(PG_FUNCTION_ARGS)
{
AttInMetadata *attinmeta;
char *filename = check_and_make_absolute(PG_GETARG_TEXT_P(0));
struct stat fst;
char lenbuf[30], cbuf[30], abuf[30], mbuf[30], dirbuf[2];
char *values[5] = {lenbuf, cbuf, abuf, mbuf, dirbuf};
pg_time_t timestamp;
HeapTuple tuple;
TupleDesc tupdesc = CreateTemplateTupleDesc(5, false);
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to get file information"))));
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "length", INT8OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "atime", TIMESTAMPOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "mtime", TIMESTAMPOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "ctime", TIMESTAMPOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "isdir", BOOLOID, -1, 0);
attinmeta = TupleDescGetAttInMetadata(tupdesc);
if (stat(filename, &fst) < 0)
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file %s: %m", filename)));
PG_RETURN_NULL();
}
else
{
snprintf(lenbuf, 30, INT64_FORMAT, (int64)fst.st_size);
timestamp = fst.st_atime;
pg_strftime(abuf, 30, "%F %T", pg_localtime(&timestamp, global_timezone));
timestamp = fst.st_mtime;
pg_strftime(mbuf, 30, "%F %T", pg_localtime(&timestamp, global_timezone));
timestamp = fst.st_ctime;
pg_strftime(cbuf, 30, "%F %T", pg_localtime(&timestamp, global_timezone));
if (fst.st_mode & S_IFDIR)
strcpy(dirbuf, "t");
else
strcpy(dirbuf, "f");
tuple = BuildTupleFromCStrings(attinmeta, values);
pfree(filename);
PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
}
}
Datum pg_ls_dir(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
struct dirent *de;
directory_fctx *fctx;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to get directory listings"))));
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
fctx = palloc(sizeof(directory_fctx));
fctx->location = check_and_make_absolute(PG_GETARG_TEXT_P(0));
fctx->dirdesc = AllocateDir(fctx->location);
if (!fctx->dirdesc)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("%s is not browsable: %m", fctx->location)));
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
fctx = (directory_fctx*) funcctx->user_fctx;
if (!fctx->dirdesc) /* not a readable directory */
SRF_RETURN_DONE(funcctx);
while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
{
int len = strlen(de->d_name);
text *result = palloc(len + VARHDRSZ);
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
VARATT_SIZEP(result) = len + VARHDRSZ;
memcpy(VARDATA(result), de->d_name, len);
SRF_RETURN_NEXT(funcctx, PointerGetDatum(result));
}
FreeDir(fctx->dirdesc);
SRF_RETURN_DONE(funcctx);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.45 2005/07/04 04:51:50 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.46 2005/08/12 03:24:08 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,14 +21,23 @@
#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "storage/procarray.h"
#include "storage/pmsignal.h"
#include "storage/fd.h"
#include "utils/builtins.h"
#include "utils/elog.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "catalog/pg_tablespace.h"
#include "postmaster/syslogger.h"
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
typedef struct
{
char *location;
DIR *dirdesc;
} directory_fctx;
/*
* Check if data is Null
@ -107,6 +116,51 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0), SIGINT));
}
Datum
pg_reload_conf(PG_FUNCTION_ARGS)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to signal the postmaster"))));
if (kill(PostmasterPid, SIGHUP))
{
ereport(WARNING,
(errmsg("failed to send signal to postmaster: %m")));
PG_RETURN_INT32(0);
}
PG_RETURN_INT32(1);
}
/*
* Rotate log file
*/
Datum
pg_rotate_logfile(PG_FUNCTION_ARGS)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to rotate log files"))));
if (!Redirect_stderr)
{
ereport(NOTICE,
(errcode(ERRCODE_WARNING),
errmsg("no logfile configured; rotation not supported")));
PG_RETURN_INT32(0);
}
SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
PG_RETURN_INT32(0);
}
#ifdef NOT_USED
/* Disabled in 8.0 due to reliability concerns; FIXME someday */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.380 2005/08/02 16:11:57 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.381 2005/08/12 03:24:22 momjian Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -3049,6 +3049,23 @@ DESCR("Prepare for taking an online backup");
DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_stop_backup - _null_ ));
DESCR("Finish taking an online backup");
DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 f f t f v 0 23 "" _null_ _null_ _null_ pg_reload_conf - _null_ ));
DESCR("Reload configuration files");
DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 f f t f v 0 23 "" _null_ _null_ _null_ pg_rotate_logfile - _null_ ));
DESCR("Rotate log file");
DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 f f t f v 1 2249 "25" _null_ _null_ _null_ pg_stat_file - _null_ ));
DESCR("Return file information");
DATA(insert OID = 2624 ( pg_file_length PGNSP PGUID 14 f f t f v 1 20 "25" _null_ _null_ _null_ "SELECT len FROM pg_stat_file($1) AS s(len int8, c timestamp, a timestamp, m timestamp, i bool)" - _null_ ));
DESCR("Return file length");
DATA(insert OID = 2625 ( pg_read_file PGNSP PGUID 12 f f t f v 3 25 "25 20 20" _null_ _null_ _null_ pg_read_file - _null_ ));
DESCR("Read text from a file");
DATA(insert OID = 2626 ( pg_ls_dir PGNSP PGUID 12 f f t t v 1 25 "25" _null_ _null_ _null_ pg_ls_dir - _null_ ));
DESCR("List all file in a directory");
/* Aggregates (moved here from pg_aggregate for 7.3) */
DATA(insert OID = 2100 ( avg PGNSP PGUID 12 t f f f i 1 1700 "20" _null_ _null_ _null_ aggregate_dummy - _null_ ));

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/storage/pmsignal.h,v 1.12 2005/06/28 19:51:25 tgl Exp $
* $PostgreSQL: pgsql/src/include/storage/pmsignal.h,v 1.13 2005/08/12 03:24:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -25,6 +25,7 @@ typedef enum
PMSIGNAL_PASSWORD_CHANGE, /* pg_auth file has changed */
PMSIGNAL_WAKEN_CHILDREN, /* send a SIGUSR1 signal to all backends */
PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */
PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */
NUM_PMSIGNALS /* Must be last value of enum! */
} PMSignalReason;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.262 2005/07/29 14:47:04 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.263 2005/08/12 03:25:13 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -374,12 +374,19 @@ extern Datum pg_complete_relation_size_oid(PG_FUNCTION_ARGS);
extern Datum pg_complete_relation_size_name(PG_FUNCTION_ARGS);
extern Datum pg_size_pretty(PG_FUNCTION_ARGS);
/* genfile.c */
extern Datum pg_stat_file(PG_FUNCTION_ARGS);
extern Datum pg_read_file(PG_FUNCTION_ARGS);
extern Datum pg_ls_dir(PG_FUNCTION_ARGS);
/* misc.c */
extern Datum nullvalue(PG_FUNCTION_ARGS);
extern Datum nonnullvalue(PG_FUNCTION_ARGS);
extern Datum current_database(PG_FUNCTION_ARGS);
extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);
/* not_in.c */
extern Datum int4notin(PG_FUNCTION_ARGS);