Re: Australian timezone configure option - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Australian timezone configure option
Date
Msg-id 200106121518.f5CFITr10589@candle.pha.pa.us
Whole thread Raw
In response to Re: Australian timezone configure option  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Australian timezone configure option
List pgsql-patches
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > OK, this patch makes Australian_timezones a GUC option.  It can be set
> > anytime in psql.  The code uses a static variable to check if the GUC
> > setting has changed and adjust the C struct accordingly.
>
> This is a horrid approach.  What if you get an error partway through
> scribbling on the static table?  Then you've got inconsistent data.

I have set the variable to -1 on entry so it will reload on failure,
though it is only doing C lookups on a static table so it is hard to see
how it would fail.

> Nor do I much care for having to execute a check subroutine before any
> use of the lookup table (quite aside from speed, are you sure it's being
> called before *every* use of the table?  how will you make sure that
> people remember to call it when they add new routines that use the
> table?).  If you're going to scribble on the table, ISTM you should
> drive that off an assignment-hook callback from the GUC stuff.

But we don't have such hooks so I did it with as little code as
possible.  The table itself is 'static' so it is only called in this
function.  (The old patch had the static removed because I thought I was
going to have to do this stuff in the guc files but now it is all in the
same file.)

> Besides which, you forgot to mark the control variable static...
> so it doesn't actually reflect the state of the table.

Fixed.  I had that in an ealier version but forgot to add it when I
moved it out to a separate function.

> It would be a lot cleaner to extend the lookup table structure so that
> you don't need to change the table contents to track the Aussie-rules
> setting.

Yes, when we do that we can remove the call and call it instead from the
GUC setting.

Here is a new version of the patch.  I found I didn't need to clear the
date cache.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/doc/src/sgml/runtime.sgml,v
retrieving revision 1.67
diff -c -r1.67 runtime.sgml
*** doc/src/sgml/runtime.sgml    2001/05/17 17:44:17    1.67
--- doc/src/sgml/runtime.sgml    2001/06/12 15:02:15
***************
*** 1201,1206 ****
--- 1201,1217 ----
        </listitem>
       </varlistentry>

+       <term>AUSTRALIAN_TIMEZONES (<type>bool</type>)</term>
+       <listitem>
+        <para>
+         If set to true, <literal>CST</literal>, <literal>EST</literal>,
+         and <literal>SAT</literal> are interpreted as Australian
+         timezones rather than as North American Central/Eastern
+         Timezones and Saturday. The default is false.
+        </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <indexterm>
         <primary>SSL</primary>
Index: src/backend/utils/adt/datetime.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/adt/datetime.c,v
retrieving revision 1.64
diff -c -r1.64 datetime.c
*** src/backend/utils/adt/datetime.c    2001/05/03 22:53:07    1.64
--- src/backend/utils/adt/datetime.c    2001/06/12 15:02:17
***************
*** 22,27 ****
--- 22,28 ----
  #include <limits.h>

  #include "miscadmin.h"
