OSDN Git Service

Accept an INTERVAL argument for SET TIME ZONE per SQL99.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 18 Oct 2001 17:30:21 +0000 (17:30 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 18 Oct 2001 17:30:21 +0000 (17:30 +0000)
 Modified the parser and the SET handlers to use full Node structures
 rather than simply a character string argument.
Implement INTERVAL() YEAR TO MONTH (etc) syntax per SQL99.
 Does not yet accept the goofy string format that goes along with, but
 this should be fairly straight forward to fix now as a bug or later
 as a feature.
Implement precision for the INTERVAL() type.
 Use the typmod mechanism for both of INTERVAL features.
Fix the INTERVAL syntax in the parser:
 opt_interval was in the wrong place.
INTERVAL is now a reserved word, otherwise we get reduce/reduce errors.
Implement an explicit date_part() function for TIMETZ.
 Should fix coersion problem with INTERVAL reported by Peter E.
Fix up some error messages for date/time types.
 Use all caps for type names within message.
Fix recently introduced side-effect bug disabling 'epoch' as a recognized
 field for date_part() etc. Reported by Peter E. (??)
Bump catalog version number.
Rename "microseconds" current transaction time field
 from ...Msec to ...Usec. Duh!
date/time regression tests updated for reference platform, but a few
 changes will be necessary for others.

23 files changed:
src/backend/access/transam/xact.c
src/backend/commands/variable.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/backend/utils/adt/nabstime.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/commands/variable.h
src/include/nodes/parsenodes.h
src/include/utils/date.h
src/include/utils/nabstime.h
src/include/utils/timestamp.h
src/interfaces/odbc/convert.c
src/test/regress/expected/horology.out
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/sql/horology.sql

index b7e13ec..cf9791a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.111 2001/09/29 04:02:21 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.112 2001/10/18 17:30:03 thomas Exp $
  *
  * NOTES
  *             Transaction aborts can now occur two ways:
@@ -378,7 +378,7 @@ GetCurrentTransactionStartTimeUsec(int *msec)
 {
        TransactionState s = CurrentTransactionState;
 
-       *msec = s->startTimeMsec;
+       *msec = s->startTimeUsec;
 
        return s->startTime;
 }
@@ -877,7 +877,7 @@ StartTransaction(void)
 #if NOT_USED
        s->startTime = GetCurrentAbsoluteTime();
 #endif
-       s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeMsec));
+       s->startTime = GetCurrentAbsoluteTimeUsec(&(s->startTimeUsec));
 
        /*
         * initialize the various transaction subsystems
index 029ea86..9da6776 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.53 2001/09/19 15:19:12 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.54 2001/10/18 17:30:14 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "optimizer/paths.h"
 #include "parser/parse_expr.h"
 #include "utils/builtins.h"
+#include "utils/date.h"
 #include "utils/guc.h"
 #include "utils/tqual.h"
 
 
 static bool show_datestyle(void);
 static bool reset_datestyle(void);
-static bool parse_datestyle(char *);
+static bool parse_datestyle(List *);
 static bool show_timezone(void);
 static bool reset_timezone(void);
-static bool parse_timezone(char *);
+static bool parse_timezone(List *);
 
 static bool show_XactIsoLevel(void);
 static bool reset_XactIsoLevel(void);
-static bool parse_XactIsoLevel(char *);
-static bool parse_random_seed(char *);
+static bool parse_XactIsoLevel(List *);
 static bool show_random_seed(void);
 static bool reset_random_seed(void);
+static bool parse_random_seed(List *);
 
 static bool show_client_encoding(void);
 static bool reset_client_encoding(void);
-static bool parse_client_encoding(char *);
+static bool parse_client_encoding(List *);
 static bool show_server_encoding(void);
 static bool reset_server_encoding(void);
-static bool parse_server_encoding(char *);
+static bool parse_server_encoding(List *);
 
 
 /*
@@ -177,7 +178,7 @@ get_token(char **tok, char **val, char *str)
 
 
 /*
- * DATE_STYLE
+ * DATESTYLE
  *
  * NOTE: set_default_datestyle() is called during backend startup to check
  * if the PGDATESTYLE environment variable is set.     We want the env var
@@ -189,17 +190,14 @@ static int        DefaultDateStyle;
 static bool DefaultEuroDates;
 
 static bool
-parse_datestyle(char *value)
+parse_datestyle_internal(char *value)
 {
        char       *tok;
        int                     dcnt = 0,
                                ecnt = 0;
 
        if (value == NULL)
-       {
-               reset_datestyle();
-               return TRUE;
-       }
+               return reset_datestyle();
 
        while ((value = get_token(&tok, NULL, value)) != 0)
        {
@@ -258,6 +256,21 @@ parse_datestyle(char *value)
 }
 
 static bool
+parse_datestyle(List *args)
+{
+       char       *value;
+
+       if (args == NULL)
+               return reset_datestyle();
+
+       Assert(IsA(lfirst(args), A_Const));
+
+       value = ((A_Const *) lfirst(args))->val.val.str;
+
+       return parse_datestyle_internal(value);
+}
+
+static bool
 show_datestyle(void)
 {
        char            buf[64];
@@ -321,8 +334,11 @@ set_default_datestyle(void)
         */
        DBDate = strdup(DBDate);
 
-       /* Parse desired setting into DateStyle/EuroDates */
-       parse_datestyle(DBDate);
+       /* Parse desired setting into DateStyle/EuroDates
+        * Use parse_datestyle_internal() to avoid any palloc() issues per above
+        * - thomas 2001-10-15
+        */
+       parse_datestyle_internal(DBDate);
 
        free(DBDate);
 
@@ -348,39 +364,96 @@ static char tzbuf[64];
 /* parse_timezone()
  * Handle SET TIME ZONE...
  * Try to save existing TZ environment variable for later use in RESET TIME ZONE.
- * - thomas 1997-11-10
+ * Accept an explicit interval per SQL9x, though this is less useful than a full time zone.
+ * - thomas 2001-10-11
  */
 static bool
-parse_timezone(char *value)
+parse_timezone(List *args)
 {
-       char       *tok;
+       List       *arg;
+       TypeName   *type;
 
-       if (value == NULL)
-       {
-               reset_timezone();
-               return TRUE;
-       }
+       if (args == NULL)
+               return reset_timezone();
 
-       while ((value = get_token(&tok, NULL, value)) != 0)
+       Assert(IsA(args, List));
+
+       foreach(arg, args)
        {
-               /* Not yet tried to save original value from environment? */
-               if (defaultTZ == NULL)
-               {
-                       /* found something? then save it for later */
-                       if ((defaultTZ = getenv("TZ")) != NULL)
-                               strcpy(TZvalue, defaultTZ);
+               A_Const *p;
 
-                       /* found nothing so mark with an invalid pointer */
-                       else
-                               defaultTZ = (char *) -1;
-               }
+               Assert(IsA(arg, List));
+               p = lfirst(arg);
+               Assert(IsA(p, A_Const));
 
-               strcpy(tzbuf, "TZ=");
-               strcat(tzbuf, tok);
-               if (putenv(tzbuf) != 0)
-                       elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+               type = p->typename;
+               if (type != NULL)
+               {
+                       if (strcmp(type->name, "interval") == 0)
+                       {
+                               Interval   *interval;
+
+                               interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
+                                                                                                                                CStringGetDatum(p->val.val.str),
+                                                                                                                                ObjectIdGetDatum(InvalidOid),
+                                                                                                                                Int32GetDatum(-1)));
+                               if (interval->month != 0)
+                                       elog(ERROR, "SET TIME ZONE illegal INTERVAL; month not allowed");
+                               CTimeZone = interval->time;
+                       }
+                       else if (strcmp(type->name, "float8") == 0)
+                       {
+                               float8 time;
+
+                               time = DatumGetFloat8(DirectFunctionCall1(float8in, CStringGetDatum(p->val.val.str)));
+                               CTimeZone = time * 3600;
+                       }
+                       /* We do not actually generate an integer constant in gram.y so this is not used... */
+                       else if (strcmp(type->name, "int4") == 0)
+                       {
+                               int32 time;
+
+                               time = p->val.val.ival;
+                               CTimeZone = time * 3600;
+                       }
+                       else
+                       {
+                               elog(ERROR, "Unable to process SET TIME ZONE command; internal coding error");
+                       }
 
-               tzset();
+                       HasCTZSet = true;
+               }
+               else
+               {
+                       char       *tok;
+                       char       *value;
+
+                       value = p->val.val.str;
+
+                       while ((value = get_token(&tok, NULL, value)) != 0)
+                       {
+                               /* Not yet tried to save original value from environment? */
+                               if (defaultTZ == NULL)
+                               {
+                                       /* found something? then save it for later */
+                                       if ((defaultTZ = getenv("TZ")) != NULL)
+                                               strcpy(TZvalue, defaultTZ);
+
+                                       /* found nothing so mark with an invalid pointer */
+                                       else
+                                               defaultTZ = (char *) -1;
+                               }
+
+                               strcpy(tzbuf, "TZ=");
+                               strcat(tzbuf, tok);
+                               if (putenv(tzbuf) != 0)
+                                       elog(ERROR, "Unable to set TZ environment variable to %s", tok);
+
+                               tzset();
+                       }
+
+                       HasCTZSet = false;
+               }
        }
 
        return TRUE;
@@ -389,11 +462,26 @@ parse_timezone(char *value)
 static bool
 show_timezone(void)
 {
-       char       *tz;
+       char *tzn;
+
+       if (HasCTZSet)
+       {
+               Interval interval;
 
-       tz = getenv("TZ");
+               interval.month = 0;
+               interval.time = CTimeZone;
+
+               tzn = DatumGetCString(DirectFunctionCall1(interval_out, IntervalPGetDatum(&interval)));
+       }
+       else
+       {
+               tzn = getenv("TZ");
+       }
 
-       elog(NOTICE, "Time zone is %s", ((tz != NULL) ? tz : "unset"));
+       if (tzn != NULL)
+               elog(NOTICE, "Time zone is '%s'", tzn);
+       else
+               elog(NOTICE, "Time zone is unset");
 
        return TRUE;
 }      /* show_timezone() */
