*** ./doc/src/sgml/func.sgml.orig	2004-12-20 15:12:22.000000000 -0200
--- ./doc/src/sgml/func.sgml	2004-12-20 15:12:59.000000000 -0200
***************
*** 8003,8008 ****
--- 8003,8014 ----
        </row>
  
        <row>
+        <entry><function>uptime()</function></entry>
+        <entry><type>text</type></entry>
+        <entry>PostgreSQL uptime information</entry>
+       </row>
+ 
+       <row>
         <entry><function>user</function></entry>
         <entry><type>name</type></entry>
         <entry>equivalent to <function>current_user</function></entry>
***************
*** 8099,8104 ****
--- 8105,8119 ----
     </para>
  
     <indexterm zone="functions-info">
+     <primary>uptime</primary>
+    </indexterm>
+ 
+    <para>
+     <function>uptime()</function> returns the <productname>PostgreSQL</productname>
+     server's uptime.
+    </para>
+ 
+    <indexterm zone="functions-info">
      <primary>version</primary>
     </indexterm>
  
*** ./src/backend/postmaster/postmaster.c.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/backend/postmaster/postmaster.c	2004-12-20 15:38:08.000000000 -0200
***************
*** 328,333 ****
--- 328,334 ----
  	InheritableSocket pgStatPipe0;
  	InheritableSocket pgStatPipe1;
  	pid_t PostmasterPid;
+ 	time_t PostmasterStartupTime;
  #ifdef WIN32
  	HANDLE PostmasterHandle;
  	HANDLE initial_signal_pipe;
***************
*** 914,919 ****
--- 915,925 ----
  	 */
  	StartupPID = StartupDataBase();
  
+ 	/*
+ 	 * Get time so we can use it to calculate PostgreSQL server uptime
+ 	 */
+ 	PostmasterStartupTime = time(NULL);
+ 
  	status = ServerLoop();
  
  	/*
***************
*** 3658,3663 ****
--- 3664,3670 ----
  	write_inheritable_socket(&param->pgStatPipe1, pgStatPipe[1], childPid);
  
  	param->PostmasterPid = PostmasterPid;
+ 	param->PostmasterStartupTime = PostmasterStartupTime;
  
  #ifdef WIN32
  	param->PostmasterHandle = PostmasterHandle;
***************
*** 3859,3864 ****
--- 3866,3872 ----
  	read_inheritable_socket(&pgStatPipe[1], &param->pgStatPipe1);
  
  	PostmasterPid = param->PostmasterPid;
+ 	PostmasterStartupTime = param->PostmasterStartupTime;
  
  #ifdef WIN32
  	PostmasterHandle = param->PostmasterHandle;
*** ./src/backend/tcop/postgres.c.orig	2004-12-21 10:30:25.000000000 -0200
--- ./src/backend/tcop/postgres.c	2004-12-21 11:41:14.000000000 -0200
***************
*** 2896,2901 ****
--- 2896,2907 ----
  		send_rfq = true;		/* initially, or after error */
  
  	/*
+ 	 * Get time so we can use it to calculate PostgreSQL server uptime
+ 	 */
+ 	if (!IsUnderPostmaster)
+ 		PostmasterStartupTime = time(NULL);
+ 
+ 	/*
  	 * Non-error queries loop here.
  	 */
  
*** ./src/backend/utils/adt/Makefile.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/backend/utils/adt/Makefile	2004-12-20 15:12:59.000000000 -0200
***************
*** 24,30 ****
  	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
  
  like.o: like.c like_match.c
  
--- 24,30 ----
  	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 uptime.o
  
  like.o: like.c like_match.c
  
