Add statement_timestamp(), clock_timestamp(), and
authorBruce Momjian <bruce@momjian.us>
Tue, 25 Apr 2006 00:25:22 +0000 (00:25 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 25 Apr 2006 00:25:22 +0000 (00:25 +0000)
transaction_timestamp() (just like now()).

Also update statement_timeout() to mention it is statement arrival time
that is measured.

Catalog version updated.

doc/src/sgml/config.sgml
doc/src/sgml/func.sgml
src/backend/access/transam/xact.c
src/backend/tcop/postgres.c
src/backend/utils/adt/timestamp.c
src/include/access/xact.h
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/timestamp.h

index 2ec9c3026cb036fcaf204feafe4cef617ce2efd2..384a71a74b2bdf553125e5c7a20cffc558a9f3cf 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.55 2006/04/23 03:39:48 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.56 2006/04/25 00:25:15 momjian Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3279,7 +3279,8 @@ SELECT * FROM parent WHERE key = 2400;
       <listitem>
        <para>
         Abort any statement that takes over the specified number of
-        milliseconds.  If <varname>log_min_error_statement</> is set to
+        milliseconds, starting from the time the command arrives at the server
+        from the client.  If <varname>log_min_error_statement</> is set to
         <literal>ERROR</> or lower, the statement that timed out will also be
         logged.  A value of zero (the default) turns off the 
         limitation.
index 0b5fb01e4da5ebcdf3f9b45c3c82d518692a59b3..b53bdca6fc397b4e0d786d0952da8a114212e3f4 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.314 2006/04/23 03:39:50 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.315 2006/04/25 00:25:15 momjian Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -5302,6 +5302,15 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
    <indexterm>
     <primary>now</primary>
    </indexterm>
+   <indexterm>
+    <primary>transaction_timestamp</primary>
+   </indexterm>
+   <indexterm>
+    <primary>statement_timestamp</primary>
+   </indexterm>
+   <indexterm>
+    <primary>clock_timestamp</primary>
+   </indexterm>
    <indexterm>
     <primary>timeofday</primary>
    </indexterm>
@@ -5358,7 +5367,7 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        <row>
         <entry><literal><function>current_timestamp</function></literal></entry>
         <entry><type>timestamp with time zone</type></entry>
-        <entry>Date and time; see <xref linkend="functions-datetime-current">
+        <entry>Date and time of start of current transaction; see <xref linkend="functions-datetime-current">
         </entry>
         <entry></entry>
         <entry></entry>
@@ -5474,8 +5483,36 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        <row>
         <entry><literal><function>now</function>()</literal></entry>
         <entry><type>timestamp with time zone</type></entry>
-        <entry>Current date and time (equivalent to
-         <function>current_timestamp</function>); see <xref linkend="functions-datetime-current">
+        <entry>Date and time of start of current transaction (equivalent to
+         <function>CURRENT_TIMESTAMP</function>); see <xref linkend="functions-datetime-current">
+        </entry>
+        <entry></entry>
+        <entry></entry>
+       </row>
+
+       <row>
+        <entry><literal><function>transaction_timestamp</function>()</literal></entry>
+        <entry><type>timestamp with time zone</type></entry>
+        <entry>Date and time of start of current transaction (equivalent to
+         <function>CURRENT_TIMESTAMP</function>); see <xref linkend="functions-datetime-current">
+        </entry>
+        <entry></entry>
+        <entry></entry>
+       </row>
+
+       <row>
+        <entry><literal><function>statement_timestamp</function>()</literal></entry>
+        <entry><type>timestamp with time zone</type></entry>
+        <entry>Date and time of start of current statement; see <xref linkend="functions-datetime-current">
+        </entry>
+        <entry></entry>
+        <entry></entry>
+       </row>
+
+       <row>
+        <entry><literal><function>clock_timestamp</function>()</literal></entry>
+        <entry><type>timestamp with time zone</type></entry>
+        <entry>Current date and time (changes during statement execution); see <xref linkend="functions-datetime-current">
         </entry>
         <entry></entry>
         <entry></entry>
@@ -5484,7 +5521,8 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
        <row>
         <entry><literal><function>timeofday</function>()</literal></entry>
         <entry><type>text</type></entry>
-        <entry>Current date and time; see <xref linkend="functions-datetime-current">
+        <entry>Current date and time (like <function>clock_timestamp</>), but as a Unix-style <type>text</> value; 
+        see <xref linkend="functions-datetime-current">
         </entry>
         <entry></entry>
         <entry></entry>
@@ -6072,7 +6110,7 @@ SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST';
   </sect2>
 
   <sect2 id="functions-datetime-current">
-   <title>Current Date/Time</title>
+   <title>Date/Time of Transaction Start</title>
 
    <indexterm>
     <primary>date</primary>
@@ -6085,8 +6123,8 @@ SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST';
    </indexterm>
 
    <para>
-    The following functions are available to obtain the current date and/or
-    time:
+    The following functions are available to obtain the date and/or
+    time of the start of the current transaction:
 <synopsis>
 CURRENT_DATE
 CURRENT_TIME
@@ -6138,12 +6176,6 @@ SELECT LOCALTIMESTAMP;
 </screen>
    </para>
 
-   <para>
-    The function <function>now()</function> is the traditional
-    <productname>PostgreSQL</productname> equivalent to
-    <function>CURRENT_TIMESTAMP</function>.
-   </para>
-
    <para>
     It is important to know that
     <function>CURRENT_TIMESTAMP</function> and related functions return
@@ -6152,26 +6184,31 @@ SELECT LOCALTIMESTAMP;
     the intent is to allow a single transaction to have a consistent
     notion of the <quote>current</quote> time, so that multiple
     modifications within the same transaction bear the same
-    time stamp.
+    time stamp.  Consider using <function>statement_timestamp</> or
+    <function>clock_timestamp</> if you need something that changes
+    more frequently.
    </para>
 
-   <note>
-    <para>
-     Other database systems may advance these values more
-     frequently.
-    </para>
-   </note>
+   <para>
+    <function>CURRENT_TIMESTAMP</> might not be the 
+    transaction start time on other database systems.
+    For this reason, and for completeness, 
+    <function>transaction_timestamp</> is provided.
+    The function <function>now()</function> is the traditional
+    <productname>PostgreSQL</productname> equivalent to
+    the SQL-standard <function>CURRENT_TIMESTAMP</function>.
+   </para>
 
    <para>
-    There is also the function <function>timeofday()</function> which
-    returns the wall-clock time and advances during transactions.  For
-    historical reasons <function>timeofday()</function> returns a
-    <type>text</type> string rather than a <type>timestamp</type>
-    value:
-<screen>
-SELECT timeofday();
-<lineannotation>Result: </lineannotation><computeroutput>Sat Feb 17 19:07:32.000126 2001 EST</computeroutput>
-</screen>
+    <function>STATEMENT_TIMESTAMP</> is the time the statement
+    arrived at the server from the client.  It is not the time
+    the command started execution.  If multiple commands were
+    sent as a single query string to the server, each command
+    has the same <function>STATEMENT_TIMESTAMP</> because they
+    all arrived at the same time.  Also, commands executed
+    by server-side functions have a <function>STATEMENT_TIMESTAMP</>
+    based on the time the client sent the query that triggered
+    the function, not the time the function was executed.
    </para>
 
    <para>
index 0bbe2c0d4956272b4230403e7f694298e2e3ff61..b59cea044b9de669eb60f3c0808f1f0834cb76f3 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.219 2006/03/29 21:17:37 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.220 2006/04/25 00:25:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -172,6 +172,7 @@ static CommandId currentCommandId;
  * keep it inside the TransactionState stack.
  */
 static TimestampTz xactStartTimestamp;
+static TimestampTz stmtStartTimestamp;
 
 /*
  * GID to be used for preparing the current transaction.  This is also
@@ -427,6 +428,24 @@ GetCurrentTransactionStartTimestamp(void)
    return xactStartTimestamp;
 }
 
+/*
+ * GetCurrentStatementStartTimestamp
+ */
+TimestampTz
+GetCurrentStatementStartTimestamp(void)
+{
+   return stmtStartTimestamp;
+}
+
+/*
+ * SetCurrentStatementStartTimestamp
+ */
+void
+SetCurrentStatementStartTimestamp(void)
+{
+   stmtStartTimestamp = GetCurrentTimestamp();
+}
+
 /*
  * GetCurrentTransactionNestLevel
  *
@@ -1367,9 +1386,9 @@ StartTransaction(void)
    XactLockTableInsert(s->transactionId);
 
    /*
-    * set now()
+    * now() and statement_timestamp() should be the same time
     */
-   xactStartTimestamp = GetCurrentTimestamp();
+   xactStartTimestamp = stmtStartTimestamp;
 
    /*
     * initialize current transaction state fields
index 04e432594e352af984a3162ab13769428d0acb31..2135c92fd807dc7120c939dc2c094bb3dd0eb1cd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.485 2006/04/22 01:26:00 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.486 2006/04/25 00:25:18 momjian Exp $
  *
  * NOTES
  *   this is the "main" module of the postgres backend and
@@ -118,6 +118,12 @@ static volatile sig_atomic_t got_SIGHUP = false;
  */
 static bool xact_started = false;
 
+/*
+ * Flag to keep track of whether we have done statement initialization.
+ * For extended query protocol this has to be remembered across messages.
+ */
+static bool command_initialized = false;
+
 /*
  * Flag to indicate that we are doing the outer loop's read-from-client,
  * as opposed to any random read from client that might happen within
@@ -164,6 +170,8 @@ static int  ReadCommand(StringInfo inBuf);
 static bool log_after_parse(List *raw_parsetree_list,
                const char *query_string, char **prepare_string);
 static List *pg_rewrite_queries(List *querytree_list);
+static void initialize_command(void);
+static void finalize_command(void);
 static void start_xact_command(void);
 static void finish_xact_command(void);
 static bool IsTransactionExitStmt(Node *parsetree);
@@ -858,7 +866,7 @@ exec_simple_query(const char *query_string)
     * one of those, else bad things will happen in xact.c. (Note that this
     * will normally change current memory context.)
     */
-   start_xact_command();
+   initialize_command();
 
    /*
     * Zap any pre-existing unnamed statement.  (While not strictly necessary,
@@ -1067,7 +1075,7 @@ exec_simple_query(const char *query_string)
    /*
     * Close down transaction statement, if one is open.
     */
-   finish_xact_command();
+   finalize_command();
 
    /*
     * If there were no parsetrees, return EmptyQueryResponse message.
@@ -1170,7 +1178,7 @@ exec_parse_message(const char *query_string,  /* string to execute */
     * that this will normally change current memory context.) Nothing happens
     * if we are already in one.
     */