@@ -411,8 +499,13 @@ show_timezone(void)
 static bool
 reset_timezone(void)
 {
+       if (HasCTZSet)
+       {
+               HasCTZSet = false;
+       }
+
        /* no time zone has been set in this session? */
-       if (defaultTZ == NULL)
+       else if (defaultTZ == NULL)
        {
        }
 
@@ -443,17 +536,23 @@ reset_timezone(void)
 
 
 
-/* SET TRANSACTION */
+/*
+ *
+ * SET TRANSACTION
+ *
+ */
 
 static bool
-parse_XactIsoLevel(char *value)
+parse_XactIsoLevel(List *args)
 {
+       char *value;
 
-       if (value == NULL)
-       {
-               reset_XactIsoLevel();
-               return TRUE;
-       }
+       if (args == NULL)
+               return reset_XactIsoLevel();
+
+       Assert(IsA(lfirst(args), A_Const));
+
+       value = ((A_Const *) lfirst(args))->val.val.str;
 
        if (SerializableSnapshot != NULL)
        {
@@ -461,7 +560,6 @@ parse_XactIsoLevel(char *value)
                return TRUE;
        }
 
-
        if (strcmp(value, "serializable") == 0)
                XactIsoLevel = XACT_SERIALIZABLE;
        else if (strcmp(value, "read committed") == 0)
@@ -503,17 +601,21 @@ reset_XactIsoLevel(void)
  * Random number seed
  */
 static bool
-parse_random_seed(char *value)
+parse_random_seed(List *args)
 {
-       double          seed = 0;
+       char   *value;
+       double  seed = 0;
+
+       if (args == NULL)
+               return reset_random_seed();
+
+       Assert(IsA(lfirst(args), A_Const));
+
+       value = ((A_Const *) lfirst(args))->val.val.str;
+
+       sscanf(value, "%lf", &seed);
+       DirectFunctionCall1(setseed, Float8GetDatum(seed));
 
-       if (value == NULL)
-               reset_random_seed();
-       else
-       {
-               sscanf(value, "%lf", &seed);
-               DirectFunctionCall1(setseed, Float8GetDatum(seed));
-       }
        return (TRUE);
 }
 
@@ -544,16 +646,26 @@ reset_random_seed(void)
  */
 
 static bool
-parse_client_encoding(char *value)
+parse_client_encoding(List *args)
 {
+       char   *value;
 #ifdef MULTIBYTE
-       int                     encoding;
+       int             encoding;
+#endif
 
+       if (args == NULL)
+               return reset_client_encoding();
+
+       Assert(IsA(lfirst(args), A_Const));
+
+       value = ((A_Const *) lfirst(args))->val.val.str;
+
+#ifdef MULTIBYTE
        encoding = pg_valid_client_encoding(value);
        if (encoding < 0)
        {
                if (value)
-                       elog(ERROR, "Client encoding %s is not supported", value);
+                       elog(ERROR, "Client encoding '%s' is not supported", value);
                else
                        elog(ERROR, "No client encoding is specified");
        }
@@ -576,8 +688,8 @@ parse_client_encoding(char *value)
 static bool
 show_client_encoding(void)
 {
-       elog(NOTICE, "Current client encoding is %s",
-               pg_get_client_encoding_name());
+       elog(NOTICE, "Current client encoding is '%s'",
+                pg_get_client_encoding_name());
        return TRUE;
 }
 
@@ -596,6 +708,7 @@ reset_client_encoding(void)
        }
        else
                encoding = GetDatabaseEncoding();
+
        pg_set_client_encoding(encoding);
 #endif
        return TRUE;
@@ -610,7 +723,7 @@ set_default_client_encoding(void)
 
 
 static bool
-parse_server_encoding(char *value)
+parse_server_encoding(List *args)
 {
        elog(NOTICE, "SET SERVER_ENCODING is not supported");
        return TRUE;
@@ -619,7 +732,7 @@ parse_server_encoding(char *value)
 static bool
 show_server_encoding(void)
 {
-       elog(NOTICE, "Current server encoding is %s", GetDatabaseEncodingName());
+       elog(NOTICE, "Current server encoding is '%s'", GetDatabaseEncodingName());
        return TRUE;
 }
 
@@ -632,33 +745,42 @@ reset_server_encoding(void)
 
 
 
+/* SetPGVariable()
+ * Dispatcher for handling SET commands.
+ * Special cases ought to be removed and handled separately by TCOP
+ */
 void
-SetPGVariable(const char *name, const char *value)
+SetPGVariable(const char *name, List *args)
 {
-       char       *mvalue = value ? pstrdup(value) : ((char *) NULL);
-
-       /*
-        * Special cases ought to be removed and handled separately by TCOP
-        */
        if (strcasecmp(name, "datestyle") == 0)
-               parse_datestyle(mvalue);
+               parse_datestyle(args);
        else if (strcasecmp(name, "timezone") == 0)
-               parse_timezone(mvalue);
+               parse_timezone(args);
        else if (strcasecmp(name, "XactIsoLevel") == 0)
-               parse_XactIsoLevel(mvalue);
+               parse_XactIsoLevel(args);
        else if (strcasecmp(name, "client_encoding") == 0)
-               parse_client_encoding(mvalue);
+               parse_client_encoding(args);
        else if (strcasecmp(name, "server_encoding") == 0)
-               parse_server_encoding(mvalue);
+               parse_server_encoding(args);
        else if (strcasecmp(name, "seed") == 0)
-               parse_random_seed(mvalue);
-       else if (strcasecmp(name, "session_authorization") == 0)
-               SetSessionAuthorization(value);
+               parse_random_seed(args);
        else
-               SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+       {
+               /* For routines defined somewhere else,
+                * go ahead and extract the string argument
+                * to match the original interface definition.
+                * Later, we can change this code too...
+                */
+               char *value;
 
-       if (mvalue)
-               pfree(mvalue);
+               value = ((args != NULL)? ((A_Const *) lfirst(args))->val.val.str: NULL);
+
+               if (strcasecmp(name, "session_authorization") == 0)
+                       SetSessionAuthorization(value);
+               else
+                       SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET, false);
+       }
+       return;
 }
 
 void
@@ -685,7 +807,8 @@ GetPGVariable(const char *name)
                show_client_encoding();
                show_server_encoding();
                show_random_seed();
-       } else
+       }
+       else
        {
                const char *val = GetConfigOption(name);
 
index 5cb918e..abf5c08 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.157 2001/10/02 21:39:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.158 2001/10/18 17:30:14 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2287,8 +2287,7 @@ _copyVariableSetStmt(VariableSetStmt *from)
 
        if (from->name)
                newnode->name = pstrdup(from->name);
-       if (from->value)
-               newnode->value = pstrdup(from->value);
+       Node_Copy(from, newnode, args);
 
        return newnode;
 }
index dd2895f..64e27f1 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.105 2001/10/02 21:39:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.106 2001/10/18 17:30:14 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1159,7 +1159,7 @@ _equalVariableSetStmt(VariableSetStmt *a, VariableSetStmt *b)
 {
        if (!equalstr(a->name, b->name))
                return false;
-       if (!equalstr(a->value, b->value))
+       if (!equal(a->args, b->args))
                return false;
 
        return true;
index 0be9360..efd5fd4 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.262 2001/10/10 00:02:42 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.263 2001/10/18 17:30:14 thomas Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -58,6 +58,7 @@
 #include "storage/lmgr.h"
 #include "utils/acl.h"
 #include "utils/numeric.h"
+#include "utils/datetime.h"
 
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
@@ -82,6 +83,8 @@ static int    pfunc_num_args;
 
 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
 static Node *makeTypeCast(Node *arg, TypeName *typename);
+static Node *makeStringConst(char *str, TypeName *typename);
+static Node *makeFloatConst(char *str);
 static Node *makeRowExpr(char *opr, List *largs, List *rargs);
 static void mapTargetColumns(List *source, List *target);
 static SelectStmt *findLeftmostSelect(SelectStmt *node);
@@ -92,6 +95,8 @@ static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
 static Node *doNegate(Node *n);
 static void doNegateFloat(Value *v);
 
+#define MASK(b) (1 << (b))
+
 %}
 
 
@@ -209,7 +214,7 @@ static void doNegateFloat(Value *v);
 
 %type <list>   extract_list, position_list
 %type <list>   substr_list, trim_list
-%type <list>   opt_interval
+%type <ival>   opt_interval
 %type <node>   substr_from, substr_for
 
 %type <boolean>        opt_binary, opt_using, opt_instead, opt_cursor
@@ -263,8 +268,9 @@ static void doNegateFloat(Value *v);
 
 %type <ival>   Iconst
 %type <str>            Sconst, comment_text
-%type <str>            UserId, opt_boolean, var_value, zone_value, ColId_or_Sconst
+%type <str>            UserId, opt_boolean, var_value, ColId_or_Sconst
 %type <str>            ColId, ColLabel, TokenId
+%type <node>   zone_value
 
 %type <node>   TableConstraint
 %type <list>   ColQualList
@@ -757,49 +763,50 @@ VariableSetStmt:  SET ColId TO var_value
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = $2;
-                                       n->value = $4;
+                                       n->args = makeList1(makeStringConst($4, NULL));
                                        $$ = (Node *) n;
                                }
                | SET ColId '=' var_value
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = $2;
-                                       n->value = $4;
+                                       n->args = makeList1(makeStringConst($4, NULL));
                                        $$ = (Node *) n;
                                }
                | SET TIME ZONE zone_value
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = "timezone";
-                                       n->value = $4;
+                                       if ($4 != NULL)
+                                               n->args = makeList1($4);
                                        $$ = (Node *) n;
                                }
                | SET TRANSACTION ISOLATION LEVEL opt_level
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = "XactIsoLevel";
-                                       n->value = $5;
+                                       n->args = makeList1(makeStringConst($5, NULL));
                                        $$ = (Node *) n;
                                }
         | SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL opt_level
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = "default_transaction_isolation";
-                                       n->value = $8;
+                                       n->args = makeList1(makeStringConst($8, NULL));
                                        $$ = (Node *) n;
                                }
                | SET NAMES opt_encoding
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name  = "client_encoding";
-                                       n->value = $3;
+                                       n->args = makeList1(makeStringConst($3, NULL));
                                        $$ = (Node *) n;
                                }
                | SET SESSION AUTHORIZATION ColId_or_Sconst
                                {
                                        VariableSetStmt *n = makeNode(VariableSetStmt);
                                        n->name = "session_authorization";
-                                       n->value = $4;
+                                       n->args = makeList1(makeStringConst($4, NULL));
                                        $$ = (Node *) n;
                                }
                ;
@@ -868,7 +875,47 @@ opt_boolean:  TRUE_P                                               { $$ = "true"; }
                | OFF                                                           { $$ = "off"; }
                ;
 
-zone_value:  Sconst                                                    { $$ = $1; }
+/* Timezone values can be:
+ * - a string such as 'pst8pdt'
+ * - an integer or floating point number
+ * - a time interval per SQL99
+ */
+zone_value:  Sconst
+                       {
+                               $$ = makeStringConst($1, NULL);
+                       }
+               | ConstInterval Sconst opt_interval
+                       {
+                               A_Const *n = (A_Const *) makeStringConst($2, $1);
+                               n->typename->typmod = (($3 << 16) | 0xFFFF);
+                               $$ = (Node *)n;
+                       }
+               | ConstInterval '(' Iconst ')' Sconst opt_interval
+                       {
+                               A_Const *n = (A_Const *) makeStringConst($5, $1);
+                               n->typename->typmod = (($3 << 16) | $6);
+                               $$ = (Node *)n;
+                       }
+               | FCONST
+                       {
+                               $$ = makeFloatConst($1);
+                       }
+               | '-' FCONST
+                       {
+                               $$ = doNegate(makeFloatConst($2));
+                       }
+               | ICONST
+                       {
+                               char buf[64];
+                               sprintf(buf, "%d", $1);
+                               $$ = makeFloatConst(pstrdup(buf));
+                       }
+               | '-' ICONST
+                       {
+                               char buf[64];
+                               sprintf(buf, "%d", $2);
+                               $$ = doNegate(makeFloatConst(pstrdup(buf)));
+                       }
                | DEFAULT                                                       { $$ = NULL; }
                | LOCAL                                                         { $$ = NULL; }
                ;
@@ -3994,7 +4041,16 @@ opt_array_bounds:        opt_array_bounds '[' ']'
                ;
 
 SimpleTypename:  ConstTypename