+ #include "utils/guc.h"
  #include "utils/datetime.h"

  static int DecodeNumber(int flen, char *field,
***************
*** 35,40 ****
--- 36,42 ----
  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 void    CheckAustralianTimezones(int field);

  #define USE_DATE_CACHE 1
  #define ROUND_ALL 0
***************
*** 117,127 ****
      {"cdt", DTZ, NEG(30)},        /* Central Daylight Time */
      {"cet", TZ, 6},                /* Central European Time */
      {"cetdst", DTZ, 12},        /* Central European Dayl.Time */
! #if USE_AUSTRALIAN_RULES
!     {"cst", TZ, 63},            /* Australia Eastern Std Time */
! #else
!     {"cst", TZ, NEG(36)},        /* Central Standard Time */
! #endif
      {DCURRENT, RESERV, DTK_CURRENT},    /* "current" is always now */
      {"dec", MONTH, 12},
      {"december", MONTH, 12},
--- 119,125 ----
      {"cdt", DTZ, NEG(30)},        /* Central Daylight Time */
      {"cet", TZ, 6},                /* Central European Time */
      {"cetdst", DTZ, 12},        /* Central European Dayl.Time */
!     {"cst", TZ, NEG(36)},        /* Central Standard Time, may be Australian */
      {DCURRENT, RESERV, DTK_CURRENT},    /* "current" is always now */
      {"dec", MONTH, 12},
      {"december", MONTH, 12},
***************
*** 134,144 ****
      {"eet", TZ, 12},            /* East. Europe, USSR Zone 1 */
      {"eetdst", DTZ, 18},        /* Eastern Europe */
      {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
! #if USE_AUSTRALIAN_RULES
!     {"est", TZ, 60},            /* Australia Eastern Std Time */
! #else
!     {"est", TZ, NEG(30)},        /* Eastern Standard Time */
! #endif
      {"feb", MONTH, 2},
      {"february", MONTH, 2},
      {"fri", DOW, 5},
--- 132,138 ----
      {"eet", TZ, 12},            /* East. Europe, USSR Zone 1 */
      {"eetdst", DTZ, 18},        /* Eastern Europe */
      {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
!     {"est", TZ, NEG(30)},        /* Eastern Standard Time, may be Australian */
      {"feb", MONTH, 2},
      {"february", MONTH, 2},
      {"fri", DOW, 5},
***************
*** 199,209 ****
      {"pst", TZ, NEG(48)},        /* Pacific Standard Time */
      {"sadt", DTZ, 63},            /* S. Australian Dayl. Time */
      {"sast", TZ, 57},            /* South Australian Std Time */
! #if USE_AUSTRALIAN_RULES
!     {"sat", TZ, 57},
! #else
!     {"sat", DOW, 6},
! #endif
      {"saturday", DOW, 6},
      {"sep", MONTH, 9},
      {"sept", MONTH, 9},
--- 193,199 ----
      {"pst", TZ, NEG(48)},        /* Pacific Standard Time */
      {"sadt", DTZ, 63},            /* S. Australian Dayl. Time */
      {"sast", TZ, 57},            /* South Australian Std Time */
!     {"sat", DOW, 6},            /* may be changed to Australian */
      {"saturday", DOW, 6},
      {"sep", MONTH, 9},
      {"sept", MONTH, 9},
***************
*** 1618,1623 ****
--- 1608,1615 ----
      int            type;
      datetkn    *tp;

+     CheckAustralianTimezones(field);
+
  #if USE_DATE_CACHE
      if ((datecache[field] != NULL)
          && (strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0))
***************
*** 2455,2457 ****
--- 2447,2494 ----

      return 0;
  }    /* EncodeTimeSpan() */
+
+
+ static void    CheckAustralianTimezones(int field)
+ {
+     datetkn    *tp;
+     /* structure preloaded as false */
+     static int prev_Australian_timezones = -1;
+
+     if (Australian_timezones != prev_Australian_timezones)
+     {
+         prev_Australian_timezones = -1;    /* in case it fails, force reload */
+         /* CST */
+         tp = datebsearch("cst", datetktbl, szdatetktbl);
+         Assert(tp);
+         tp->type = TZ;
+         if (!Australian_timezones)
+             tp->value = NEG(36);    /* Central Standard Time */
+         else
+             tp->value = 63;            /* Australia Eastern Std Time */
+
+         /* EST */
+         tp = datebsearch("est", datetktbl, szdatetktbl);
+         Assert(tp);
+         tp->type = TZ;
+         if (!Australian_timezones)
+             tp->value = NEG(30);    /* Eastern Standard Time */
+         else
+             tp->value = 60;            /* Australia Eastern Std Time */
+
+         /* SAT */
+         tp = datebsearch("sat", datetktbl, szdatetktbl);
+         Assert(tp);
+         if (!Australian_timezones)
+         {
+             tp->type = DOW;
+             tp->value = 6;
+         }
+         else
+         {
+             tp->type = TZ;
+             tp->value = 57;
+         }
+         prev_Australian_timezones = Australian_timezones;
+     }
+ }
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.37
diff -c -r1.37 guc.c
*** src/backend/utils/misc/guc.c    2001/06/07 04:50:57    1.37
--- src/backend/utils/misc/guc.c    2001/06/12 15:02:17
***************
*** 71,76 ****
--- 71,78 ----

  bool        SQL_inheritance = true;

+ bool        Australian_timezones = false;
+
  #ifndef PG_KRB_SRVTAB
  #define PG_KRB_SRVTAB ""
  #endif
***************
*** 222,227 ****
--- 224,230 ----
      {"show_source_port", PGC_SIGHUP, &ShowPortNumber, false},

      {"sql_inheritance", PGC_USERSET, &SQL_inheritance, true},
+     {"australian_timezones", PGC_USERSET, &Australian_timezones, false},

      {"fixbtree", PGC_POSTMASTER, &FixBTree, true},

***************
*** 880,885 ****
--- 883,889 ----
          case PGC_BOOL:
              val = *((struct config_bool *) record)->variable ? "on" : "off";
              break;
+
          case PGC_INT:
              snprintf(buffer, 256, "%d", *((struct config_int *) record)->variable);
              val = buffer;
***************
*** 955,961 ****
              elog(FATAL, "out of memory");
      }
      else
! /* no equal sign in string */
      {
          *name = strdup(string);
          if (!*name)
--- 959,965 ----
              elog(FATAL, "out of memory");
      }
      else
!     /* no equal sign in string */
      {
          *name = strdup(string);
          if (!*name)
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.11
diff -c -r1.11 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    2001/05/07 23:32:55    1.11
--- src/backend/utils/misc/postgresql.conf.sample    2001/06/12 15:02:17
***************
*** 85,108 ****


  #
- #    Inheritance
- #
- #sql_inheritance = true
-
-
- #
- #    Deadlock
- #
- #deadlock_timeout = 1000
-
-
- #
- #    Expression Depth Limitation
- #
- #max_expr_depth = 10000 # min 10
-
-
- #
  #    Write-ahead log (WAL)
  #
  #wal_buffers = 8 # min 4
--- 85,90 ----
***************
*** 172,174 ****
--- 154,166 ----
  #trace_lock_oidmin = 16384
  #trace_lock_table = 0
  #endif
+
+
+ #
+ #    Misc
+ #
+ #sql_inheritance = true
+ #australian_timezones = false
+ #deadlock_timeout = 1000
+ #max_expr_depth = 10000 # min 10
+
Index: src/include/utils/datetime.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/utils/datetime.h,v
retrieving revision 1.18
diff -c -r1.18 datetime.h
*** src/include/utils/datetime.h    2001/05/03 22:53:07    1.18
--- src/include/utils/datetime.h    2001/06/12 15:02:18
***************
*** 182,187 ****
--- 182,188 ----
      char        value;            /* this may be unsigned, alas */
  } datetkn;

+ extern datetkn datetktbl[];

  /* TMODULO()
   * Macro to replace modf(), which is broken on some platforms.
Index: src/include/utils/guc.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/utils/guc.h,v
retrieving revision 1.7
diff -c -r1.7 guc.h
*** src/include/utils/guc.h    2001/06/07 04:50:57    1.7
--- src/include/utils/guc.h    2001/06/12 15:02:18
***************
*** 68,72 ****
--- 68,73 ----
  extern bool Show_btree_build_stats;

  extern bool SQL_inheritance;
+ extern bool Australian_timezones;

  #endif     /* GUC_H */
Index: src/test/regress/expected/horology-no-DST-before-1970.out
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/expected/horology-no-DST-before-1970.out,v
retrieving revision 1.12
diff -c -r1.12 horology-no-DST-before-1970.out
*** src/test/regress/expected/horology-no-DST-before-1970.out    2001/04/06 05:50:25    1.12
--- src/test/regress/expected/horology-no-DST-before-1970.out    2001/06/12 15:02:24
***************
*** 4,9 ****
--- 4,11 ----
  --
  -- date, time arithmetic
  --
+ -- needed so tests pass
+ SET australian_timezones = 'off';
  SELECT date '1981-02-03' + time '04:05:06' AS "Date + Time";
           Date + Time
  ------------------------------
Index: src/test/regress/expected/horology-solaris-1947.out
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/expected/horology-solaris-1947.out,v
retrieving revision 1.10
diff -c -r1.10 horology-solaris-1947.out
*** src/test/regress/expected/horology-solaris-1947.out    2001/04/06 05:50:25    1.10
--- src/test/regress/expected/horology-solaris-1947.out    2001/06/12 15:02:24
***************
*** 4,9 ****
--- 4,11 ----
  --
  -- date, time arithmetic
  --
+ -- needed so tests pass
+ SET australian_timezones = 'off';
  SELECT date '1981-02-03' + time '04:05:06' AS "Date + Time";
           Date + Time
  ------------------------------
Index: src/test/regress/expected/horology.out
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/expected/horology.out,v
retrieving revision 1.23
diff -c -r1.23 horology.out
*** src/test/regress/expected/horology.out    2001/04/06 05:50:25    1.23
--- src/test/regress/expected/horology.out    2001/06/12 15:02:25
***************
*** 4,9 ****
--- 4,11 ----
  --
  -- date, time arithmetic
  --
+ -- needed so tests pass
+ SET australian_timezones = 'off';
  SELECT date '1981-02-03' + time '04:05:06' AS "Date + Time";
           Date + Time
  ------------------------------
Index: src/test/regress/expected/timestamp.out
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/expected/timestamp.out,v
retrieving revision 1.12
diff -c -r1.12 timestamp.out
*** src/test/regress/expected/timestamp.out    2001/05/03 19:00:37    1.12
--- src/test/regress/expected/timestamp.out    2001/06/12 15:02:26
***************
*** 4,9 ****
--- 4,11 ----
  -- Shorthand values
  -- Not directly usable for regression testing since these are not constants.
  -- So, just try to test parser and hope for the best - thomas 97/04/26
+ -- needed so tests pass
+ SET australian_timezones = 'off';
  SELECT (timestamp 'today' = (timestamp 'yesterday' + interval '1 day')) as "True";
   True
  ------
Index: src/test/regress/sql/horology.sql
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/sql/horology.sql,v
retrieving revision 1.14
diff -c -r1.14 horology.sql
*** src/test/regress/sql/horology.sql    2001/04/06 05:50:29    1.14
--- src/test/regress/sql/horology.sql    2001/06/12 15:02:26
***************
*** 1,10 ****
  --
  -- HOROLOGY
  --
-
  --
  -- date, time arithmetic
  --

  SELECT date '1981-02-03' + time '04:05:06' AS "Date + Time";

--- 1,11 ----
  --
  -- HOROLOGY
  --
  --
  -- date, time arithmetic
  --
+ -- needed so tests pass
+ SET australian_timezones = 'off';

  SELECT date '1981-02-03' + time '04:05:06' AS "Date + Time";

Index: src/test/regress/sql/timestamp.sql
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/test/regress/sql/timestamp.sql,v
retrieving revision 1.7
diff -c -r1.7 timestamp.sql
*** src/test/regress/sql/timestamp.sql    2000/11/25 05:00:33    1.7
--- src/test/regress/sql/timestamp.sql    2001/06/12 15:02:26
***************
*** 1,10 ****
  --
  -- DATETIME
  --
-
  -- Shorthand values
  -- Not directly usable for regression testing since these are not constants.
  -- So, just try to test parser and hope for the best - thomas 97/04/26

  SELECT (timestamp 'today' = (timestamp 'yesterday' + interval '1 day')) as "True";
  SELECT (timestamp 'today' = (timestamp 'tomorrow' - interval '1 day')) as "True";
--- 1,11 ----
  --
  -- DATETIME
  --
  -- Shorthand values
  -- Not directly usable for regression testing since these are not constants.
  -- So, just try to test parser and hope for the best - thomas 97/04/26
+ -- needed so tests pass
+ SET australian_timezones = 'off';

  SELECT (timestamp 'today' = (timestamp 'yesterday' + interval '1 day')) as "True";
  SELECT (timestamp 'today' = (timestamp 'tomorrow' - interval '1 day')) as "True";

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: 7.1 odbc bug & patch
Next
From: Bruce Momjian
Date:
Subject: Re: Australian timezone configure option