Allow interpretation of INTERVALs with more timezone-like syntax.
authorThomas G. Lockhart
Sat, 11 Nov 2000 19:55:19 +0000 (19:55 +0000)
committerThomas G. Lockhart
Sat, 11 Nov 2000 19:55:19 +0000 (19:55 +0000)
Define conversions to and from text for date, time, and timetz.
Have millisecond and microsecond return full # of seconds in those units.
 Previously, only returned full fractional part in those units.

src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/backend/utils/adt/timestamp.c

index a19ae9e48af176e8c7507dffedd92555b645bdb1..d7f4da718bff56442c11b4f9b9d087897d24b051 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.51 2000/10/29 13:17:33 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.52 2000/11/11 19:55:19 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -339,6 +339,61 @@ abstime_date(PG_FUNCTION_ARGS)
 }
 
 
+/* date_text()
+ * Convert date to text data type.
+ */
+Datum
+date_text(PG_FUNCTION_ARGS)
+{
+   /* Input is a Date, but may as well leave it in Datum form */
+   Datum       date = PG_GETARG_DATUM(0);
+   text       *result;
+   char       *str;
+   int         len;
+
+   str = DatumGetCString(DirectFunctionCall1(date_out, date));
+
+   len = (strlen(str) + VARHDRSZ);
+
+   result = palloc(len);
+
+   VARATT_SIZEP(result) = len;
+   memmove(VARDATA(result), str, (len - VARHDRSZ));
+
+   pfree(str);
+
+   PG_RETURN_TEXT_P(result);
+}
+
+
+/* text_date()
+ * Convert text string to date.
+ * Text type is not null terminated, so use temporary string
+ * then call the standard input routine.
+ */
+Datum
+text_date(PG_FUNCTION_ARGS)
+{
+   text       *str = PG_GETARG_TEXT_P(0);
+   int         i;
+   char       *sp,
+              *dp,
+               dstr[MAXDATELEN + 1];
+
+   if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
+       elog(ERROR, "Bad date external representation (too long)");
+
+   sp = VARDATA(str);
+   dp = dstr;
+   for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
+       *dp++ = *sp++;
+   *dp = '\0';
+
+   return DirectFunctionCall1(date_in,
+                              CStringGetDatum(dstr));
+}
+
+
 /*****************************************************************************
  *  Time ADT
  *****************************************************************************/
@@ -576,6 +631,61 @@ time_interval(PG_FUNCTION_ARGS)
 }
 
 
+/* time_text()
+ * Convert time to text data type.
+ */
+Datum
+time_text(PG_FUNCTION_ARGS)
+{
+   /* Input is a Time, but may as well leave it in Datum form */
+   Datum       time = PG_GETARG_DATUM(0);
+   text       *result;
+   char       *str;
+   int         len;
+
+   str = DatumGetCString(DirectFunctionCall1(time_out, time));
+
+   len = (strlen(str) + VARHDRSZ);
+
+   result = palloc(len);
+
+   VARATT_SIZEP(result) = len;
+   memmove(VARDATA(result), str, (len - VARHDRSZ));
+
+   pfree(str);
+
+   PG_RETURN_TEXT_P(result);
+}
+
+
+/* text_time()
+ * Convert text string to time.
+ * Text type is not null terminated, so use temporary string
+ * then call the standard input routine.
+ */
+Datum
+text_time(PG_FUNCTION_ARGS)
+{
+   text       *str = PG_GETARG_TEXT_P(0);
+   int         i;
+   char       *sp,
+              *dp,
+               dstr[MAXDATELEN + 1];
+
+   if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
+       elog(ERROR, "Bad time external representation (too long)");
+
+   sp = VARDATA(str);
+   dp = dstr;
+   for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
+       *dp++ = *sp++;
+   *dp = '\0';
+
+   return DirectFunctionCall1(time_in,
+                              CStringGetDatum(dstr));
+}
+
+
 /*****************************************************************************
  *  Time With Time Zone ADT
  *****************************************************************************/
@@ -851,3 +961,58 @@ datetimetz_timestamp(PG_FUNCTION_ARGS)
 
    PG_RETURN_TIMESTAMP(result);
 }