-               | ConstInterval
+               | ConstInterval opt_interval
+                               {
+                                       $$ = $1;
+                                       $$->typmod = (($2 << 16) | 0xFFFF);
+                               }
+               | ConstInterval '(' Iconst ')' opt_interval
+                               {
+                                       $$ = $1;
+                                       $$->typmod = (($5 << 16) | $3);
+                               }
                ;
 
 ConstTypename:  GenericType
@@ -4267,7 +4323,10 @@ ConstDatetime:  datetime
                                         * - thomas 2001-09-06
                                         */
                                        $$->timezone = $2;
-                                       $$->typmod = 0;
+                                       /* SQL99 specified a default precision of six.
+                                        * - thomas 2001-09-30
+                                        */
+                                       $$->typmod = 6;
                                }
                | TIME '(' Iconst ')' opt_timezone
                                {
@@ -4295,7 +4354,7 @@ ConstDatetime:  datetime
                                }
                ;
 
-ConstInterval:  INTERVAL opt_interval
+ConstInterval:  INTERVAL
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("interval");
@@ -4326,15 +4385,20 @@ opt_timezone:  WITH TIME ZONE                                   { $$ = TRUE; }
                | /*EMPTY*/                                                             { $$ = FALSE; }
                ;
 
-opt_interval:  datetime                                                        { $$ = makeList1($1); }
-               | YEAR_P TO MONTH_P                                             { $$ = NIL; }
-               | DAY_P TO HOUR_P                                               { $$ = NIL; }
-               | DAY_P TO MINUTE_P                                             { $$ = NIL; }
-               | DAY_P TO SECOND_P                                             { $$ = NIL; }
-               | HOUR_P TO MINUTE_P                                    { $$ = NIL; }
-               | HOUR_P TO SECOND_P                                    { $$ = NIL; }
-               | MINUTE_P TO SECOND_P                                  { $$ = NIL; }
-               | /*EMPTY*/                                                             { $$ = NIL; }
+opt_interval:  YEAR_P                                                  { $$ = MASK(YEAR); }
+               | MONTH_P                                                               { $$ = MASK(MONTH); }
+               | DAY_P                                                                 { $$ = MASK(DAY); }
+               | HOUR_P                                                                { $$ = MASK(HOUR); }
+               | MINUTE_P                                                              { $$ = MASK(MINUTE); }
+               | SECOND_P                                                              { $$ = MASK(SECOND); }
+               | YEAR_P TO MONTH_P                                             { $$ = MASK(YEAR) | MASK(MONTH); }
+               | DAY_P TO HOUR_P                                               { $$ = MASK(DAY) | MASK(HOUR); }
+               | DAY_P TO MINUTE_P                                             { $$ = MASK(DAY) | MASK(HOUR) | MASK(MINUTE); }
+               | DAY_P TO SECOND_P                                             { $$ = MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND); }
+               | HOUR_P TO MINUTE_P                                    { $$ = MASK(HOUR) | MASK(MINUTE); }
+               | HOUR_P TO SECOND_P                                    { $$ = MASK(HOUR) | MASK(MINUTE) | MASK(SECOND); }
+               | MINUTE_P TO SECOND_P                                  { $$ = MASK(MINUTE) | MASK(SECOND); }
+               | /*EMPTY*/                                                             { $$ = -1; }
                ;
 
 
@@ -5561,6 +5625,16 @@ AexprConst:  Iconst
                                        n->typename = $1;
                                        n->val.type = T_String;
                                        n->val.val.str = $2;
+                                       n->typename->typmod = (($3 << 16) | 0xFFFF);
+                                       $$ = (Node *)n;
+                               }
+               | ConstInterval '(' Iconst ')' Sconst opt_interval
+                               {
+                                       A_Const *n = makeNode(A_Const);
+                                       n->typename = $1;
+                                       n->val.type = T_String;
+                                       n->val.val.str = $5;
+                                       n->typename->typmod = (($6 << 16) | $3);
                                        $$ = (Node *)n;
                                }
                | ParamNo
@@ -5616,7 +5690,6 @@ UserId:  ColId                                                    { $$ = $1; };
 ColId:  IDENT                                                  { $$ = $1; }
                | datetime                                              { $$ = $1; }
                | TokenId                                               { $$ = $1; }
-               | INTERVAL                                              { $$ = "interval"; }
                | NATIONAL                                              { $$ = "national"; }
                | NONE                                                  { $$ = "none"; }
                | PATH_P                                                { $$ = "path"; }
@@ -5818,12 +5891,13 @@ ColLabel:  ColId                                                { $$ = $1; }
                | GROUP                                                 { $$ = "group"; }
                | HAVING                                                { $$ = "having"; }
                | ILIKE                                                 { $$ = "ilike"; }
-               | INITIALLY                                             { $$ = "initially"; }
                | IN                                                    { $$ = "in"; }
+               | INITIALLY                                             { $$ = "initially"; }
                | INNER_P                                               { $$ = "inner"; }
+               | INOUT                                                 { $$ = "inout"; }
                | INTERSECT                                             { $$ = "intersect"; }
+               | INTERVAL                                              { $$ = "interval"; }
                | INTO                                                  { $$ = "into"; }
-               | INOUT                                                 { $$ = "inout"; }
                | IS                                                    { $$ = "is"; }
                | ISNULL                                                { $$ = "isnull"; }
                | JOIN                                                  { $$ = "join"; }
@@ -5947,6 +6021,31 @@ makeTypeCast(Node *arg, TypeName *typename)
        }
 }
 
+static Node *
+makeStringConst(char *str, TypeName *typename)
+{
+       A_Const *n = makeNode(A_Const);
+       n->val.type = T_String;
+       n->val.val.str = str;
+       n->typename = typename;
+
+       return (Node *)n;
+}
+
+static Node *
+makeFloatConst(char *str)
+{
+       A_Const *n = makeNode(A_Const);
+       TypeName *t = makeNode(TypeName);
+       n->val.type = T_Float;
+       n->val.val.str = str;
+       t->name = xlateSqlType("float");
+       t->typmod = -1;
+       n->typename = t;
+
+       return (Node *)n;
+}
+
 /* makeRowExpr()
  * Generate separate operator nodes for a single row descriptor expression.
  * Perhaps this should go deeper in the parser someday...
index 6822fe8..66ccb65 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.120 2001/10/12 00:07:14 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.121 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -740,7 +740,7 @@ ProcessUtility(Node *parsetree,
                        {
                                VariableSetStmt *n = (VariableSetStmt *) parsetree;
 
-                               SetPGVariable(n->name, n->value);
+                               SetPGVariable(n->name, n->args);
                                set_ps_display(commandTag = "SET VARIABLE");
                        }
                        break;
index f8693c7..d59d9f9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.61 2001/10/04 15:14:22 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.62 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1458,6 +1458,117 @@ text_timetz(PG_FUNCTION_ARGS)
                                                           Int32GetDatum(-1));
 }
 
+/* timetz_part()
+ * Extract specified field from time type.
+ */
+Datum
+timetz_part(PG_FUNCTION_ARGS)
+{
+       text       *units = PG_GETARG_TEXT_P(0);
+       TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
+       float8          result;
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowunits[MAXDATELEN + 1];
+
+       if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
+               elog(ERROR, "TIMETZ units '%s' not recognized",
+                        DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                PointerGetDatum(units))));
+       up = VARDATA(units);
+       lp = lowunits;
+       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+               *lp++ = tolower((unsigned char) *up++);
+       *lp = '\0';
+
+       type = DecodeUnits(0, lowunits, &val);
+       if (type == UNKNOWN_FIELD)
+               type = DecodeSpecial(0, lowunits, &val);
+
+       if (type == UNITS)
+       {
+               double          trem;
+               double          dummy;
+               int                     tz;
+               double          fsec;
+               struct tm       tt,
+                                  *tm = &tt;
+
+               trem = time->time;
+               TMODULO(trem, tm->tm_hour, 3600e0);
+               TMODULO(trem, tm->tm_min, 60e0);
+               TMODULO(trem, tm->tm_sec, 1e0);
+               fsec = trem;
+               tz = time->zone;
+
+               switch (val)
+               {
+                       case DTK_TZ:
+                               result = tz;
+                               break;
+
+                       case DTK_TZ_MINUTE:
+                               result = tz / 60;
+                               TMODULO(result, dummy, 60e0);
+                               break;
+
+                       case DTK_TZ_HOUR:
+                               dummy = tz;
+                               TMODULO(dummy, result, 3600e0);
+                               break;
+
+                       case DTK_MICROSEC:
+                               result = ((tm->tm_sec + fsec) * 1000000);
+                               break;
+
+                       case DTK_MILLISEC:
+                               result = ((tm->tm_sec + fsec) * 1000);
+                               break;
+
+                       case DTK_SECOND:
+                               result = (tm->tm_sec + fsec);
+                               break;
+
+                       case DTK_MINUTE:
+                               result = tm->tm_min;
+                               break;
+
+                       case DTK_HOUR:
+                               result = tm->tm_hour;
+                               break;
+
+                       case DTK_DAY:
+                       case DTK_MONTH:
+                       case DTK_QUARTER:
+                       case DTK_YEAR:
+                       case DTK_DECADE:
+                       case DTK_CENTURY:
+                       case DTK_MILLENNIUM:
+                       default:
+                               elog(ERROR, "TIMETZ units '%s' not supported",
+                                        DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                                PointerGetDatum(units))));
+                               result = 0;
+               }
+       }
+       else if ((type == RESERV) && (val == DTK_EPOCH))
+       {
+               result = time->time - time->zone;
+       }
+       else
+       {
+               elog(ERROR, "TIMETZ units '%s' not recognized",
+                        DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                PointerGetDatum(units))));
+               result = 0;
+       }
+
+       PG_RETURN_FLOAT8(result);
+}
+
 /* timetz_zone()
  * Encode time with time zone type with specified time zone.
  */
index 33fa764..2752319 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.72 2001/10/11 18:06:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.73 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,7 @@ static int    DecodeTimezone(char *str, int *tzp);
 static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
 static int     DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
 static int     DecodePosixTimezone(char *str, int *val);