-   start_xact_command();
+   initialize_command();
 
    /*
     * Switch to appropriate context for constructing parsetrees.
@@ -1393,7 +1401,7 @@ exec_bind_message(StringInfo input_message)
     * this will normally change current memory context.) Nothing happens if
     * we are already in one.
     */
-   start_xact_command();
+   initialize_command();
 
    /* Switch back to message context */
    MemoryContextSwitchTo(MessageContext);
@@ -1759,7 +1767,7 @@ exec_execute_message(const char *portal_name, long max_rows)
     * Ensure we are in a transaction command (this should normally be the
     * case already due to prior BIND).
     */
-   start_xact_command();
+   initialize_command();
 
    /*
     * If we are in aborted transaction state, the only portals we can
@@ -1883,7 +1891,7 @@ exec_describe_statement_message(const char *stmt_name)
     * Start up a transaction command. (Note that this will normally change
     * current memory context.) Nothing happens if we are already in one.
     */
-   start_xact_command();
+   initialize_command();
 
    /* Switch back to message context */
    MemoryContextSwitchTo(MessageContext);
@@ -1961,7 +1969,7 @@ exec_describe_portal_message(const char *portal_name)
     * Start up a transaction command. (Note that this will normally change
     * current memory context.) Nothing happens if we are already in one.
     */
