mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Implement precision support for timestamp and time, both with and without
time zones. SQL99 spec requires a default of zero (round to seconds) which is set in gram.y as typmod is set in the parse tree. We *could* change to a default of either 6 (for internal compatibility with previous versions) or 2 (for external compatibility with previous versions). Evaluate entries in pg_proc wrt the iscachable attribute for timestamp and other date/time types. Try to recognize cases where side effects like the current time zone setting may have an effect on results to decide whether something is cachable or not.
This commit is contained in:
@@ -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);
|
||||
|
||||
PG_RETURN_TIMEADT(time);
|
||||
AdjustTimeForTypmod(&result, typmod);
|
||||
|
||||
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));
|
||||
|
||||
time->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
||||
time->zone = tz;
|
||||
result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
||||
result->zone = tz;
|
||||
|
||||
PG_RETURN_TIMETZADT_P(time);
|
||||
AdjustTimeForTypmod(&(result->time), typmod);
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user