+void TrimTrailingZeros(char *str);
 
 
 int                    day_tab[2][13] = {
@@ -239,81 +240,73 @@ static unsigned int australian_szdatetktbl = sizeof australian_datetktbl /
                                                                                         sizeof australian_datetktbl[0];
 
 static datetkn deltatktbl[] = {
-/*     text, token, lexval */
-       {"@", IGNORE, 0},                       /* postgres relative time prefix */
+       /* text, token, lexval */
+       {"@", IGNORE, 0},                       /* postgres relative prefix */
        {DAGO, AGO, 0},                         /* "ago" indicates negative time offset */
-       {"c", UNITS, DTK_CENTURY},      /* "century" relative time units */
-       {"cent", UNITS, DTK_CENTURY},           /* "century" relative time units */
-       {"centuries", UNITS, DTK_CENTURY},      /* "centuries" relative time units */
-       {DCENTURY, UNITS, DTK_CENTURY},         /* "century" relative time units */
-       {"d", UNITS, DTK_DAY},          /* "day" relative time units */
-       {DDAY, UNITS, DTK_DAY},         /* "day" relative time units */
-       {"days", UNITS, DTK_DAY},       /* "days" relative time units */
-       {"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */
-       {"decs", UNITS, DTK_DECADE},/* "decades" relative time units */
-       {DDECADE, UNITS, DTK_DECADE},           /* "decade" relative time units */
-       {"decades", UNITS, DTK_DECADE},         /* "decades" relative time units */
-       {"h", UNITS, DTK_HOUR},         /* "hour" relative time units */
-       {DHOUR, UNITS, DTK_HOUR},       /* "hour" relative time units */
-       {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */
-       {"hr", UNITS, DTK_HOUR},        /* "hour" relative time units */
-       {"hrs", UNITS, DTK_HOUR},       /* "hours" relative time units */
+       {"c", UNITS, DTK_CENTURY},      /* "century" relative */
+       {"cent", UNITS, DTK_CENTURY},           /* "century" relative */
+       {"centuries", UNITS, DTK_CENTURY},      /* "centuries" relative */
+       {DCENTURY, UNITS, DTK_CENTURY},         /* "century" relative */
+       {"d", UNITS, DTK_DAY},                          /* "day" relative */
+       {DDAY, UNITS, DTK_DAY},                         /* "day" relative */
+       {"days", UNITS, DTK_DAY},                       /* "days" relative */
+       {"dec", UNITS, DTK_DECADE},                     /* "decade" relative */
+       {"decs", UNITS, DTK_DECADE},            /* "decades" relative */
+       {DDECADE, UNITS, DTK_DECADE},           /* "decade" relative */
+       {"decades", UNITS, DTK_DECADE},         /* "decades" relative */
+       {"h", UNITS, DTK_HOUR},                         /* "hour" relative */
+       {DHOUR, UNITS, DTK_HOUR},                       /* "hour" relative */
+       {"hours", UNITS, DTK_HOUR},                     /* "hours" relative */
+       {"hr", UNITS, DTK_HOUR},                        /* "hour" relative */
+       {"hrs", UNITS, DTK_HOUR},                       /* "hours" relative */
        {INVALID, RESERV, DTK_INVALID},         /* reserved for invalid time */
-       {"m", UNITS, DTK_MINUTE},       /* "minute" relative time units */
-       {"microsecon", UNITS, DTK_MICROSEC},            /* "microsecond" relative
-                                                                                                * time units */
-       {"mil", UNITS, DTK_MILLENNIUM},         /* "millennium" relative time
-                                                                                * units */
-       {"mils", UNITS, DTK_MILLENNIUM},        /* "millennia" relative time units */
-       {"millennia", UNITS, DTK_MILLENNIUM},           /* "millennia" relative
-                                                                                                * time units */
-       {DMILLENNIUM, UNITS, DTK_MILLENNIUM},           /* "millennium" relative
-                                                                                                * time units */
-       {"millisecon", UNITS, DTK_MILLISEC},            /* relative time units */
-       {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
-       {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
-       {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
-       {DMINUTE, UNITS, DTK_MINUTE},           /* "minute" relative time units */
-       {"minutes", UNITS, DTK_MINUTE},         /* "minutes" relative time units */
-       {"mon", UNITS, DTK_MONTH},      /* "months" relative time units */
-       {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
-       {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
+       {"m", UNITS, DTK_MINUTE},                       /* "minute" relative */
+       {"microsecon", UNITS, DTK_MICROSEC},    /* "microsecond" relative */
+       {"mil", UNITS, DTK_MILLENNIUM},                 /* "millennium" relative */
+       {"millennia", UNITS, DTK_MILLENNIUM},   /* "millennia" relative */
+       {DMILLENNIUM, UNITS, DTK_MILLENNIUM},   /* "millennium" relative */
+       {"millisecon", UNITS, DTK_MILLISEC},    /* relative */
+       {"mils", UNITS, DTK_MILLENNIUM},        /* "millennia" relative */
+       {"min", UNITS, DTK_MINUTE},                     /* "minute" relative */
+       {"mins", UNITS, DTK_MINUTE},            /* "minutes" relative */
+       {"mins", UNITS, DTK_MINUTE},            /* "minutes" relative */
+       {DMINUTE, UNITS, DTK_MINUTE},           /* "minute" relative */
+       {"minutes", UNITS, DTK_MINUTE},         /* "minutes" relative */
+       {"mon", UNITS, DTK_MONTH},                      /* "months" relative */
+       {"mons", UNITS, DTK_MONTH},                     /* "months" relative */
+       {DMONTH, UNITS, DTK_MONTH},                     /* "month" relative */
        {"months", UNITS, DTK_MONTH},
        {"ms", UNITS, DTK_MILLISEC},
        {"msec", UNITS, DTK_MILLISEC},
        {DMILLISEC, UNITS, DTK_MILLISEC},
        {"mseconds", UNITS, DTK_MILLISEC},
        {"msecs", UNITS, DTK_MILLISEC},
-       {"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time */
-       {DQUARTER, UNITS, DTK_QUARTER},         /* "quarter" relative time */
-       {"reltime", IGNORE, 0},         /* for pre-v6.1 "Undefined Reltime" */
+       {"qtr", UNITS, DTK_QUARTER},            /* "quarter" relative */
+       {DQUARTER, UNITS, DTK_QUARTER},         /* "quarter" relative */
+       {"reltime", IGNORE, 0},         /* pre-v6.1 "Undefined Reltime" */
        {"s", UNITS, DTK_SECOND},
        {"sec", UNITS, DTK_SECOND},
        {DSECOND, UNITS, DTK_SECOND},
        {"seconds", UNITS, DTK_SECOND},
        {"secs", UNITS, DTK_SECOND},
-       {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
+       {DTIMEZONE, UNITS, DTK_TZ},                     /* "timezone" time offset */
        {"timezone", UNITS, DTK_TZ},            /* "timezone" time offset */
        {"timezone_h", UNITS, DTK_TZ_HOUR},             /* timezone hour units */
        {"timezone_m", UNITS, DTK_TZ_MINUTE},   /* timezone minutes units */
        {"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
-       {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
-       {"usec", UNITS, DTK_MICROSEC},          /* "microsecond" relative time
-                                                                                * units */
-       {DMICROSEC, UNITS, DTK_MICROSEC},       /* "microsecond" relative time
-                                                                                * units */
-       {"useconds", UNITS, DTK_MICROSEC},      /* "microseconds" relative time
-                                                                                * units */
-       {"usecs", UNITS, DTK_MICROSEC},         /* "microseconds" relative time
-                                                                                * units */
-       {"w", UNITS, DTK_WEEK},         /* "week" relative time units */
-       {DWEEK, UNITS, DTK_WEEK},       /* "week" relative time units */
-       {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */
-       {"y", UNITS, DTK_YEAR},         /* "year" relative time units */
-       {DYEAR, UNITS, DTK_YEAR},       /* "year" relative time units */
-       {"years", UNITS, DTK_YEAR}, /* "years" relative time units */
-       {"yr", UNITS, DTK_YEAR},        /* "year" relative time units */
-       {"yrs", UNITS, DTK_YEAR},       /* "years" relative time units */
+       {"us", UNITS, DTK_MICROSEC},            /* "microsecond" relative */
+       {"usec", UNITS, DTK_MICROSEC},          /* "microsecond" relative */
+       {DMICROSEC, UNITS, DTK_MICROSEC},       /* "microsecond" relative */
+       {"useconds", UNITS, DTK_MICROSEC},      /* "microseconds" relative */
+       {"usecs", UNITS, DTK_MICROSEC},         /* "microseconds" relative */
+       {"w", UNITS, DTK_WEEK},         /* "week" relative */
+       {DWEEK, UNITS, DTK_WEEK},       /* "week" relative */
+       {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
+       {"y", UNITS, DTK_YEAR},         /* "year" relative */
+       {DYEAR, UNITS, DTK_YEAR},       /* "year" relative */
+       {"years", UNITS, DTK_YEAR}, /* "years" relative */
+       {"yr", UNITS, DTK_YEAR},        /* "year" relative */
+       {"yrs", UNITS, DTK_YEAR},       /* "years" relative */
 };
 
 static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
@@ -346,8 +339,10 @@ date2j(int y, int m, int d)
 {
        int                     m12 = (m - 14) / 12;
 
-       return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12
-                       - (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075);
+       return ((1461 * (y + 4800 + m12)) / 4
+                       + (367 * (m - 2 - 12 * (m12))) / 12
+                       - (3 * ((y + 4900 + m12) / 100)) / 4
+                       + d - 32075);
 }      /* date2j() */
 
 void
@@ -390,11 +385,28 @@ j2day(int date)
 }      /* j2day() */
 
 
-/*
- * parse and convert date in timestr (the normal interface)
- *
- * Returns the number of seconds since epoch (J2000)
- */
+void
+TrimTrailingZeros(char *str)
+{
+       int len = strlen(str);
+
+       /* chop off trailing one to cope with interval rounding */
+       if (strcmp((str + len - 4), "0001") == 0)
+       {
+               len -= 4;
+               *(str + len) = '\0';
+       }
+
+       /* chop off trailing zeros... */
+       while ((*(str + len - 1) == '0')
+                  && (*(str + len - 3) != '.'))
+       {
+               len--;
+               *(str + len) = '\0';
+       }
+       return;
+}
+
 
 /* ParseDateTime()
  * Break string into tokens based on a date/time context.
@@ -989,7 +1001,11 @@ DetermineLocalTimeZone(struct tm * tm)
 {
        int                     tz;
 
-       if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+       if (HasCTZSet)
+       {
+               tz = CTimeZone;
+       }
+       else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
        {
 #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
                /*
@@ -1044,9 +1060,6 @@ DetermineLocalTimeZone(struct tm * tm)
  * SQL92 TIME WITH TIME ZONE, but it reveals
  * bogosity with SQL92 date/time standards, since
  * we must infer a time zone from current time.
- * XXX Later, we should probably support
- * SET TIME ZONE <integer>
- * which of course is a screwed up convention.
  * - thomas 2000-03-10
  */
 int
@@ -2246,33 +2259,23 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
                                 */
                                if (fsec != 0) {
                                        sprintf((str + strlen(str)), ":%013.10f", sec);
-                                       /* chop off trailing pairs of zeros... */
-                                       while ((strcmp((str + strlen(str) - 2), "00") == 0)
-                                                  && (*(str + strlen(str) - 3) != '.'))
-                                       {
-                                               *(str + strlen(str) - 2) = '\0';
-                                       }
+                                       TrimTrailingZeros(str);
                                }
                                else
                                {
                                        sprintf((str + strlen(str)), ":%02.0f", sec);
                                }
 
-                               if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+                               /* tzp == NULL indicates that we don't want *any* time zone info in the output string.
+                                * *tzn != NULL indicates that we *have* time zone info available.
+                                * tm_isdst != -1 indicates that we have a valid time zone translation.
+                                */
+                               if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
                                {
-                                       if (tzp != NULL)
-                                       {
-                                               hour = -(*tzp / 3600);
-                                               min = ((abs(*tzp) / 60) % 60);
-                                       }
-                                       else
-                                       {
-                                               hour = 0;
-                                               min = 0;
-                                       }
+                                       hour = -(*tzp / 3600);
+                                       min = ((abs(*tzp) / 60) % 60);
                                        sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
                                }
-
                        }
                        else
                        {
@@ -2305,12 +2308,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
                                 */
                                if (fsec != 0) {
                                        sprintf((str + strlen(str)), ":%013.10f", sec);
-                                       /* chop off trailing pairs of zeros... */
-                                       while ((strcmp((str + strlen(str) - 2), "00") == 0)
-                                                  && (*(str + strlen(str) - 3) != '.'))
-                                       {
-                                               *(str + strlen(str) - 2) = '\0';
-                                       }
+                                       TrimTrailingZeros(str);
                                }
                                else
                                {
@@ -2319,6 +2317,13 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
 
                                if ((*tzn != NULL) && (tm->tm_isdst >= 0))
                                        sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+                               else if (tzp != NULL)
+                               {
+                                       hour = -(*tzp / 3600);
+                                       min = ((abs(*tzp) / 60) % 60);
+                                       sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+                               }
                        }
                        else
                                sprintf((str + 5), "/%04d %02d:%02d %s",
@@ -2341,12 +2346,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
                                 */
                                if (fsec != 0) {
                                        sprintf((str + strlen(str)), ":%013.10f", sec);
-                                       /* chop off trailing pairs of zeros... */
-                                       while ((strcmp((str + strlen(str) - 2), "00") == 0)
-                                                  && (*(str + strlen(str) - 3) != '.'))
-                                       {
-                                               *(str + strlen(str) - 2) = '\0';
-                                       }
+                                       TrimTrailingZeros(str);
                                }
                                else
                                {
@@ -2355,6 +2355,13 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
 
                                if ((*tzn != NULL) && (tm->tm_isdst >= 0))
                                        sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+                               else if (tzp != NULL)
+                               {
+                                       hour = -(*tzp / 3600);
+                                       min = ((abs(*tzp) / 60) % 60);
+                                       sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+                               }
                        }
                        else
                                sprintf((str + 5), ".%04d %02d:%02d %s",
@@ -2387,12 +2394,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
                                 */
                                if (fsec != 0) {
                                        sprintf((str + strlen(str)), ":%013.10f", sec);
-                                       /* chop off trailing pairs of zeros... */
-                                       while ((strcmp((str + strlen(str) - 2), "00") == 0)
-                                                  && (*(str + strlen(str) - 3) != '.'))
-                                       {
-                                               *(str + strlen(str) - 2) = '\0';
-                                       }
+                                       TrimTrailingZeros(str);
                                }
                                else
                                {
@@ -2400,8 +2402,16 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
                                }
 
                                sprintf((str + strlen(str)), " %04d", tm->tm_year);
-                               if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+
+                               if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
                                        sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+                               else if (HasCTZSet && (tzp != NULL))
+                               {
+                                       hour = -(*tzp / 3600);
+                                       min = ((abs(*tzp) / 60) % 60);
+                                       sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+                               }
                        }
                        else
                        {
@@ -2485,12 +2495,12 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
                                if (fsec != 0)
                                {
                                        fsec += tm->tm_sec;
-                                       sprintf(cp, ":%05.2f", fabs(fsec));
+                                       sprintf(cp, ":%013.10f", fabs(fsec));
+                                       TrimTrailingZeros(cp);
                                        cp += strlen(cp);
                                        is_nonzero = TRUE;
-
-                                       /* otherwise, integer seconds only? */
                                }
+                               /* otherwise, integer seconds only? */
                                else if (tm->tm_sec != 0)
                                {
                                        sprintf(cp, ":%02d", abs(tm->tm_sec));
index b7ac078..cd8a778 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.87 2001/10/01 02:31:33 ishii Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.88 2001/10/18 17:30:15 thomas Exp $
  *
  * NOTES
  *
@@ -113,7 +113,7 @@ static int istinterval(char *i_string,
 
 /* GetCurrentAbsoluteTime()
  * Get the current system time. Set timezone parameters if not specified elsewhere.
- * Define HasTZSet to allow clients to specify the default timezone.
+ * Define HasCTZSet to allow clients to specify the default timezone.
  *
  * Returns the number of seconds since epoch (January 1 1970 GMT)
  */
@@ -173,7 +173,7 @@ GetCurrentAbsoluteTime(void)
                 */
                strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
 #endif
-       };
+       }
 
        return (AbsoluteTime) now;
 }      /* GetCurrentAbsoluteTime() */
@@ -181,7 +181,7 @@ GetCurrentAbsoluteTime(void)
 
 /* GetCurrentAbsoluteTime()
  * Get the current system time. Set timezone parameters if not specified elsewhere.
- * Define HasTZSet to allow clients to specify the default timezone.
+ * Define HasCTZSet to allow clients to specify the default timezone.
  *
  * Returns the number of seconds since epoch (January 1 1970 GMT)
  */
@@ -284,7 +284,7 @@ GetCurrentTimeUsec(struct tm *tm, double *fsec)
 
 
 void
-abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char *tzn)
+abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
 {
        time_t          time = (time_t) _time;
 
@@ -297,9 +297,15 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char *tzn)
        ftime(&tb);
 #endif
 
+       /* If HasCTZSet is true then we have a brute force time zone specified.
+        * Go ahead and rotate to the local time zone since we will later bypass
+        * any calls which adjust the tm fields.
+        */
+       if (HasCTZSet && (tzp != NULL))
+               time -= CTimeZone;
 
 #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
-       if (tzp != NULL)
+       if ((! HasCTZSet) && (tzp != NULL))
        {
                tx = localtime((time_t *) &time);
 #ifdef NO_MKTIME_BEFORE_1970
@@ -329,47 +335,95 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char *tzn)
        tm->tm_zone = tx->tm_zone;
 
        if (tzp != NULL)
-               *tzp = -tm->tm_gmtoff;  /* tm_gmtoff is Sun/DEC-ism */
-       /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
-       if (tzn != NULL)
        {
-
-               /*
-                * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
-                * contains an error message, which doesn't fit in the buffer
+               /* We have a brute force time zone per SQL99?
+                * Then use it without change
+                * since we have already rotated to the time zone.
                 */
-               StrNCpy(tzn, tm->tm_zone, MAXTZLEN + 1);
-               if (strlen(tm->tm_zone) > MAXTZLEN)
-                       elog(NOTICE, "Invalid timezone \'%s\'", tm->tm_zone);
+               if (HasCTZSet)
+               {
+                       *tzp = CTimeZone;
+                       tm->tm_gmtoff = CTimeZone;
+                       tm->tm_isdst = -1;
+                       tm->tm_zone = NULL;
+                       if (tzn != NULL)
+                               *tzn = NULL;
+               }
+               else
+               {
+                       *tzp = -tm->tm_gmtoff;  /* tm_gmtoff is Sun/DEC-ism */
+
+                       /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
+                       if (tzn != NULL)
+                       {
+                               /*
+                                * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
+                                * contains an error message, which doesn't fit in the buffer
+                                */
+                               StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);
+                               if (strlen(tm->tm_zone) > MAXTZLEN)
+                                       elog(NOTICE, "Invalid timezone \'%s\'", tm->tm_zone);
+                       }
+               }
        }
 #elif defined(HAVE_INT_TIMEZONE)
        if (tzp != NULL)
-               *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
-
-       if (tzn != NULL)
-       {
-
-               /*
-                * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
-                * contains an error message, which doesn't fit in the buffer
+               /* We have a brute force time zone per SQL99?
+                * Then use it without change
+                * since we have already rotated to the time zone.
                 */
-               StrNCpy(tzn, tzname[tm->tm_isdst], MAXTZLEN + 1);
-               if (strlen(tzname[tm->tm_isdst]) > MAXTZLEN)
-                       elog(NOTICE, "Invalid timezone \'%s\'", tzname[tm->tm_isdst]);
+               if (HasCTZSet)
+               {
+                       *tzp = CTimeZone;
+                       tm->tm_isdst = -1;
+                       if (tzn != NULL)
+                               *tzn = NULL;
+               }
+               else
+               {
+                       *tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
+
+                       if (tzn != NULL)
+                       {
+
+                               /*
+                                * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
+                                * contains an error message, which doesn't fit in the buffer
+                                */
+                               StrNCpy(*tzn, tzname[tm->tm_isdst], MAXTZLEN + 1);
+                               if (strlen(tzname[tm->tm_isdst]) > MAXTZLEN)
+                                       elog(NOTICE, "Invalid timezone \'%s\'", tzname[tm->tm_isdst]);
+                       }
+               }
        }
 #endif
 #else                                                  /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
        if (tzp != NULL)
-               *tzp = tb.timezone * 60;
-
-       /*
-        * XXX does this work to get the local timezone string in V7? - tgl
-        * 97/03/18
-        */
-       if (tzn != NULL)
        {
-               strftime(tzn, MAXTZLEN, "%Z", localtime(&now));
-               tzn[MAXTZLEN] = '\0';   /* let's just be sure it's null-terminated */
+               /* We have a brute force time zone per SQL99?
+                * Then use it without change
+                * since we have already rotated to the time zone.
+                */
+               if (HasCTZSet)
+               {
+                       *tzp = CTimeZone;
+                       if (tzn != NULL)
+                               *tzn = NULL;
+               }
+               else
+               {
+                       *tzp = tb.timezone * 60;
+
+                       /*
+                        * XXX does this work to get the local timezone string in V7? - tgl
+                        * 97/03/18
+                        */
+                       if (tzn != NULL)
+                       {
+                               strftime(*tzn, MAXTZLEN, "%Z", localtime(&now));
+                               tzn[MAXTZLEN] = '\0';   /* let's just be sure it's null-terminated */
+                       }
+               }
        }
 #endif
 
@@ -508,7 +562,7 @@ nabstimeout(PG_FUNCTION_ARGS)
                        strcpy(buf, EARLY);
                        break;
                default:
-                       abstime2tm(time, &tz, tm, tzn);
+                       abstime2tm(time, &tz, tm, &tzn);
                        EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
                        break;
        }
@@ -676,7 +730,8 @@ abstime_timestamp(PG_FUNCTION_ARGS)
        struct tm       tt,
                           *tm = &tt;
        int                     tz;
-       char            tzn[MAXTZLEN];
+       char            zone[MAXDATELEN + 1],
+                          *tzn = zone;
 
        switch (abstime)
        {
@@ -694,7 +749,7 @@ abstime_timestamp(PG_FUNCTION_ARGS)
                        break;
 
                default:
-                       abstime2tm(abstime, &tz, tm, tzn);
+                       abstime2tm(abstime, &tz, tm, &tzn);
                        result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400) + tz;
                        break;
        };
index 6eeb349..13ad90e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.55 2001/10/05 06:38:59 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.56 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@ static double time2t(const int hour, const int min, const double sec);
 static int     EncodeSpecialTimestamp(Timestamp dt, char *str);
 static Timestamp dt2local(Timestamp dt, int timezone);
 static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
+static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);
 
 
 /*****************************************************************************
@@ -69,7 +70,7 @@ timestamp_in(PG_FUNCTION_ARGS)
        {
                case DTK_DATE:
                        if (tm2timestamp(tm, fsec, NULL, &result) != 0)
-                               elog(ERROR, "Timestamp out of range '%s'", str);
+                               elog(ERROR, "TIMESTAMP out of range '%s'", str);
                        break;
 
                case DTK_EPOCH:
@@ -85,12 +86,12 @@ timestamp_in(PG_FUNCTION_ARGS)
                        break;
 
                case DTK_INVALID:
-                       elog(ERROR, "Timestamp '%s' no longer supported", str);
+                       elog(ERROR, "TIMESTAMP '%s' no longer supported", str);
                        TIMESTAMP_NOEND(result);
                        break;
 
                default:
-                       elog(ERROR, "Timestamp '%s' not parsed; internal coding error", str);
+                       elog(ERROR, "TIMESTAMP '%s' not parsed; internal coding error", str);
                        TIMESTAMP_NOEND(result);
        }
 
@@ -157,7 +158,7 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
                        TimestampTypmod = typmod;
                }
 
-               *time = (rint(((double) *time)*TimestampScale)/TimestampScale);
+               *time = (rint(((double) *time) * TimestampScale)/TimestampScale);
        }
 }
 
@@ -192,7 +193,7 @@ timestamptz_in(PG_FUNCTION_ARGS)
        {
                case DTK_DATE:
                        if (tm2timestamp(tm, fsec, &tz, &result) != 0)
-                               elog(ERROR, "Timestamp out of range '%s'", str);
+                               elog(ERROR, "TIMESTAMP WITH TIME ZONE out of range '%s'", str);
                        break;
 
                case DTK_EPOCH:
@@ -208,12 +209,12 @@ timestamptz_in(PG_FUNCTION_ARGS)
                        break;
 
                case DTK_INVALID:
-                       elog(ERROR, "Timestamp with time zone '%s' no longer supported", str);
+                       elog(ERROR, "TIMESTAMP WITH TIME ZONE '%s' no longer supported", str);
                        TIMESTAMP_NOEND(result);
                        break;
 
                default:
-                       elog(ERROR, "Timestamp with time zone '%s' not parsed; internal coding error", str);
+                       elog(ERROR, "TIMESTAMP WITH TIME ZONE '%s' not parsed; internal coding error", str);
                        TIMESTAMP_NOEND(result);
        }
 
@@ -277,6 +278,10 @@ Datum
 interval_in(PG_FUNCTION_ARGS)
 {
        char       *str = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
        Interval   *result;
        double          fsec;
        struct tm       tt,
@@ -306,6 +311,7 @@ interval_in(PG_FUNCTION_ARGS)
                case DTK_DELTA:
                        if (tm2interval(tm, fsec, result) != 0)
                                elog(ERROR, "Bad interval external representation '%s'", str);
+                       AdjustIntervalForTypmod(result, typmod);
                        break;
 
                case DTK_INVALID:
@@ -342,6 +348,148 @@ interval_out(PG_FUNCTION_ARGS)
        PG_RETURN_CSTRING(result);
 }
 
+/* interval_scale()
+ * Adjust interval type for specified fields.
+ * Used by PostgreSQL type system to stuff columns.
+ */
+Datum
+interval_scale(PG_FUNCTION_ARGS)
+{
+       Interval   *interval = PG_GETARG_INTERVAL_P(0);
+       int32           typmod = PG_GETARG_INT32(1);
+       Interval   *result;
+
+       result = palloc(sizeof(Interval));
+       *result = *interval;
+
+       AdjustIntervalForTypmod(result, typmod);
+
+       PG_RETURN_INTERVAL_P(result);
+}
+
+#define MASK(b) (1 << (b))
+
+static void
+AdjustIntervalForTypmod(Interval *interval, int32 typmod)
+{
+       if (typmod != -1)
+       {
+               int range = ((typmod >> 16) & 0xFFFF);
+               int precision = (typmod & 0xFFFF);
+
+               if (range == 0xFFFF)
+               {
+                       /* Do nothing... */
+               }
+               if (range == MASK(YEAR))
+               {
+                       interval->month = ((interval->month / 12) * 12);
+                       interval->time = 0;
+               }
+               else if (range == MASK(MONTH))
+               {
+                       interval->month %= 12;
+                       interval->time = 0;
+               }
+               /* YEAR TO MONTH */
+               else if (range  == (MASK(YEAR) | MASK(MONTH)))
+               {
+                       interval->time = 0;
+               }
+               else if (range == MASK(DAY))
+               {
+                       interval->month = 0;
+                       interval->time = (((int)(interval->time / 86400)) * 86400);
+               }
+               else if (range == MASK(HOUR))
+               {
+                       double day;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, day, 86400.0);
+                       interval->time = (((int)(interval->time / 3600)) * 3600.0);
+               }
+               else if (range == MASK(MINUTE))
+               {
+                       double hour;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, hour, 3600.0);
+                       interval->time = (((int)(interval->time / 60)) * 60);
+               }
+               else if (range == MASK(SECOND))
+               {
+                       double hour;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, hour, 60.0);
+//                     interval->time = (int)(interval->time);
+               }
+               /* DAY TO HOUR */
+               else if (range == (MASK(DAY) | MASK(HOUR)))
+               {
+                       interval->month = 0;
+                       interval->time = (((int)(interval->time / 3600)) * 3600);
+               }
+               /* DAY TO MINUTE */
+               else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE)))
+               {
+                       interval->month = 0;
+                       interval->time = (((int)(interval->time / 60)) * 60);
+               }
+               /* DAY TO SECOND */
+               else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
+               {
+                       interval->month = 0;
+               }
+               /* HOUR TO MINUTE */
+               else if (range == (MASK(HOUR) | MASK(MINUTE)))
+               {
+                       double day;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, day, 86400.0);
+                       interval->time = (((int)(interval->time / 60)) * 60);
+               }
+               /* HOUR TO SECOND */
+               else if (range == (MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
+               {
+                       double day;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, day, 86400.0);
+               }
+               /* MINUTE TO SECOND */
+               else if (range == (MASK(MINUTE) | MASK(SECOND)))
+               {
+                       double hour;
+
+                       interval->month = 0;
+                       TMODULO(interval->time, hour, 3600.0);
+               }
+               else
+               {
+                       elog(ERROR, "AdjustIntervalForTypmod(): internal coding error");
+               }
+
+               if (precision != 0xFFFF)
+               {
+                       static double IntervalScale = 1;
+                       static int IntervalTypmod = 0;
+
+                       if (precision != IntervalTypmod)
+                       {
+                               IntervalTypmod = precision;
+                               IntervalScale = pow(10.0, IntervalTypmod);
+                       }
+
+                       interval->time = (rint(interval->time * IntervalScale) / IntervalScale);
+               }
+       }
+
+       return;
+}
+
 
 /* EncodeSpecialTimestamp()
  * Convert reserved timestamp data type to string.
@@ -417,6 +565,13 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 
        date0 = date2j(2000, 1, 1);
 
+       /* If HasCTZSet is true then we have a brute force time zone specified.
+        * Go ahead and rotate to the local time zone since we will later bypass
+        * any calls which adjust the tm fields.
+        */
+       if (HasCTZSet && (tzp != NULL))
+               dt -= CTimeZone;
+
        time = dt;
        TMODULO(time, date, 86400e0);
 
@@ -441,7 +596,24 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 
        if (tzp != NULL)
        {
-               if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+               /* We have a brute force time zone per SQL99?
+                * Then use it without change
+                * since we have already rotated to the time zone.
+                */
+               if (HasCTZSet)
+               {
+                       *tzp = CTimeZone;
+                       tm->tm_gmtoff = CTimeZone;
+                       tm->tm_isdst = 0;
+                       tm->tm_zone = NULL;
+                       if (tzn != NULL)
+                               *tzn = NULL;
+               }
+
+               /* Does this fall within the capabilities of the localtime() interface?
+                * Then use this to rotate to the local time zone.
+                */
+               else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
                {
                        utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
 
@@ -492,6 +664,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
                                *tzn = CTZName;
 #endif
 
+                       dt = dt2local(dt, *tzp);
                }
                else
                {
@@ -500,9 +673,6 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
                        if (tzn != NULL)
                                *tzn = NULL;
                }
-
-               dt = dt2local(dt, *tzp);
-
        }
        else
        {
@@ -1072,14 +1242,14 @@ timestamp_pl_span(PG_FUNCTION_ARGS)
 
                                if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
                                {
-                                       elog(ERROR, "Unable to add timestamp and interval"
+                                       elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
                                                 "\n\ttimestamp_pl_span() internal error encoding timestamp");
                                        PG_RETURN_NULL();
                                }
                        }
                        else
                        {
-                               elog(ERROR, "Unable to add timestamp and interval"
+                               elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
                                         "\n\ttimestamp_pl_span() internal error decoding timestamp");
                                PG_RETURN_NULL();
                        }
@@ -1164,12 +1334,12 @@ timestamptz_pl_span(PG_FUNCTION_ARGS)
                                tz = DetermineLocalTimeZone(tm);
 
                                if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
-                                       elog(ERROR, "Unable to add timestamp and interval"
+                                       elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
                                                "\n\ttimestamptz_pl_span() internal error encoding timestamp");
                        }
                        else
                        {
-                               elog(ERROR, "Unable to add timestamp and interval"
+                               elog(ERROR, "Unable to add TIMESTAMP and INTERVAL"
                                         "\n\ttimestamptz_pl_span() internal error decoding timestamp");
                        }
                }
@@ -1546,11 +1716,11 @@ timestamp_age(PG_FUNCTION_ARGS)
                }
 
                if (tm2interval(tm, fsec, result) != 0)
-                       elog(ERROR, "Unable to encode interval"
+                       elog(ERROR, "Unable to encode INTERVAL"
                                 "\n\ttimestamp_age() internal coding error");
        }
        else
-               elog(ERROR, "Unable to decode timestamp"
+               elog(ERROR, "Unable to decode TIMESTAMP"
                         "\n\ttimestamp_age() internal coding error");
 
        PG_RETURN_INTERVAL_P(result);
@@ -1655,10 +1825,10 @@ timestamptz_age(PG_FUNCTION_ARGS)
                }
 
                if (tm2interval(tm, fsec, result) != 0)
-                       elog(ERROR, "Unable to decode timestamp");
+                       elog(ERROR, "Unable to decode TIMESTAMP");
        }
        else
-               elog(ERROR, "Unable to decode timestamp");
+               elog(ERROR, "Unable to decode TIMESTAMP");
 
        PG_RETURN_INTERVAL_P(result);
 }
@@ -1711,7 +1881,7 @@ text_timestamp(PG_FUNCTION_ARGS)
                                dstr[MAXDATELEN + 1];
 
        if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Bad timestamp external representation (too long)");
+               elog(ERROR, "TIMESTAMP bad external representation (too long)");
 
        sp = VARDATA(str);
        dp = dstr;
@@ -1767,7 +1937,7 @@ text_timestamptz(PG_FUNCTION_ARGS)
                                dstr[MAXDATELEN + 1];
 
        if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Bad timestamp with time zone external representation (too long)");
+               elog(ERROR, "TIMESTAMP WITH TIME ZONE bad external representation (too long)");
 
        sp = VARDATA(str);
        dp = dstr;
@@ -1824,14 +1994,17 @@ text_interval(PG_FUNCTION_ARGS)
                                dstr[MAXDATELEN + 1];
 
        if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Bad interval external representation (too long)");
+               elog(ERROR, "INTERVAL bad external representation (too long)");
        sp = VARDATA(str);
        dp = dstr;
        for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
                *dp++ = *sp++;
        *dp = '\0';
 