+
+
+/* timetz_text()
+ * Convert timetz to text data type.
+ */
+Datum
+timetz_text(PG_FUNCTION_ARGS)
+{
+   /* Input is a Timetz, but may as well leave it in Datum form */
+   Datum       timetz = PG_GETARG_DATUM(0);
+   text       *result;
+   char       *str;
+   int         len;
+
+   str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
+
+   len = (strlen(str) + VARHDRSZ);
+
+   result = palloc(len);
+
+   VARATT_SIZEP(result) = len;
+   memmove(VARDATA(result), str, (len - VARHDRSZ));
+
+   pfree(str);
+
+   PG_RETURN_TEXT_P(result);
+}
+
+
+/* text_timetz()
+ * Convert text string to timetz.
+ * Text type is not null terminated, so use temporary string
+ * then call the standard input routine.
+ */
+Datum
+text_timetz(PG_FUNCTION_ARGS)
+{
+   text       *str = PG_GETARG_TEXT_P(0);
+   int         i;
+   char       *sp,
+              *dp,
+               dstr[MAXDATELEN + 1];
+
+   if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
+       elog(ERROR, "Bad timetz external representation (too long)");
+
+   sp = VARDATA(str);
+   dp = dstr;
+   for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
+       *dp++ = *sp++;
+   *dp = '\0';
+
+   return DirectFunctionCall1(timetz_in,
+                              CStringGetDatum(dstr));
+}
index 0f8f344ef58eec3eba9bc6d49ce692380124b0d9..a167943dff9a5c50a595be5e92657e267b203423 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.55 2000/11/06 15:57:00 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.56 2000/11/11 19:55:19 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -494,7 +494,7 @@ ParseDateTime(char *timestr, char *lowstr,
            {
                ftype[nf] = DTK_TZ;
                *lp++ = *cp++;
-               while (isdigit((int) *cp) || (*cp == ':'))
+               while (isdigit((int) *cp) || (*cp == ':') || (*cp == '.'))
                    *lp++ = *cp++;
 
                /* special? */
@@ -1657,7 +1657,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 
    *dtype = DTK_DELTA;
 
-   type = DTK_SECOND;
+   type = IGNORE;
    tm->tm_year = 0;
    tm->tm_mon = 0;
    tm->tm_mday = 0;
@@ -1687,7 +1687,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
                 * So, work this out to drop through to DTK_NUMBER, which *can* tolerate this.
                 */
                cp = field[i]+1;
-               while ((*cp != '\0') && (*cp != ':'))
+               while ((*cp != '\0') && (*cp != ':') && (*cp != '.'))
                    cp++;
                if ((*cp == ':')
                    && (DecodeTime((field[i]+1), fmask, &tmask, tm, fsec) == 0)) {
@@ -1705,6 +1705,14 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
                    type = DTK_DAY;
                    tmask = DTK_M(TZ);
                    break;
+               } else if (type == IGNORE) {
+                   if (*cp == '.') {
+                       /* Got a decimal point? Then assume some sort of seconds specification */
+                       type = DTK_SECOND;
+                   } else if (*cp == '\0') {
+                       /* Only a signed integer? Then must assume a timezone-like usage */
+                       type = DTK_HOUR;
+                   }
                }
                /* DROP THROUGH */
 
@@ -1714,6 +1722,8 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 
                if (*cp == '.')
                {
+                   if (type == IGNORE)
+                       type = DTK_SECOND;
                    fval = strtod(cp, &cp);
                    if (*cp != '\0')
                        return -1;
index ab147d295b56a7e38ffbcf5f70ab13fc7c127fe9..4478dc95efa596ea5576386ac664cb8aa581d7a3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.37 2000/11/06 15:57:00 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.38 2000/11/11 19:55:19 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2100,11 +2100,11 @@ interval_part(PG_FUNCTION_ARGS)
            switch (val)
            {
                case DTK_MICROSEC:
-                   result = (fsec * 1000000);
+                   result = ((tm->tm_sec + fsec) * 1000000);
                    break;
 
                case DTK_MILLISEC:
-                   result = (fsec * 1000);
+                   result = ((tm->tm_sec + fsec) * 1000);
                    break;
 
                case DTK_SECOND: