Skip to content

Commit 89a99cb

Browse files
author
Thomas G. Lockhart
committed
Allow interpretation of INTERVALs with more timezone-like syntax.
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.
1 parent ecc367b commit 89a99cb

File tree

3 files changed

+183
-8
lines changed

3 files changed

+183
-8
lines changed

src/backend/utils/adt/date.c

Lines changed: 166 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.51 2000/10/29 13:17:33 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.52 2000/11/11 19:55:19 thomas Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -339,6 +339,61 @@ abstime_date(PG_FUNCTION_ARGS)
339339
}
340340

341341

342+
/* date_text()
343+
* Convert date to text data type.
344+
*/
345+
Datum
346+
date_text(PG_FUNCTION_ARGS)
347+
{
348+
/* Input is a Date, but may as well leave it in Datum form */
349+
Datum date = PG_GETARG_DATUM(0);
350+
text *result;
351+
char *str;
352+
int len;
353+
354+
str = DatumGetCString(DirectFunctionCall1(date_out, date));
355+
356+
len = (strlen(str) + VARHDRSZ);
357+
358+
result = palloc(len);
359+
360+
VARATT_SIZEP(result) = len;
361+
memmove(VARDATA(result), str, (len - VARHDRSZ));
362+
363+
pfree(str);
364+
365+
PG_RETURN_TEXT_P(result);
366+
}
367+
368+
369+
/* text_date()
370+
* Convert text string to date.
371+
* Text type is not null terminated, so use temporary string
372+
* then call the standard input routine.
373+
*/
374+
Datum
375+
text_date(PG_FUNCTION_ARGS)
376+
{
377+
text *str = PG_GETARG_TEXT_P(0);
378+
int i;
379+
char *sp,
380+
*dp,
381+
dstr[MAXDATELEN + 1];
382+
383+
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
384+
elog(ERROR, "Bad date external representation (too long)");
385+
386+
sp = VARDATA(str);
387+
dp = dstr;
388+
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
389+
*dp++ = *sp++;
390+
*dp = '\0';
391+
392+
return DirectFunctionCall1(date_in,
393+
CStringGetDatum(dstr));
394+
}
395+
396+
342397
/*****************************************************************************
343398
* Time ADT
344399
*****************************************************************************/
@@ -576,6 +631,61 @@ time_interval(PG_FUNCTION_ARGS)
576631
}
577632

578633

634+
/* time_text()
635+
* Convert time to text data type.
636+
*/
637+
Datum
638+
time_text(PG_FUNCTION_ARGS)
639+
{
640+
/* Input is a Time, but may as well leave it in Datum form */
641+
Datum time = PG_GETARG_DATUM(0);
642+
text *result;
643+
char *str;
644+
int len;
645+
646+
str = DatumGetCString(DirectFunctionCall1(time_out, time));
647+
648+
len = (strlen(str) + VARHDRSZ);
649+
650+
result = palloc(len);
651+
652+
VARATT_SIZEP(result) = len;
653+
memmove(VARDATA(result), str, (len - VARHDRSZ));
654+
655+
pfree(str);
656+
657+
PG_RETURN_TEXT_P(result);
658+
}
659+
660+
661+
/* text_time()
662+
* Convert text string to time.
663+
* Text type is not null terminated, so use temporary string
664+
* then call the standard input routine.
665+
*/
666+
Datum
667+
text_time(PG_FUNCTION_ARGS)
668+
{
669+
text *str = PG_GETARG_TEXT_P(0);
670+
int i;
671+
char *sp,
672+
*dp,
673+
dstr[MAXDATELEN + 1];
674+
675+
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
676+
elog(ERROR, "Bad time external representation (too long)");
677+
678+
sp = VARDATA(str);
679+
dp = dstr;
680+
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
681+
*dp++ = *sp++;
682+
*dp = '\0';
683+
684+
return DirectFunctionCall1(time_in,
685+
CStringGetDatum(dstr));
686+
}
687+
688+
579689
/*****************************************************************************
580690
* Time With Time Zone ADT
581691
*****************************************************************************/
@@ -851,3 +961,58 @@ datetimetz_timestamp(PG_FUNCTION_ARGS)
851961