-       return DirectFunctionCall1(interval_in, CStringGetDatum(dstr));
+       return DirectFunctionCall3(interval_in,
+                                                          CStringGetDatum(dstr),
+                                                          ObjectIdGetDatum(InvalidOid),
+                                                          Int32GetDatum(-1));
 }
 
 /* timestamp_trunc()
@@ -1854,7 +2027,7 @@ timestamp_trunc(PG_FUNCTION_ARGS)
                           *tm = &tt;
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "TIMESTAMP units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
        up = VARDATA(units);
@@ -1903,16 +2076,16 @@ timestamp_trunc(PG_FUNCTION_ARGS)
                                break;
 
                        default:
-                               elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
                                result = 0;
                }
 
                if (tm2timestamp(tm, fsec, NULL, &result) != 0)
-                       elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits);
+                       elog(ERROR, "Unable to truncate TIMESTAMP to '%s'", lowunits);
        }
        else
        {
-               elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+               elog(ERROR, "TIMESTAMP units '%s' not recognized", lowunits);
                result = 0;
        }
 
@@ -1941,7 +2114,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
                           *tm = &tt;
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
        up = VARDATA(units);
@@ -1984,24 +2157,23 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
                        case DTK_MILLISEC:
                                fsec = rint(fsec * 1000) / 1000;
                                break;
-
                        case DTK_MICROSEC:
                                fsec = rint(fsec * 1000000) / 1000000;
                                break;
 
                        default:
-                               elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
                                result = 0;
                }
 
                tz = DetermineLocalTimeZone(tm);
 
                if (tm2timestamp(tm, fsec, &tz, &result) != 0)
-                       elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits);
+                       elog(ERROR, "Unable to truncate TIMESTAMP WITH TIME ZONE to '%s'", lowunits);
        }
        else
        {
-               elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized", lowunits);
                PG_RETURN_NULL();
        }
 
@@ -2030,7 +2202,7 @@ interval_trunc(PG_FUNCTION_ARGS)
        result = (Interval *) palloc(sizeof(Interval));
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "INTERVAL units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
        up = VARDATA(units);
@@ -2078,22 +2250,22 @@ interval_trunc(PG_FUNCTION_ARGS)
                                        break;
 
                                default:
-                                       elog(ERROR, "Interval units '%s' not supported", lowunits);
+                                       elog(ERROR, "INTERVAL units '%s' not supported", lowunits);
                        }
 
                        if (tm2interval(tm, fsec, result) != 0)
-                               elog(ERROR, "Unable to truncate interval to '%s'", lowunits);
+                               elog(ERROR, "Unable to truncate INTERVAL to '%s'", lowunits);
 
                }
                else
                {
-                       elog(NOTICE, "Unable to decode interval; internal coding error");
+                       elog(NOTICE, "Unable to decode INTERVAL; internal coding error");
                        *result = *interval;
                }
        }
        else
        {
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "INTERVAL units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
                *result = *interval;
@@ -2202,7 +2374,7 @@ timestamp_part(PG_FUNCTION_ARGS)
                           *tm = &tt;
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "TIMESTAMP units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
        up = VARDATA(units);
@@ -2212,7 +2384,7 @@ timestamp_part(PG_FUNCTION_ARGS)
        *lp = '\0';
 
        type = DecodeUnits(0, lowunits, &val);
-       if (type == IGNORE)
+       if (type == UNKNOWN_FIELD)
                type = DecodeSpecial(0, lowunits, &val);
 
        if (TIMESTAMP_NOT_FINITE(timestamp))
@@ -2221,7 +2393,8 @@ timestamp_part(PG_FUNCTION_ARGS)
                PG_RETURN_FLOAT8(result);
        }
 
-       if ((type == UNITS) && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0))
+       if ((type == UNITS)
+               && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0))
        {
                switch (val)
                {
@@ -2281,7 +2454,7 @@ timestamp_part(PG_FUNCTION_ARGS)
                        case DTK_TZ_MINUTE:
                        case DTK_TZ_HOUR:
                        default:
-                               elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
                                result = 0;
                }
        }
@@ -2295,28 +2468,28 @@ timestamp_part(PG_FUNCTION_ARGS)
 
                        case DTK_DOW:
                                if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
-                                       elog(ERROR, "Unable to encode timestamp");
+                                       elog(ERROR, "Unable to encode TIMESTAMP");
 
                                result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
                                break;
 
                        case DTK_DOY:
                                if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
-                                       elog(ERROR, "Unable to encode timestamp");
+                                       elog(ERROR, "Unable to encode TIMESTAMP");
 
                                result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
                                                  - date2j(tm->tm_year, 1, 1) + 1);
                                break;
 
                        default:
-                               elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP units '%s' not supported", lowunits);
                                result = 0;
                }
 
        }
        else
        {
-               elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+               elog(ERROR, "TIMESTAMP units '%s' not recognized", lowunits);
                result = 0;
        }
 
@@ -2346,7 +2519,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
                           *tm = &tt;
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                           PointerGetDatum(units))));
        up = VARDATA(units);
@@ -2356,7 +2529,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
        *lp = '\0';
 
        type = DecodeUnits(0, lowunits, &val);
-       if (type == IGNORE)
+       if (type == UNKNOWN_FIELD)
                type = DecodeSpecial(0, lowunits, &val);
 
        if (TIMESTAMP_NOT_FINITE(timestamp))
@@ -2436,7 +2609,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
                                break;
 
                        default:
-                               elog(ERROR, "Timestamp with time zone units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
                                result = 0;
                }
 
@@ -2451,27 +2624,27 @@ timestamptz_part(PG_FUNCTION_ARGS)
 
                        case DTK_DOW:
                                if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
-                                       elog(ERROR, "Unable to encode timestamp with time zone");
+                                       elog(ERROR, "Unable to encode TIMESTAMP WITH TIME ZONE");
 
                                result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
                                break;
 
                        case DTK_DOY:
                                if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
-                                       elog(ERROR, "Unable to encode timestamp with time zone");
+                                       elog(ERROR, "Unable to encode TIMESTAMP WITH TIME ZONE");
 
                                result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
                                                  - date2j(tm->tm_year, 1, 1) + 1);
                                break;
 
                        default:
-                               elog(ERROR, "Timestamp with time zone units '%s' not supported", lowunits);
+                               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not supported", lowunits);
                                result = 0;
                }
        }
        else
        {
-               elog(ERROR, "Timestamp with time zone units '%s' not recognized", lowunits);
+               elog(ERROR, "TIMESTAMP WITH TIME ZONE units '%s' not recognized", lowunits);
                result = 0;
        }
 
@@ -2499,7 +2672,7 @@ interval_part(PG_FUNCTION_ARGS)
                           *tm = &tt;
 
        if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "INTERVAL units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                           PointerGetDatum(units))));
        up = VARDATA(units);
@@ -2509,7 +2682,7 @@ interval_part(PG_FUNCTION_ARGS)
        *lp = '\0';
 
        type = DecodeUnits(0, lowunits, &val);
-       if (type == IGNORE)
+       if (type == UNKNOWN_FIELD)
                type = DecodeSpecial(0, lowunits, &val);
 
        if (type == UNITS)
@@ -2567,7 +2740,7 @@ interval_part(PG_FUNCTION_ARGS)
                                        break;
 
                                default:
-                                       elog(ERROR, "Interval units '%s' not supported",
+                                       elog(ERROR, "INTERVAL units '%s' not supported",
                                                 DatumGetCString(DirectFunctionCall1(textout,
                                                                                                                         PointerGetDatum(units))));
                                        result = 0;
@@ -2576,7 +2749,7 @@ interval_part(PG_FUNCTION_ARGS)
                }
                else
                {
-                       elog(NOTICE, "Unable to decode interval"
+                       elog(NOTICE, "Unable to decode INTERVAL"
                                 "\n\tinterval_part() internal coding error");
                        result = 0;
                }
@@ -2592,7 +2765,7 @@ interval_part(PG_FUNCTION_ARGS)
        }
        else
        {
-               elog(ERROR, "Interval units '%s' not recognized",
+               elog(ERROR, "INTERVAL units '%s' not recognized",
                         DatumGetCString(DirectFunctionCall1(textout,
                                                                                                 PointerGetDatum(units))));
                result = 0;
@@ -2695,12 +2868,12 @@ timestamp_timestamptz(PG_FUNCTION_ARGS)
        else
        {
                if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
-                       elog(ERROR, "Unable to convert timestamp to timestamp with time zone (tm)");
+                       elog(ERROR, "Unable to convert TIMESTAMP to TIMESTAMP WITH TIME ZONE (tm)");
 
                tz = DetermineLocalTimeZone(tm);
 
                if (tm2timestamp(tm, fsec, &tz, &result) != 0)
-                       elog(ERROR, "Unable to convert timestamp to timestamp with time zone");
+                       elog(ERROR, "Unable to convert TIMESTAMP to TIMESTAMP WITH TIME ZONE");
        }
 
        PG_RETURN_TIMESTAMPTZ(result);
@@ -2727,10 +2900,10 @@ timestamptz_timestamp(PG_FUNCTION_ARGS)
        else
        {
                if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
-                       elog(ERROR, "Unable to convert timestamp with time zone to timestamp (tm)");
+                       elog(ERROR, "Unable to convert TIMESTAMP WITH TIME ZONE to TIMESTAMP (tm)");
 
                if (tm2timestamp(tm, fsec, NULL, &result) != 0)
-                       elog(ERROR, "Unable to convert timestamp with time zone to timestamp");
+                       elog(ERROR, "Unable to convert TIMESTAMP WITH TIME ZONE to TIMESTAMP");
        }
 
        PG_RETURN_TIMESTAMP(result);
@@ -2784,8 +2957,8 @@ timestamptz_zone(PG_FUNCTION_ARGS)
                dt = dt2local(timestamp, tz);
 
                if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
-                       elog(ERROR, "Unable to decode timestamp"
-                                "\n\ttimestamp_zone() internal coding error");
+                       elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
+                                "\n\ttimestamptz_zone() internal coding error");
 
                up = upzone;
                lp = lowzone;
@@ -2845,8 +3018,8 @@ timestamptz_izone(PG_FUNCTION_ARGS)
        dt = dt2local(timestamp, tz);
 
        if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
-               elog(ERROR, "Unable to decode timestamp"
-                       "\n\ttimestamp_izone() internal coding error");
+               elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
+                       "\n\ttimestamptz_izone() internal coding error");
 
        EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
        len = (strlen(buf) + VARHDRSZ);
index be5e9db..557e076 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xact.h,v 1.37 2001/09/28 08:09:12 thomas Exp $
+ * $Id: xact.h,v 1.38 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,7 +40,7 @@ typedef struct TransactionStateData
        CommandId       commandId;
        CommandId       scanCommandId;
        AbsoluteTime startTime;
-       int                     startTimeMsec;
+       int                     startTimeUsec;
        int                     state;
        int                     blockState;
 } TransactionStateData;
index 790bb6c..92eb196 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.98 2001/10/03 17:22:05 tgl Exp $
+ * $Id: catversion.h,v 1.99 2001/10/18 17:30:15 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200110031
+#define CATALOG_VERSION_NO     200110181
 
 #endif
index 7f179d9..5efc7be 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.216 2001/10/12 02:08:34 ishii Exp $
+ * $Id: pg_proc.h,v 1.217 2001/10/18 17:30:15 thomas Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -1434,7 +1434,6 @@ DATA(insert OID = 1171 (  date_part                  PGUID 12 f t f t 2 f  701 "25 1184" 100
 DESCR("extract field from timestamp with time zone");
 DATA(insert OID = 1172 (  date_part               PGUID 12 f t t t 2 f  701 "25 1186" 100 0 0 100  interval_part - ));
 DESCR("extract field from interval");
-
 DATA(insert OID = 1173 (  timestamptz     PGUID 12 f t f t 1 f 1184 "702" 100 0 0 100  abstime_timestamptz - ));
 DESCR("convert abstime to timestamp with time zone");
 DATA(insert OID = 1174 (  timestamptz     PGUID 12 f t f t 1 f 1184 "1082" 100 0 0 100  date_timestamptz - ));
@@ -1523,7 +1522,8 @@ DATA(insert OID = 1271 (  overlaps                   PGUID 12 f t t f 4 f 16 "1266 1266 1266 1
 DESCR("SQL92 interval comparison");
 DATA(insert OID = 1272 (  datetime_pl     PGUID 12 f t t t 2 f 1114 "1082 1083" 100 0 0 100  datetime_timestamp - ));
 DESCR("convert date and time to timestamp");
-
+DATA(insert OID = 1273 (  date_part               PGUID 12 f t t t 2 f  701 "25 1266" 100 0 0 100  timetz_part - ));
+DESCR("extract field from time with time zone");
 DATA(insert OID = 1274 (  int84pl                 PGUID 12 f t t t 2 f 20 "20 23" 100 0 0 100  int84pl - ));
 DESCR("add");
 DATA(insert OID = 1275 (  int84mi                 PGUID 12 f t t t 2 f 20 "20 23" 100 0 0 100  int84mi - ));
@@ -1709,11 +1709,11 @@ DESCR("length");
 
 DATA(insert OID = 1382 (  date_part    PGUID 14 f t f t 2 f  701 "25 702" 100 0 0 100  "select date_part($1, timestamptz($2))" - ));
 DESCR("extract field from abstime");
-DATA(insert OID = 1383 (  date_part    PGUID 14 f t f t 2 f  701 "25 703" 100 0 0 100  "select date_part($1, interval($2))" - ));
+DATA(insert OID = 1383 (  date_part    PGUID 14 f t f t 2 f  701 "25 703" 100 0 0 100  "select date_part($1, cast($2 as interval))" - ));
 DESCR("extract field from reltime");
 DATA(insert OID = 1384 (  date_part    PGUID 14 f t t t 2 f  701 "25 1082" 100 0 0 100  "select date_part($1, cast($2 as timestamp without time zone))" - ));
 DESCR("extract field from date");
-DATA(insert OID = 1385 (  date_part    PGUID 14 f t t t 2 f  701 "25 1083" 100 0 0 100  "select date_part($1, interval($2))" - ));
+DATA(insert OID = 1385 (  date_part    PGUID 14 f t t t 2 f  701 "25 1083" 100 0 0 100  "select date_part($1, cast($2 as time with time zone))" - ));
 DESCR("extract field from time");
 DATA(insert OID = 1386 (  age             PGUID 14 f t f t 1 f 1186 "1184" 100 0 0 100  "select age(cast(current_date as timestamp with time zone), $1)" - ));
 DESCR("date difference from today preserving months and years");
index c1e9541..75e88b8 100644 (file)
@@ -2,13 +2,13 @@
  * Headers for handling of 'SET var TO', 'SHOW var' and 'RESET var'
  * statements
  *
- * $Id: variable.h,v 1.13 2000/10/26 17:31:33 tgl Exp $
+ * $Id: variable.h,v 1.14 2001/10/18 17:30:16 thomas Exp $
  *
  */
 #ifndef VARIABLE_H
 #define VARIABLE_H
 
