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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy