summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c232
-rw-r--r--src/backend/postmaster/pgarch.c6
-rw-r--r--src/backend/utils/adt/misc.c82
-rw-r--r--src/include/access/xlog_internal.h17
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_proc.h17
-rw-r--r--src/include/utils/builtins.h3
7 files changed, 313 insertions, 48 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b0fac745266..59666580035 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.153 2004/08/01 17:45:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.154 2004/08/03 20:32:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -5048,3 +5048,233 @@ issue_xlog_fsync(void)
break;
}
}
+
+
+/*
+ * pg_start_backup: set up for taking an on-line backup dump
+ *
+ * Essentially what this does is to create a backup label file in $PGDATA,
+ * where it will be archived as part of the backup dump. The label file
+ * contains the user-supplied label string (typically this would be used
+ * to tell where the backup dump will be stored) and the starting time and
+ * starting WAL offset for the dump.
+ */
+Datum
+pg_start_backup(PG_FUNCTION_ARGS)
+{
+ text *backupid = PG_GETARG_TEXT_P(0);
+ text *result;
+ char *backupidstr;
+ XLogRecPtr startpoint;
+ time_t stamp_time;
+ char strfbuf[128];
+ char labelfilename[MAXPGPATH];
+ char xlogfilename[MAXFNAMELEN];
+ uint32 _logId;
+ uint32 _logSeg;
+ struct stat stat_buf;
+ FILE *fp;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to run a backup"))));
+ backupidstr = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(backupid)));
+ /*
+ * The oldest point in WAL that would be needed to restore starting from
+ * the most recent checkpoint is precisely the RedoRecPtr.
+ */
+ startpoint = GetRedoRecPtr();
+ XLByteToSeg(startpoint, _logId, _logSeg);
+ XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
+ /*
+ * We deliberately use strftime/localtime not the src/timezone functions,
+ * so that backup labels will consistently be recorded in the same
+ * timezone regardless of TimeZone setting. This matches elog.c's
+ * practice.
+ */
+ stamp_time = time(NULL);
+ strftime(strfbuf, sizeof(strfbuf),
+ "%Y-%m-%d %H:%M:%S %Z",
+ localtime(&stamp_time));
+ /*
+ * Check for existing backup label --- implies a backup is already running
+ */
+ snprintf(labelfilename, MAXPGPATH, "%s/backup_label", DataDir);
+ if (stat(labelfilename, &stat_buf) != 0)
+ {
+ if (errno != ENOENT)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not stat \"%s\": %m",
+ labelfilename)));
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("a backup is already in progress"),
+ errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
+ labelfilename)));
+ /*
+ * Okay, write the file
+ */
+ fp = AllocateFile(labelfilename, "w");
+ if (!fp)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not create file \"%s\": %m",
+ labelfilename)));
+ fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
+ startpoint.xlogid, startpoint.xrecoff, xlogfilename);
+ fprintf(fp, "START TIME: %s\n", strfbuf);
+ fprintf(fp, "LABEL: %s\n", backupidstr);
+ if (fflush(fp) || ferror(fp) || FreeFile(fp))
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not write file \"%s\": %m",
+ labelfilename)));
+ /*
+ * We're done. As a convenience, return the starting WAL offset.
+ */
+ snprintf(xlogfilename, sizeof(xlogfilename), "%X/%X",
+ startpoint.xlogid, startpoint.xrecoff);
+ result = DatumGetTextP(DirectFunctionCall1(textin,
+ CStringGetDatum(xlogfilename)));
+ PG_RETURN_TEXT_P(result);
+}
+
+/*
+ * pg_stop_backup: finish taking an on-line backup dump
+ *
+ * We remove the backup label file created by pg_start_backup, and instead
+ * create a backup history file in pg_xlog (whence it will immediately be
+ * archived). The backup history file contains the same info found in
+ * the label file, plus the backup-end time and WAL offset.
+ */
+Datum
+pg_stop_backup(PG_FUNCTION_ARGS)
+{
+ text *result;
+ XLogCtlInsert *Insert = &XLogCtl->Insert;
+ XLogRecPtr startpoint;
+ XLogRecPtr stoppoint;
+ time_t stamp_time;
+ char strfbuf[128];
+ char labelfilename[MAXPGPATH];
+ char histfilename[MAXPGPATH];
+ char startxlogfilename[MAXFNAMELEN];
+ char stopxlogfilename[MAXFNAMELEN];
+ uint32 _logId;
+ uint32 _logSeg;
+ FILE *lfp;
+ FILE *fp;
+ char ch;
+ int ich;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to run a backup"))));
+ /*
+ * Get the current end-of-WAL position; it will be unsafe to use this
+ * dump to restore to a point in advance of this time.
+ */
+ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ INSERT_RECPTR(stoppoint, Insert, Insert->curridx);
+ LWLockRelease(WALInsertLock);
+
+ XLByteToSeg(stoppoint, _logId, _logSeg);
+ XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg);
+ /*
+ * We deliberately use strftime/localtime not the src/timezone functions,
+ * so that backup labels will consistently be recorded in the same
+ * timezone regardless of TimeZone setting. This matches elog.c's
+ * practice.
+ */
+ stamp_time = time(NULL);
+ strftime(strfbuf, sizeof(strfbuf),
+ "%Y-%m-%d %H:%M:%S %Z",
+ localtime(&stamp_time));
+ /*
+ * Open the existing label file
+ */
+ snprintf(labelfilename, MAXPGPATH, "%s/backup_label", DataDir);
+ lfp = AllocateFile(labelfilename, "r");
+ if (!lfp)
+ {
+ if (errno != ENOENT)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m",
+ labelfilename)));
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("a backup is not in progress")));
+ }
+ /*
+ * Read and parse the START WAL LOCATION line (this code is pretty
+ * crude, but we are not expecting any variability in the file format).
+ */
+ if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %24s)%c",
+ &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename,
+ &ch) != 4 || ch != '\n')
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("invalid data in file \"%s\"", labelfilename)));
+ /*
+ * Write the backup history file
+ */
+ XLByteToSeg(startpoint, _logId, _logSeg);
+ BackupHistoryFilePath(histfilename, ThisTimeLineID, _logId, _logSeg,
+ startpoint.xrecoff % XLogSegSize);
+ fp = AllocateFile(histfilename, "w");
+ if (!fp)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not create file \"%s\": %m",
+ histfilename)));
+ fprintf(fp, "START WAL LOCATION: %X/%X (file %s)\n",
+ startpoint.xlogid, startpoint.xrecoff, startxlogfilename);
+ fprintf(fp, "STOP WAL LOCATION: %X/%X (file %s)\n",
+ stoppoint.xlogid, stoppoint.xrecoff, stopxlogfilename);
+ /* transfer start time and label lines from label to history file */
+ while ((ich = fgetc(lfp)) != EOF)
+ fputc(ich, fp);
+ fprintf(fp, "STOP TIME: %s\n", strfbuf);
+ if (fflush(fp) || ferror(fp) || FreeFile(fp))
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not write file \"%s\": %m",
+ histfilename)));
+ /*
+ * Close and remove the backup label file
+ */
+ if (ferror(lfp) || FreeFile(lfp))
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m",
+ labelfilename)));
+ if (unlink(labelfilename) != 0)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not remove file \"%s\": %m",
+ labelfilename)));
+ /*
+ * Notify archiver that history file may be archived immediately
+ */
+ if (XLogArchivingActive())
+ {
+ BackupHistoryFileName(histfilename, ThisTimeLineID, _logId, _logSeg,
+ startpoint.xrecoff % XLogSegSize);
+ XLogArchiveNotify(histfilename);
+ }
+ /*
+ * We're done. As a convenience, return the ending WAL offset.
+ */
+ snprintf(stopxlogfilename, sizeof(stopxlogfilename), "%X/%X",
+ stoppoint.xlogid, stoppoint.xrecoff);
+ result = DatumGetTextP(DirectFunctionCall1(textin,
+ CStringGetDatum(stopxlogfilename)));
+ PG_RETURN_TEXT_P(result);
+}
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index a4038963331..960ece75831 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -19,7 +19,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.3 2004/08/01 17:45:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.4 2004/08/03 20:32:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -64,8 +64,8 @@
* ----------
*/
#define MIN_XFN_CHARS 16
-#define MAX_XFN_CHARS 24
-#define VALID_XFN_CHARS "0123456789ABCDEF.history"
+#define MAX_XFN_CHARS 40
+#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup"
#define NUM_ARCHIVE_RETRIES 3
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 0cc315c6205..8bf989a8658 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.35 2004/07/02 18:59:22 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.36 2004/08/03 20:32:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,8 @@
#include "catalog/pg_type.h"
#include "catalog/pg_tablespace.h"
+#define atooid(x) ((Oid) strtoul((x), NULL, 10))
+
/*
* Check if data is Null
@@ -67,8 +69,7 @@ current_database(PG_FUNCTION_ARGS)
/*
- * Functions to terminate a backend or cancel a query running on
- * a different backend.
+ * Functions to send signals to other backends.
*/
static int pg_signal_backend(int pid, int sig)
@@ -76,14 +77,16 @@ static int pg_signal_backend(int pid, int sig)
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("only superuser can signal other backends"))));
+ (errmsg("must be superuser to signal other server processes"))));
if (!IsBackendPid(pid))
{
- /* This is just a warning so a loop-through-resultset will not abort
- * if one backend terminated on it's own during the run */
+ /*
+ * This is just a warning so a loop-through-resultset will not abort
+ * if one backend terminated on it's own during the run
+ */
ereport(WARNING,
- (errmsg("pid %i is not a postgresql backend",pid)));
+ (errmsg("PID %d is not a PostgreSQL server process", pid)));
return 0;
}
@@ -91,24 +94,32 @@ static int pg_signal_backend(int pid, int sig)
{
/* Again, just a warning to allow loops */
ereport(WARNING,
- (errmsg("failed to send signal to backend %i: %m",pid)));
+ (errmsg("could not send signal to process %d: %m",pid)));
return 0;
}
return 1;
}
Datum
-pg_terminate_backend(PG_FUNCTION_ARGS)
+pg_cancel_backend(PG_FUNCTION_ARGS)
{
- PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGTERM));
+ PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT));
}
+#ifdef NOT_USED
+
+/* Disabled in 8.0 due to reliability concerns; FIXME someday */
+
Datum
-pg_cancel_backend(PG_FUNCTION_ARGS)
+pg_terminate_backend(PG_FUNCTION_ARGS)
{
- PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT));
+ PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGTERM));
}
+#endif
+
+
+/* Function to find out which databases make use of a tablespace */
typedef struct
{
@@ -140,9 +151,8 @@ Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
if (tablespaceOid == GLOBALTABLESPACE_OID)
{
fctx->dirdesc = NULL;
- ereport(NOTICE,
- (errcode(ERRCODE_WARNING),
- errmsg("global tablespace never has databases.")));
+ ereport(WARNING,
+ (errmsg("global tablespace never has databases")));
}
else
{
@@ -154,10 +164,17 @@ Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
fctx->dirdesc = AllocateDir(fctx->location);
- if (!fctx->dirdesc) /* not a tablespace */
- ereport(NOTICE,
- (errcode(ERRCODE_WARNING),
- errmsg("%d is no tablespace oid.", tablespaceOid)));
+ if (!fctx->dirdesc)
+ {
+ /* the only expected error is ENOENT */
+ if (errno != ENOENT)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open directory \"%s\": %m",
+ fctx->location)));
+ ereport(WARNING,
+ (errmsg("%u is not a tablespace oid", tablespaceOid)));
+ }
}
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
@@ -174,27 +191,30 @@ Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
char *subdir;
DIR *dirdesc;
- Oid datOid = atol(de->d_name);
+ Oid datOid = atooid(de->d_name);
+ /* this test skips . and .., but is awfully weak */
if (!datOid)
continue;
+ /* if database subdir is empty, don't report tablespace as used */
+
/* size = path length + dir sep char + file name + terminator */
subdir = palloc(strlen(fctx->location) + 1 + strlen(de->d_name) + 1);
sprintf(subdir, "%s/%s", fctx->location, de->d_name);
dirdesc = AllocateDir(subdir);
- if (dirdesc)
- {
- while ((de = readdir(dirdesc)) != 0)
- {
- if (strcmp(de->d_name, ".") && strcmp(de->d_name, ".."))
- break;
- }
- pfree(subdir);
- FreeDir(dirdesc);
+ pfree(subdir);
+ if (!dirdesc)
+ continue; /* XXX more sloppiness */
- if (!de) /* database subdir is empty; don't report tablespace as used */
- continue;
+ while ((de = readdir(dirdesc)) != 0)
+ {
+ if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
+ break;
}
+ FreeDir(dirdesc);
+
+ if (!de)
+ continue; /* indeed, nothing in it */
SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(datOid));
}
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 09877bf64be..89c37b7d66a 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -11,12 +11,13 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.1 2004/07/21 22:31:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.2 2004/08/03 20:32:34 tgl Exp $
*/
#ifndef XLOG_INTERNAL_H
#define XLOG_INTERNAL_H
#include "access/xlog.h"
+#include "fmgr.h"
#include "storage/block.h"
#include "storage/relfilenode.h"
@@ -177,7 +178,7 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
* These macros encapsulate knowledge about the exact layout of XLog file
* names, timeline history file names, and archive-status file names.
*/
-#define MAXFNAMELEN 32
+#define MAXFNAMELEN 64
#define XLogFileName(fname, tli, log, seg) \
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg)
@@ -194,6 +195,12 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
#define StatusFilePath(path, xlog, suffix) \
snprintf(path, MAXPGPATH, "%s/archive_status/%s%s", XLogDir, xlog, suffix)
+#define BackupHistoryFileName(fname, tli, log, seg, offset) \
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, log, seg, offset)
+
+#define BackupHistoryFilePath(path, tli, log, seg, offset) \
+ snprintf(path, MAXPGPATH, "%s/%08X%08X%08X.%08X.backup", XLogDir, tli, log, seg, offset)
+
extern char XLogDir[MAXPGPATH];
/*
@@ -221,4 +228,10 @@ typedef struct RmgrData
extern const RmgrData RmgrTable[];
+/*
+ * These aren't in xlog.h because I'd rather not include fmgr.h there.
+ */
+extern Datum pg_start_backup(PG_FUNCTION_ARGS);
+extern Datum pg_stop_backup(PG_FUNCTION_ARGS);
+
#endif /* XLOG_INTERNAL_H */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index d7d180eaf51..0d5ac8f13c5 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.247 2004/07/21 20:43:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.248 2004/08/03 20:32:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200407211
+#define CATALOG_VERSION_NO 200408031
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 646fa73dd15..21bd60fb946 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.342 2004/07/12 20:23:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.343 2004/08/03 20:32:35 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2815,11 +2815,6 @@ DESCR("Statistics: Blocks fetched for database");
DATA(insert OID = 1945 ( pg_stat_get_db_blocks_hit PGNSP PGUID 12 f f t f s 1 20 "26" _null_ pg_stat_get_db_blocks_hit - _null_ ));
DESCR("Statistics: Blocks found in cache for database");
-DATA(insert OID = 2171 ( pg_terminate_backend PGNSP PGUID 12 f f t f s 1 23 "23" _null_ pg_terminate_backend - _null_ ));
-DESCR("Terminate a backend process");
-DATA(insert OID = 2172 ( pg_cancel_backend PGNSP PGUID 12 f f t f s 1 23 "23" _null_ pg_cancel_backend - _null_ ));
-DESCR("Cancel running query on a backend process");
-
DATA(insert OID = 1946 ( encode PGNSP PGUID 12 f f t f i 2 25 "17 25" _null_ binary_encode - _null_ ));
DESCR("Convert bytea value into some ascii-only text string");
DATA(insert OID = 1947 ( decode PGNSP PGUID 12 f f t f i 2 17 "25 25" _null_ binary_decode - _null_ ));
@@ -2993,10 +2988,18 @@ DATA(insert OID = 2082 ( pg_operator_is_visible PGNSP PGUID 12 f f t f s 1 16 "
DESCR("is operator visible in search path?");
DATA(insert OID = 2083 ( pg_opclass_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" _null_ pg_opclass_is_visible - _null_ ));
DESCR("is opclass visible in search path?");
-DATA(insert OID = 2093 ( pg_conversion_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" _null_ pg_conversion_is_visible - _null_ ));
+DATA(insert OID = 2093 ( pg_conversion_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" _null_ pg_conversion_is_visible - _null_ ));
DESCR("is conversion visible in search path?");
+DATA(insert OID = 2171 ( pg_cancel_backend PGNSP PGUID 12 f f t f v 1 23 "23" _null_ pg_cancel_backend - _null_ ));
+DESCR("Cancel a server process' current query");
+DATA(insert OID = 2172 ( pg_start_backup PGNSP PGUID 12 f f t f v 1 25 "25" _null_ pg_start_backup - _null_ ));
+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_ pg_stop_backup - _null_ ));
+DESCR("Finish taking an online backup");
+
+
/* 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_ aggregate_dummy - _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 3e9f58e7f26..09d91d985c9 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.246 2004/07/12 20:23:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.247 2004/08/03 20:32:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -360,7 +360,6 @@ extern Datum float84ge(PG_FUNCTION_ARGS);
extern Datum nullvalue(PG_FUNCTION_ARGS);
extern Datum nonnullvalue(PG_FUNCTION_ARGS);
extern Datum current_database(PG_FUNCTION_ARGS);
-extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);