diff options
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/date.c | 113 | ||||
| -rw-r--r-- | src/backend/utils/adt/datetime.c | 126 | ||||
| -rw-r--r-- | src/backend/utils/adt/numeric.c | 4 | ||||
| -rw-r--r-- | src/backend/utils/adt/timestamp.c | 106 | ||||
| -rw-r--r-- | src/backend/utils/adt/varchar.c | 4 |
5 files changed, 284 insertions, 69 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 36b3a52de2..d35849cd62 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.58 2001/09/28 08:09:10 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.59 2001/10/03 05:29:24 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,9 @@ #include "utils/timestamp.h" +static void +AdjustTimeForTypmod(TimeADT *time, int32 typmod); + /***************************************************************************** * Date ADT *****************************************************************************/ @@ -425,7 +428,11 @@ Datum time_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); - TimeADT time; +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); + TimeADT result; double fsec; struct tm tt, *tm = &tt; @@ -439,9 +446,11 @@ time_in(PG_FUNCTION_ARGS) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0)) elog(ERROR, "Bad time external representation '%s'", str); - time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); + result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); + + AdjustTimeForTypmod(&result, typmod); - PG_RETURN_TIMEADT(time); + PG_RETURN_TIMEADT(result); } Datum @@ -452,13 +461,14 @@ time_out(PG_FUNCTION_ARGS) struct tm tt, *tm = &tt; double fsec; + double trem; char buf[MAXDATELEN + 1]; - tm->tm_hour = (time / (60 * 60)); - tm->tm_min = (((int) (time / 60)) % 60); - tm->tm_sec = (((int) time) % 60); - - fsec = 0; + trem = time; + TMODULO(trem, tm->tm_hour, 3600e0); + TMODULO(trem, tm->tm_min, 60e0); + TMODULO(trem, tm->tm_sec, 1e0); + fsec = trem; EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf); @@ -466,6 +476,43 @@ time_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* time_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +time_scale(PG_FUNCTION_ARGS) +{ + TimeADT time = PG_GETARG_TIMEADT(0); + int32 typmod = PG_GETARG_INT32(1); + TimeADT result; + + result = time; + AdjustTimeForTypmod(&result, typmod); + + PG_RETURN_TIMEADT(result); +} + +static void +AdjustTimeForTypmod(TimeADT *time, int32 typmod) +{ + if ((typmod >= 0) && (typmod <= 13)) + { + static double TimeScale = 1; + static int32 TimeTypmod = 0; + + if (typmod != TimeTypmod) + TimeScale = pow(10, typmod); + + *time = (rint(((double) *time)*TimeScale)/TimeScale); + + if (*time >= 86400) + *time -= 86400; + } + + return; +} + Datum time_eq(PG_FUNCTION_ARGS) @@ -882,12 +929,15 @@ text_time(PG_FUNCTION_ARGS) * Time With Time Zone ADT *****************************************************************************/ - Datum timetz_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); - TimeTzADT *time; +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); + TimeTzADT *result; double fsec; struct tm tt, *tm = &tt; @@ -902,12 +952,14 @@ timetz_in(PG_FUNCTION_ARGS) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) elog(ERROR, "Bad time external representation '%s'", str); - time = (TimeTzADT *) palloc(sizeof(TimeTzADT)); + result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); + + result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); + result->zone = tz; - time->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); - time->zone = tz; + AdjustTimeForTypmod(&(result->time), typmod); - PG_RETURN_TIMETZADT_P(time); + PG_RETURN_TIMETZADT_P(result); } Datum @@ -919,13 +971,15 @@ timetz_out(PG_FUNCTION_ARGS) *tm = &tt; double fsec; int tz; + double trem; char buf[MAXDATELEN + 1]; - tm->tm_hour = (time->time / (60 * 60)); - tm->tm_min = (((int) (time->time / 60)) % 60); - tm->tm_sec = (((int) time->time) % 60); + trem = time->time; + TMODULO(trem, tm->tm_hour, 3600e0); + TMODULO(trem, tm->tm_min, 60e0); + TMODULO(trem, tm->tm_sec, 1e0); + fsec = trem; - fsec = 0; tz = time->zone; EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf); @@ -934,6 +988,27 @@ timetz_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* timetz_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +timetz_scale(PG_FUNCTION_ARGS) +{ + TimeTzADT *time = PG_GETARG_TIMETZADT_P(0); + int32 typmod = PG_GETARG_INT32(1); + TimeTzADT *result; + + result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); + + result->time = time->time; + result->zone = time->zone; + + AdjustTimeForTypmod(&(result->time), typmod); + + PG_RETURN_TIMETZADT_P(result); +} + static int timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2) diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 28ca77b64e..dd17ea36c7 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.67 2001/09/28 08:09:10 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.68 2001/10/03 05:29:24 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -26,8 +26,6 @@ #include "utils/datetime.h" -#define ROUND_ALL 1 - static int DecodeNumber(int flen, char *field, int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits); @@ -2173,8 +2171,27 @@ EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str) sec = (tm->tm_sec + fsec); - sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min); - sprintf((str + 6), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec); + sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min); + + /* If we have fractional seconds, then include a decimal point + * We will do up to 6 fractional digits, and we have rounded any inputs + * to eliminate anything to the right of 6 digits anyway. + * If there are no fractional seconds, then do not bother printing + * a decimal point at all. - thomas 2001-09-29 + */ + if (fsec != 0) { + sprintf((str + strlen(str)), ":%013.10f", sec); + /* chop off trailing pairs of zeros... */ + while ((strcmp((str + strlen(str) - 2), "00") == 0) + && (*(str + strlen(str) - 3) != '.')) + { + *(str + strlen(str) - 2) = '\0'; + } + } + else + { + sprintf((str + strlen(str)), ":%02.0f", sec); + } if (tzp != NULL) { @@ -2221,9 +2238,28 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha case USE_ISO_DATES: if (tm->tm_year > 0) { - sprintf(str, "%04d-%02d-%02d %02d:%02d:", + sprintf(str, "%04d-%02d-%02d %02d:%02d", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); - sprintf((str + strlen(str)), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec); + + /* If we have fractional seconds, then include a decimal point + * We will do up to 6 fractional digits, and we have rounded any inputs + * to eliminate anything to the right of 6 digits anyway. + * If there are no fractional seconds, then do not bother printing + * a decimal point at all. - thomas 2001-09-29 + */ + if (fsec != 0) { + sprintf((str + strlen(str)), ":%013.10f", sec); + /* chop off trailing pairs of zeros... */ + while ((strcmp((str + strlen(str) - 2), "00") == 0) + && (*(str + strlen(str) - 3) != '.')) + { + *(str + strlen(str) - 2) = '\0'; + } + } + else + { + sprintf((str + strlen(str)), ":%02.0f", sec); + } if ((*tzn != NULL) && (tm->tm_isdst >= 0)) { @@ -2261,8 +2297,28 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha if (tm->tm_year > 0) { - sprintf((str + 5), "/%04d %02d:%02d:%05.2f", - tm->tm_year, tm->tm_hour, tm->tm_min, sec); + sprintf((str + 5), "/%04d %02d:%02d", + tm->tm_year, tm->tm_hour, tm->tm_min); + + /* If we have fractional seconds, then include a decimal point + * We will do up to 6 fractional digits, and we have rounded any inputs + * to eliminate anything to the right of 6 digits anyway. + * If there are no fractional seconds, then do not bother printing + * a decimal point at all. - thomas 2001-09-29 + */ + if (fsec != 0) { + sprintf((str + strlen(str)), ":%013.10f", sec); + /* chop off trailing pairs of zeros... */ + while ((strcmp((str + strlen(str) - 2), "00") == 0) + && (*(str + strlen(str) - 3) != '.')) + { + *(str + strlen(str) - 2) = '\0'; + } + } + else + { + sprintf((str + strlen(str)), ":%02.0f", sec); + } if ((*tzn != NULL) && (tm->tm_isdst >= 0)) sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); @@ -2277,8 +2333,28 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon); if (tm->tm_year > 0) { - sprintf((str + 5), ".%04d %02d:%02d:%05.2f", - tm->tm_year, tm->tm_hour, tm->tm_min, sec); + sprintf((str + 5), ".%04d %02d:%02d", + tm->tm_year, tm->tm_hour, tm->tm_min); + + /* If we have fractional seconds, then include a decimal point + * We will do up to 6 fractional digits, and we have rounded any inputs + * to eliminate anything to the right of 6 digits anyway. + * If there are no fractional seconds, then do not bother printing + * a decimal point at all. - thomas 2001-09-29 + */ + if (fsec != 0) { + sprintf((str + strlen(str)), ":%013.10f", sec); + /* chop off trailing pairs of zeros... */ + while ((strcmp((str + strlen(str) - 2), "00") == 0) + && (*(str + strlen(str) - 3) != '.')) + { + *(str + strlen(str) - 2) = '\0'; + } + } + else + { + sprintf((str + strlen(str)), ":%02.0f", sec); + } if ((*tzn != NULL) && (tm->tm_isdst >= 0)) sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); @@ -2305,18 +2381,30 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha if (tm->tm_year > 0) { sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min); - if (fsec != 0) - { - sprintf((str + 16), ":%05.2f %04d", sec, tm->tm_year); - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) - sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); + + /* If we have fractional seconds, then include a decimal point + * We will do up to 6 fractional digits, and we have rounded any inputs + * to eliminate anything to the right of 6 digits anyway. + * If there are no fractional seconds, then do not bother printing + * a decimal point at all. - thomas 2001-09-29 + */ + if (fsec != 0) { + sprintf((str + strlen(str)), ":%013.10f", sec); + /* chop off trailing pairs of zeros... */ + while ((strcmp((str + strlen(str) - 2), "00") == 0) + && (*(str + strlen(str) - 3) != '.')) + { + *(str + strlen(str) - 2) = '\0'; + } } else { - sprintf((str + 16), ":%02.0f %04d", sec, tm->tm_year); - if ((*tzn != NULL) && (tm->tm_isdst >= 0)) - sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); + sprintf((str + strlen(str)), ":%02.0f", sec); } + + sprintf((str + strlen(str)), " %04d", tm->tm_year); + if ((*tzn != NULL) && (tm->tm_isdst >= 0)) + sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); } else { diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index f115657102..797586018d 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -5,7 +5,7 @@ * * 1998 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.43 2001/08/14 22:21:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.44 2001/10/03 05:29:24 thomas Exp $ * * ---------- */ @@ -193,10 +193,8 @@ Datum numeric_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); - #ifdef NOT_USED Oid typelem = PG_GETARG_OID(1); - #endif int32 typmod = PG_GETARG_INT32(2); NumericVar value; diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 1bd4268965..8bd0daf2bf 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.51 2001/09/28 08:09:11 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.52 2001/10/03 05:29:24 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,8 @@ static double time2t(const int hour, const int min, const double sec); static int EncodeSpecialTimestamp(Timestamp dt, char *str); static Timestamp dt2local(Timestamp dt, int timezone); +static void +AdjustTimestampForTypmod(Timestamp *time, int32 typmod); /***************************************************************************** @@ -45,6 +47,10 @@ Datum timestamp_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); Timestamp result; double fsec; struct tm tt, @@ -89,6 +95,8 @@ timestamp_in(PG_FUNCTION_ARGS) TIMESTAMP_NOEND(result); } + AdjustTimestampForTypmod(&result, typmod); + PG_RETURN_TIMESTAMP(result); } @@ -98,7 +106,7 @@ timestamp_in(PG_FUNCTION_ARGS) Datum timestamp_out(PG_FUNCTION_ARGS) { - Timestamp dt = PG_GETARG_TIMESTAMP(0); + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); char *result; struct tm tt, *tm = &tt; @@ -106,9 +114,9 @@ timestamp_out(PG_FUNCTION_ARGS) char *tzn = NULL; char buf[MAXDATELEN + 1]; - if (TIMESTAMP_NOT_FINITE(dt)) - EncodeSpecialTimestamp(dt, buf); - else if (timestamp2tm(dt, NULL, tm, &fsec, NULL) == 0) + if (TIMESTAMP_NOT_FINITE(timestamp)) + EncodeSpecialTimestamp(timestamp, buf); + else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0) EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf); else elog(ERROR, "Unable to format timestamp; internal coding error"); @@ -117,6 +125,42 @@ timestamp_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* timestamp_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +timestamp_scale(PG_FUNCTION_ARGS) +{ + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); + int32 typmod = PG_GETARG_INT32(1); + Timestamp result; + + result = timestamp; + + if (! TIMESTAMP_NOT_FINITE(result)) + AdjustTimestampForTypmod(&result, typmod); + + PG_RETURN_TIMESTAMP(result); +} + +static void +AdjustTimestampForTypmod(Timestamp *time, int32 typmod) +{ + if ((typmod >= 0) && (typmod <= 13)) + { + static double TimestampScale = 1; + static int32 TimestampTypmod = 0; + + if (typmod != TimestampTypmod) + TimestampScale = pow(10, typmod); + + *time = (rint(((double) *time)*TimestampScale)/TimestampScale); + } + + return; +} + /* timestamptz_in() * Convert a string to internal form. @@ -125,6 +169,10 @@ Datum timestamptz_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); TimestampTz result; double fsec; struct tm tt, @@ -169,6 +217,8 @@ timestamptz_in(PG_FUNCTION_ARGS) TIMESTAMP_NOEND(result); } + AdjustTimestampForTypmod(&result, typmod); + PG_RETURN_TIMESTAMPTZ(result); } @@ -198,6 +248,25 @@ timestamptz_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* timestamptz_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +timestamptz_scale(PG_FUNCTION_ARGS) +{ + TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); + int32 typmod = PG_GETARG_INT32(1); + TimestampTz result; + + result = timestamp; + + if (! TIMESTAMP_NOT_FINITE(result)) + AdjustTimestampForTypmod(&result, typmod); + + PG_RETURN_TIMESTAMPTZ(result); +} + /* interval_in() * Convert a string to internal form. @@ -2119,16 +2188,13 @@ timestamp_part(PG_FUNCTION_ARGS) text *units = PG_GETARG_TEXT_P(0); Timestamp timestamp = PG_GETARG_TIMESTAMP(1); float8 result; - int tz; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; - double dummy; double fsec; - char *tzn; struct tm tt, *tm = &tt; @@ -2152,24 +2218,10 @@ timestamp_part(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(result); } - if ((type == UNITS) && (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) == 0)) + if ((type == UNITS) && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)) { switch (val) { - case DTK_TZ: - result = tz; - break; - - case DTK_TZ_MINUTE: - result = tz / 60; - TMODULO(result, dummy, 60e0); - break; - - case DTK_TZ_HOUR: - dummy = tz; - TMODULO(dummy, result, 3600e0); - break; - case DTK_MICROSEC: result = (fsec * 1000000); break; @@ -2222,11 +2274,13 @@ timestamp_part(PG_FUNCTION_ARGS) result = (tm->tm_year / 1000); break; + case DTK_TZ: + case DTK_TZ_MINUTE: + case DTK_TZ_HOUR: default: elog(ERROR, "Timestamp units '%s' not supported", lowunits); result = 0; } - } else if (type == RESERV) { @@ -2237,14 +2291,14 @@ timestamp_part(PG_FUNCTION_ARGS) break; case DTK_DOW: - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0) elog(ERROR, "Unable to encode timestamp"); result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); break; case DTK_DOY: - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0) elog(ERROR, "Unable to encode timestamp"); result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index b142d126c1..7ed56e7962 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.82 2001/09/11 05:18:59 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.83 2001/10/03 05:29:24 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -33,7 +33,7 @@ * at CREATE TABLE time. * * It's hard to implement these types because we cannot figure out - * the length of the type from the type itself. I change (hopefully all) the + * the length of the type from the type itself. I changed (hopefully all) the * fmgr calls that invoke input functions of a data type to supply the * length also. (eg. in INSERTs, we have the tupleDescriptor which contains * the length of the attributes and hence the exact length of the char() or |