-extern void SetPGVariable(const char *name, const char *value);
+extern void SetPGVariable(const char *name, List *args);
 extern void GetPGVariable(const char *name);
 extern void ResetPGVariable(const char *name);
 
index 44961bc..ef6c9c6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.146 2001/10/12 00:07:15 tgl Exp $
+ * $Id: parsenodes.h,v 1.147 2001/10/18 17:30:16 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -736,7 +736,7 @@ typedef struct VariableSetStmt
 {
        NodeTag         type;
        char       *name;
-       char       *value;
+       List       *args;
 } VariableSetStmt;
 
 /* ----------------------
index 2698fc9..0e1aa14 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: date.h,v 1.13 2001/10/03 05:29:25 thomas Exp $
+ * $Id: date.h,v 1.14 2001/10/18 17:30:16 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -118,6 +118,7 @@ extern Datum timestamptz_timetz(PG_FUNCTION_ARGS);
 extern Datum datetimetz_timestamptz(PG_FUNCTION_ARGS);
 extern Datum text_timetz(PG_FUNCTION_ARGS);
 extern Datum timetz_text(PG_FUNCTION_ARGS);
+extern Datum timetz_part(PG_FUNCTION_ARGS);
 extern Datum timetz_zone(PG_FUNCTION_ARGS);
 extern Datum timetz_izone(PG_FUNCTION_ARGS);
 extern Datum timetz_pl_interval(PG_FUNCTION_ARGS);
index 299c7db..b7aaf0d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nabstime.h,v 1.31 2001/09/28 08:09:14 thomas Exp $
+ * $Id: nabstime.h,v 1.32 2001/10/18 17:30:16 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -158,6 +158,6 @@ extern Datum timeofday(PG_FUNCTION_ARGS);
 /* non-fmgr-callable support routines */
 extern AbsoluteTime GetCurrentAbsoluteTime(void);
 extern AbsoluteTime GetCurrentAbsoluteTimeUsec(int *usec);
-extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn);
+extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char **tzn);
 
 #endif  /* NABSTIME_H */
index 1a5f28f..1e193be 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: timestamp.h,v 1.20 2001/10/03 15:42:12 tgl Exp $
+ * $Id: timestamp.h,v 1.21 2001/10/18 17:30:16 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -105,6 +105,7 @@ extern Datum timestamp_larger(PG_FUNCTION_ARGS);
 
 extern Datum interval_in(PG_FUNCTION_ARGS);
 extern Datum interval_out(PG_FUNCTION_ARGS);
+extern Datum interval_scale(PG_FUNCTION_ARGS);
 extern Datum interval_eq(PG_FUNCTION_ARGS);
 extern Datum interval_ne(PG_FUNCTION_ARGS);
 extern Datum interval_lt(PG_FUNCTION_ARGS);
index 5e20631..3e7d241 100644 (file)
@@ -1788,8 +1788,8 @@ convert_escape(char *value)
                mapFunc = mapFunction(key);
 
                /*
-                * We could have mapFunction() return key if not in table... -
-                * thomas 2000-04-03
+                * We could have mapFunction() return key if not in table...
+                * thomas 2000-04-03
                 */
                if (mapFunc == NULL)
                {
index 21ad646..c0dec19 100644 (file)
@@ -1310,9 +1310,9 @@ SELECT '' AS "16", f1 AS "timestamp"
     | Sat Sep 22 18:19:20 2001 PDT
 (16 rows)
 
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 + t.f1 AS plus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
   FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
-  ORDER BY plus, "timestamp", interval;
+  ORDER BY plus, "timestamp", "interval";
  160 |          timestamp           |           interval            |             plus             
 -----+------------------------------+-------------------------------+------------------------------
      | Thu Jan 01 00:00:00 1970 PST | @ 14 secs ago                 | Wed Dec 31 23:59:46 1969 PST
@@ -1477,10 +1477,10 @@ SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 + t.f1 AS plus
      | Sat Sep 22 18:19:20 2001 PDT | @ 34 years                    | Sat Sep 22 18:19:20 2035 PDT
 (160 rows)
 
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 - t.f1 AS minus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
   FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
   WHERE isfinite(d.f1)
-  ORDER BY minus, "timestamp", interval;
+  ORDER BY minus, "timestamp", "interval";
  160 |          timestamp           |           interval            |            minus             
 -----+------------------------------+-------------------------------+------------------------------
      | Thu Jan 01 00:00:00 1970 PST | @ 34 years                    | Wed Jan 01 00:00:00 1936 PST
@@ -2084,7 +2084,7 @@ SELECT '' AS ten, f1 AS interval, reltime(f1) AS reltime
      | @ 5 mons 12 hours             | @ 5 mons 12 hours
 (10 rows)
 
-SELECT '' AS six, f1 as reltime, interval(f1) AS interval
+SELECT '' AS six, f1 as reltime, CAST(f1 AS interval) AS interval
   FROM RELTIME_TBL;
  six |    reltime    |   interval    
 -----+---------------+---------------
index 9405e8b..70fa14c 100644 (file)
@@ -59,7 +59,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('infinity');
 INSERT INTO TIMESTAMP_TBL VALUES ('epoch');
 -- Obsolete special values
 INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
-ERROR:  Timestamp 'invalid' no longer supported
+ERROR:  TIMESTAMP 'invalid' no longer supported
 -- Postgres v6.0 standard output format
 INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
 INSERT INTO TIMESTAMP_TBL VALUES ('Invalid Abstime');
@@ -137,7 +137,7 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 2001');
 INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
 ERROR:  Bad timestamp external representation 'Feb 16 17:32:01 -0097'
 INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
-ERROR:  Timestamp out of range 'Feb 16 17:32:01 5097 BC'
+ERROR:  TIMESTAMP out of range 'Feb 16 17:32:01 5097 BC'
 SELECT '' AS "64", d1 FROM TIMESTAMP_TBL; 
  64 |             d1              
 ----+-----------------------------
index ed11d16..dd7ef75 100644 (file)
@@ -54,7 +54,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('infinity');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('epoch');
 -- Obsolete special values
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
-ERROR:  Timestamp with time zone 'invalid' no longer supported
+ERROR:  TIMESTAMP WITH TIME ZONE 'invalid' no longer supported
 -- Postgres v6.0 standard output format
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Invalid Abstime');
@@ -132,7 +132,7 @@ INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 2001');
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097');
 ERROR:  Bad timestamp external representation 'Feb 16 17:32:01 -0097'
 INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC');
-ERROR:  Timestamp out of range 'Feb 16 17:32:01 5097 BC'
+ERROR:  TIMESTAMP WITH TIME ZONE out of range 'Feb 16 17:32:01 5097 BC'
 SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL; 
  64 |               d1                
 ----+---------------------------------
index 956e669..9e46521 100644 (file)
@@ -177,14 +177,14 @@ SELECT '' AS "16", f1 AS "timestamp"
   FROM TEMP_TIMESTAMP
   ORDER BY "timestamp";
 
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 + t.f1 AS plus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 + t.f1 AS plus
   FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
-  ORDER BY plus, "timestamp", interval;
+  ORDER BY plus, "timestamp", "interval";
 
-SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS interval, d.f1 - t.f1 AS minus
+SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minus
   FROM TEMP_TIMESTAMP d, INTERVAL_TBL t
   WHERE isfinite(d.f1)
-  ORDER BY minus, "timestamp", interval;
+  ORDER BY minus, "timestamp", "interval";
 
 SELECT '' AS "16", d.f1 AS "timestamp", timestamp '1980-01-06 00:00 GMT' AS gpstime_zero,
    d.f1 - timestamp '1980-01-06 00:00 GMT' AS difference
@@ -250,7 +250,7 @@ SELECT '' AS three, f1 as abstime, cast(f1 as timestamp) AS "timestamp"
 SELECT '' AS ten, f1 AS interval, reltime(f1) AS reltime
   FROM INTERVAL_TBL;
 
-SELECT '' AS six, f1 as reltime, interval(f1) AS interval
+SELECT '' AS six, f1 as reltime, CAST(f1 AS interval) AS interval
   FROM RELTIME_TBL;
 
 DROP TABLE TEMP_TIMESTAMP;