*** ./src/backend/utils/adt/uptime.c.orig	2004-12-22 00:11:47.000000000 -0200
--- ./src/backend/utils/adt/uptime.c	2004-12-22 00:59:51.000000000 -0200
***************
*** 0 ****
--- 1,85 ----
+ /*-------------------------------------------------------------------------
+  *
+  * uptime.c
+  *
+  *	Returns the PostgreSQL server uptime information
+  *
+  * Portions Copyright (c) 2004, PostgreSQL Global Development Group
+  *
+  *
+  * IDENTIFICATION
+  *
+  * $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "postgres.h"
+ 
+ #include <time.h>
+ 
+ #include "miscadmin.h"
+ #include "utils/builtins.h"
+ 
+ 
+ Datum
+ pgsql_uptime(PG_FUNCTION_ARGS)
+ {
+ 	char		buf[64];
+ 	int		buflen;
+ 	time_t		now;
+ 	long		updays, uphours, upmins, upsecs;
+ 	text		*result;
+ 
+ 	if (PostmasterStartupTime == InvalidTime)
+ 		ereport(ERROR,
+ 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 			(errmsg("invalid value for PostmasterStartupTime"))));
+ 	
+ 	/* calculate the uptime */
+ 	now = time(NULL);
+ 	upsecs = now - PostmasterStartupTime;
+ 
+ 	buf[0] = '\0';
+ 
+ 	/* days */
+ 	updays = (long) (upsecs / (60 * 60 * 24));
+ 	if (updays)
+ 		snprintf(buf, sizeof(buf),
+ 			" %ld %s", updays, (updays == 1) ? "day" : "days");
+ 
+ 	buflen = strlen(buf);
+ 
+ 	/* hours */
+ 	upsecs %= (60 * 60 * 24);
+ 	uphours = (long) (upsecs / (60 * 60));
+ 	if (uphours)
+ 		snprintf(buf + buflen, sizeof(buf) - buflen,
+ 			" %ld %s", uphours, (uphours == 1) ? "hour" : "hours");
+ 
+ 	buflen = strlen(buf);
+ 
+ 	/* minutes */
+ 	upsecs %= (60 * 60);
+ 	upmins = (long) (upsecs / 60);
+ 	if (upmins)
+ 		snprintf(buf + buflen, sizeof(buf) - buflen,
+ 			" %ld %s", upmins, (upmins == 1) ? "minute" : "minutes");
+ 	
+ 	buflen = strlen(buf);
+ 
+ 	/* seconds */
+ 	upsecs %= 60;
+ 	if (upsecs)
+ 		snprintf(buf + buflen, sizeof(buf) - buflen,
+ 			" %ld %s", upsecs, (upsecs == 1) ? "second" : "seconds");
+ 
+ 	/* make a text type for output */
+ 	/* -1 because we strip the initial space */
+ 	buflen = strlen(buf) - 1;
+ 	result = (text *) palloc(buflen + VARHDRSZ);
+ 	VARATT_SIZEP(result) = buflen + VARHDRSZ;
+ 	memcpy(VARDATA(result), (buf + 1), buflen);
+ 
+ 	PG_RETURN_TEXT_P(result);
+ }
*** ./src/backend/utils/init/globals.c.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/backend/utils/init/globals.c	2004-12-20 15:24:33.000000000 -0200
***************
*** 63,68 ****
--- 63,70 ----
  
  pid_t		PostmasterPid = 0;
  
+ time_t		PostmasterStartupTime = InvalidTime;
+ 
  /*
   * IsPostmasterEnvironment is true in a postmaster process and any postmaster
   * child process; it is false in a standalone process (bootstrap or
*** ./src/include/catalog/pg_proc.h.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/include/catalog/pg_proc.h	2004-12-20 15:12:59.000000000 -0200
***************
*** 199,204 ****
--- 199,206 ----
  
  DATA(insert OID =  84 (  boolne			   PGNSP PGUID 12 f f t f i 2 16 "16 16" _null_ boolne - _null_ ));
  DESCR("not equal");
+ DATA(insert OID =  88 (  uptime			   PGNSP PGUID 12 f f t f s 0 25 "" _null_ pgsql_uptime - _null_ ));
+ DESCR("PostgreSQL server uptime");
  DATA(insert OID =  89 (  version		   PGNSP PGUID 12 f f t f s 0 25 "" _null_ pgsql_version - _null_ ));
  DESCR("PostgreSQL version string");
  
*** ./src/include/miscadmin.h.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/include/miscadmin.h	2004-12-20 15:12:59.000000000 -0200
***************
*** 117,126 ****
--- 117,129 ----
   *	  globals.h --															 *
   *****************************************************************************/
  
+ #define	InvalidTime	(-1)
+ 
  /*
   * from utils/init/globals.c
   */
  extern pid_t PostmasterPid;
+ extern time_t PostmasterStartupTime;
  extern bool IsPostmasterEnvironment;
  extern bool IsUnderPostmaster;
  
*** ./src/include/utils/builtins.h.orig	2004-12-20 15:12:22.000000000 -0200
--- ./src/include/utils/builtins.h	2004-12-20 15:12:59.000000000 -0200
***************
*** 595,600 ****
--- 595,603 ----
  extern Datum bytea_substr(PG_FUNCTION_ARGS);
  extern Datum bytea_substr_no_len(PG_FUNCTION_ARGS);
  
+ /* uptime.c */
+ extern Datum pgsql_uptime(PG_FUNCTION_ARGS);
+ 
  /* version.c */
  extern Datum pgsql_version(PG_FUNCTION_ARGS);
  