852962
PG_RETURN_TIMESTAMP(result);
853963
}
964+
965+
966+
/* timetz_text()
967+
* Convert timetz to text data type.
968+
*/
969+
Datum
970+
timetz_text(PG_FUNCTION_ARGS)
971+
{
972+
/* Input is a Timetz, but may as well leave it in Datum form */
973+
Datum timetz = PG_GETARG_DATUM(0);
974+
text *result;
975+
char *str;
976+
int len;
977+
978+
str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
979+
980+
len = (strlen(str) + VARHDRSZ);
981+
982+
result = palloc(len);
983+
984+
VARATT_SIZEP(result) = len;
985+
memmove(VARDATA(result), str, (len - VARHDRSZ));
986+
987+
pfree(str);
988+
989+
PG_RETURN_TEXT_P(result);
990+
}
991+
992+
993+
/* text_timetz()
994+
* Convert text string to timetz.
995+
* Text type is not null terminated, so use temporary string
996+
* then call the standard input routine.
997+
*/
998+
Datum
999+
text_timetz(PG_FUNCTION_ARGS)
1000+
{
1001+
text *str = PG_GETARG_TEXT_P(0);
1002+
int i;
1003+
char *sp,
1004+
*dp,
1005+
dstr[MAXDATELEN + 1];
1006+
1007+
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
1008+
elog(ERROR, "Bad timetz external representation (too long)");
1009+
1010+
sp = VARDATA(str);
1011+
dp = dstr;
1012+
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
1013+
*dp++ = *sp++;
1014+
*dp = '\0';
1015+
1016+
return DirectFunctionCall1(timetz_in,
1017+
CStringGetDatum(dstr));
1018+
}

src/backend/utils/adt/datetime.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.55 2000/11/06 15:57:00 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.56 2000/11/11 19:55:19 thomas Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -494,7 +494,7 @@ ParseDateTime(char *timestr, char *lowstr,
494494
{
495495
ftype[nf] = DTK_TZ;
496496
*lp++ = *cp++;
497-
while (isdigit((int) *cp) || (*cp == ':'))
497+
while (isdigit((int) *cp) || (*cp == ':') || (*cp == '.'))
498498
*lp++ = *cp++;
499499

500500
/* special? */
@@ -1657,7 +1657,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
16571657

16581658
*dtype = DTK_DELTA;
16591659

1660-
type = DTK_SECOND;
1660+
type = IGNORE;
16611661
tm->tm_year = 0;
16621662
tm->tm_mon = 0;
16631663
tm->tm_mday = 0;
@@ -1687,7 +1687,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
16871687
* So, work this out to drop through to DTK_NUMBER, which *can* tolerate this.
16881688
*/
16891689
cp = field[i]+1;
1690-
while ((*cp != '\0') && (*cp != ':'))
1690+
while ((*cp != '\0') && (*cp != ':') && (*cp != '.'))
16911691
cp++;
16921692
if ((*cp == ':')
16931693
&& (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
17051705
type = DTK_DAY;
17061706
tmask = DTK_M(TZ);
17071707
break;
1708+
} else if (type == IGNORE) {
1709+
if (*cp == '.') {
1710+
/* Got a decimal point? Then assume some sort of seconds specification */
1711+
type = DTK_SECOND;
1712+
} else if (*cp == '\0') {
1713+
/* Only a signed integer? Then must assume a timezone-like usage */
1714+
type = DTK_HOUR;
1715+
}
17081716
}
17091717
/* DROP THROUGH */
17101718

@@ -1714,6 +1722,8 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
17141722

17151723
if (*cp == '.')
17161724
{
1725+
if (type == IGNORE)
1726+
type = DTK_SECOND;
17171727
fval = strtod(cp, &cp);
17181728
if (*cp != '\0')
17191729
return -1;

src/backend/utils/adt/timestamp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.37 2000/11/06 15:57:00 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.38 2000/11/11 19:55:19 thomas Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2100,11 +2100,11 @@ interval_part(PG_FUNCTION_ARGS)
21002100
switch (val)
21012101
{
21022102
case DTK_MICROSEC:
2103-
result = (fsec * 1000000);
2103+
result = ((tm->tm_sec + fsec) * 1000000);
21042104
break;
21052105

21062106
case DTK_MILLISEC:
2107-
result = (fsec * 1000);
2107+
result = ((tm->tm_sec + fsec) * 1000);
21082108
break;
21092109

21102110
case DTK_SECOND:

0 commit comments

Comments
 (0)