-   start_xact_command();
+   initialize_command();
 
    /* Switch back to message context */
    MemoryContextSwitchTo(MessageContext);
@@ -2000,16 +2008,15 @@ exec_describe_portal_message(const char *portal_name)
 
 
 /*
- * Convenience routines for starting/committing a single command.
+ * Start xact if necessary, and set statement_timestamp() and optionally
+ * statement_timeout.
  */
 static void
-start_xact_command(void)
+initialize_command(void)
 {
-   if (!xact_started)
+   if (!command_initialized)
    {
-       ereport(DEBUG3,
-               (errmsg_internal("StartTransactionCommand")));
-       StartTransactionCommand();
+       SetCurrentStatementStartTimestamp();
 
        /* Set statement timeout running, if any */
        if (StatementTimeout > 0)
@@ -2017,19 +2024,48 @@ start_xact_command(void)
        else
            cancel_from_timeout = false;
 
-       xact_started = true;
+       command_initialized = true;
    }
+   start_xact_command();
 }
 
 static void
-finish_xact_command(void)
+finalize_command(void)
 {
-   if (xact_started)
+   if (command_initialized)
    {
        /* Cancel any active statement timeout before committing */
        disable_sig_alarm(true);
 
-       /* Now commit the command */
+       command_initialized = false;
+   }
+   finish_xact_command();
+}
+
+
+/*
+ * Check if the newly-arrived query string needs to have an implicit
+ * transaction started.
+ */
+static void
+start_xact_command(void)
+{
+   if (!xact_started)
+   {
+       ereport(DEBUG3,
+               (errmsg_internal("StartTransactionCommand")));
+
+       StartTransactionCommand();
+
+       xact_started = true;
+   }
+}
+
+static void
+finish_xact_command(void)
+{
+   if (xact_started)
+   {
        ereport(DEBUG3,
                (errmsg_internal("CommitTransactionCommand")));
 
@@ -3137,7 +3173,8 @@ PostgresMain(int argc, char *argv[], const char *username)
 
        /* We don't have a transaction command open anymore */
        xact_started = false;
-
+       command_initialized = false;
+       
        /* Now we can allow interrupts again */
        RESUME_INTERRUPTS();
    }
@@ -3305,7 +3342,7 @@ PostgresMain(int argc, char *argv[], const char *username)
                pgstat_report_activity("<FASTPATH> function call");
 
                /* start an xact for this function invocation */
-               start_xact_command();
+               initialize_command();
 
                /* switch back to message context */
                MemoryContextSwitchTo(MessageContext);
@@ -3328,7 +3365,7 @@ PostgresMain(int argc, char *argv[], const char *username)
                }
 
                /* commit the function-invocation transaction */
-               finish_xact_command();
+               finalize_command();
 
                send_ready_for_query = true;
                break;
@@ -3416,7 +3453,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 
            case 'S':           /* sync */
                pq_getmsgend(&input_message);
-               finish_xact_command();
+               finalize_command();
                send_ready_for_query = true;
                break;
 
index 0524bf123944b0e947cc4c84e07d880a521c93c5..fd40c1ebfdd9f69facbfd62813005e090d60c9e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.162 2006/03/06 22:49:16 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.163 2006/04/25 00:25:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -919,6 +919,18 @@ now(PG_FUNCTION_ARGS)
    PG_RETURN_TIMESTAMPTZ(GetCurrentTransactionStartTimestamp());
 }
 
+Datum
+statement_timestamp(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_TIMESTAMPTZ(GetCurrentStatementStartTimestamp());
+}
+
+Datum
+clock_timestamp(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_TIMESTAMPTZ(GetCurrentTimestamp());
+}
+
 Datum
 pgsql_postmaster_start_time(PG_FUNCTION_ARGS)
 {
index da2455f68fdf467a616ca8c4785d52d11b1ea99f..6591ba0456bcfba218570be87477dcd0c47604c6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.81 2006/03/24 04:32:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.82 2006/04/25 00:25:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -141,6 +141,8 @@ extern TransactionId GetCurrentTransactionIdIfAny(void);
 extern SubTransactionId GetCurrentSubTransactionId(void);
 extern CommandId GetCurrentCommandId(void);
 extern TimestampTz GetCurrentTransactionStartTimestamp(void);
+extern TimestampTz GetCurrentStatementStartTimestamp(void);
+extern void SetCurrentStatementStartTimestamp(void);
 extern int GetCurrentTransactionNestLevel(void);
 extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
 extern void CommandCounterIncrement(void);
index a88d3cfd5971d4427a13376381cbc95ad3098db9..11b02f691ad68afd6f3cbb2338833d534fe49f11 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.323 2006/04/22 01:26:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.324 2006/04/25 00:25:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200604211
+#define CATALOG_VERSION_NO 200604241
 
 #endif
index 9542d632f2518ea9c6c5db4b483cb8a8c92fe8e5..61339eadadc9a299c3a655f2f1e8c2d6389f1804 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.405 2006/04/05 22:11:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.406 2006/04/25 00:25:20 momjian Exp $
  *
  * NOTES
  *   The script catalog/genbki.sh reads this file and generates .bki
@@ -1614,6 +1614,12 @@ DATA(insert OID = 1298 (  timetzdate_pl    PGNSP PGUID 14 f f t f i 2 1184 "1266
 DESCR("convert time with time zone and date to timestamp with time zone");
 DATA(insert OID = 1299 (  now             PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_  now - _null_ ));
 DESCR("current transaction time");
+DATA(insert OID = 2647 (  transaction_timestamp    PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_ now - _null_ ));
+DESCR("current transaction time");
+DATA(insert OID = 2648 (  statement_timestamp  PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_ statement_timestamp - _null_ ));
+DESCR("current statement time");
+DATA(insert OID = 2649 (  clock_timestamp  PGNSP PGUID 12 f f t f v 0 1184 "" _null_ _null_ _null_ clock_timestamp - _null_ ));
+DESCR("current clock time");
 
 /* OIDS 1300 - 1399 */
 
index 9747b300b6c27105b16c529cb8327a2328c85b46..4e9e0c3f6f7a63dc4c523c1c990720781871e201 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.59 2006/03/06 22:49:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.60 2006/04/25 00:25:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -284,6 +284,8 @@ extern Datum timestamptz_trunc(PG_FUNCTION_ARGS);
 extern Datum timestamptz_part(PG_FUNCTION_ARGS);
 
 extern Datum now(PG_FUNCTION_ARGS);
+extern Datum statement_timestamp(PG_FUNCTION_ARGS);
+extern Datum clock_timestamp(PG_FUNCTION_ARGS);
 
 extern Datum pgsql_postmaster_start_time(PG_FUNCTION_ARGS);