]> granicus.if.org Git - postgresql/commitdiff
Allow interpretation of INTERVALs with more timezone-like syntax.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Sat, 11 Nov 2000 19:55:19 +0000 (19:55 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
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: