diff --git a/src/common/backend/utils/adt/datetime.cpp b/src/common/backend/utils/adt/datetime.cpp index 1a48d2d6c87b227edc85b842f81bf872d9d4164e..9369230fe1f26ffc2de751540dcf50a76efff510 100644 --- a/src/common/backend/utils/adt/datetime.cpp +++ b/src/common/backend/utils/adt/datetime.cpp @@ -3553,11 +3553,18 @@ void EncodeDateTime(struct pg_tm* tm, fsec_t fsec, bool print_tz, int tz, const *str++ = '-'; str = pg_ultostr_zeropad_width_2(str, tm->tm_mday); *str++ = (style == USE_ISO_DATES) ? ' ' : 'T'; - str = pg_ultostr_zeropad_width_2(str, tm->tm_hour); - *str++ = ':'; - str = pg_ultostr_zeropad_width_2(str, tm->tm_min); - *str++ = ':'; - str = AppendTimestampSeconds(str, tm, fsec); + if (tm->tm_hour || tm->tm_min || tm->tm_sec || fsec) { + str = pg_ultostr_zeropad_width_2(str, tm->tm_hour); + *str++ = ':'; + str = pg_ultostr_zeropad_width_2(str, tm->tm_min); + *str++ = ':'; + str = AppendTimestampSeconds(str, tm, fsec); + } else { + constexpr char TIME_ZERO[] = "00:00:00"; + rc = memcpy_sp(str, MAXDATELEN + 1, TIME_ZERO, sizeof(TIME_ZERO)); + securec_check(rc, "\0", "\0"); + str += sizeof(TIME_ZERO) - 1; + } if (print_tz) str = EncodeTimezone(str, tz, style); break; diff --git a/src/common/backend/utils/adt/timestamp.cpp b/src/common/backend/utils/adt/timestamp.cpp index e50717aa6a4aa1faf79f2f6dee904a3c5cff1ae5..f1bf6ca006e99161db8bdc649b37a5fab95e7190 100644 --- a/src/common/backend/utils/adt/timestamp.cpp +++ b/src/common/backend/utils/adt/timestamp.cpp @@ -126,7 +126,7 @@ typedef struct { } generate_series_timestamptz_fctx; static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec); -static void EncodeSpecialTimestamp(Timestamp dt, char* str); +void EncodeSpecialTimestamp(Timestamp dt, char* str); static Timestamp dt2local(Timestamp dt, int timezone); static void AdjustTimestampForTypmod(Timestamp* time, int32 typmod); static void AdjustIntervalForTypmod(Interval* interval, int32 typmod); @@ -388,6 +388,20 @@ static void CheckNlsFormat() } } +void timestamp_out(Timestamp ts, char* buf) { + pg_tm tm; + fsec_t fsec; + + CheckNlsFormat(); + + if (TIMESTAMP_NOT_FINITE(ts)) + EncodeSpecialTimestamp(ts, buf); + else if (timestamp2tm(ts, NULL, &tm, &fsec, NULL, NULL) == 0) + EncodeDateTime(&tm, fsec, false, 0, NULL, u_sess->time_cxt.DateStyle, buf); + else + ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); +} + /* timestamp_out() * Convert a timestamp to external form. */ @@ -395,18 +409,9 @@ Datum timestamp_out(PG_FUNCTION_ARGS) { Timestamp timestamp = PG_GETARG_TIMESTAMP(0); char* result = NULL; - struct pg_tm tt, *tm = &tt; - fsec_t fsec; char buf[MAXDATELEN + 1]; - CheckNlsFormat(); - - if (TIMESTAMP_NOT_FINITE(timestamp)) - EncodeSpecialTimestamp(timestamp, buf); - else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) - EncodeDateTime(tm, fsec, false, 0, NULL, u_sess->time_cxt.DateStyle, buf); - else - ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); + timestamp_out(timestamp, buf); result = pstrdup(buf); PG_RETURN_CSTRING(result); @@ -1564,7 +1569,7 @@ static void AdjustIntervalForTypmod(Interval* interval, int32 typmod) /* EncodeSpecialTimestamp() * Convert reserved timestamp data type to string. */ -static void EncodeSpecialTimestamp(Timestamp dt, char* str) +void EncodeSpecialTimestamp(Timestamp dt, char* str) { int rc = 0; if (TIMESTAMP_IS_NOBEGIN(dt)) { @@ -1861,7 +1866,12 @@ int timestamp2tm(Timestamp dt, int* tzp, struct pg_tm* tm, fsec_t* fsec, const c return -1; j2date((int)date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); + + if (time == 0) { + tm->tm_hour = tm->tm_min = tm->tm_sec = *fsec = 0; + } else { + dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); + } #else time = dt; TMODULO(time, date, (double)SECS_PER_DAY); diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 030ff32e56939a1c7e3337ad9122c8240779004f..b9f43a02be7734eb6ec31322755bf204facc9a69 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -482,6 +482,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt) utils_cxt->varcharoutput_buffer = (char*)palloc0(256); utils_cxt->numericoutput_buffer = (char*)palloc0(64); utils_cxt->dateoutput_buffer = (char*)palloc0(MAXDATELEN + 1); + utils_cxt->timestamp_output_buffer = (char*)palloc0(MAXDATELEN + 1); (void)syscalllockInit(&utils_cxt->deleMemContextMutex); diff --git a/src/gausskernel/storage/access/common/printtup.cpp b/src/gausskernel/storage/access/common/printtup.cpp index 89159a6a922e26dc52c2d72285ea692497f4caca..6e1ac734c0af110bdd951bffa6d1aff12ebadfec 100644 --- a/src/gausskernel/storage/access/common/printtup.cpp +++ b/src/gausskernel/storage/access/common/printtup.cpp @@ -1315,6 +1315,13 @@ void printtup(TupleTableSlot *slot, DestReceiver *self) outputstr = output_date_out(DatumGetDateADT(attr)); } break; + case F_TIMESTAMP_OUT: { + outputstr = u_sess->utils_cxt.timestamp_output_buffer; + Timestamp ts = DatumGetTimestamp(attr); + + timestamp_out(ts, outputstr); + break; + } default: outputstr = OutputFunctionCall(&thisState->finfo, attr); need_free = true; diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 679a91b0c8e5f28eeeec76671d1211f5a87a31c7..771894b97e0596b982285a0bd3a5ca0fe8356622 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -707,6 +707,7 @@ typedef struct knl_u_utils_context { char* varcharoutput_buffer; char* numericoutput_buffer; char* dateoutput_buffer; + char* timestamp_output_buffer; syscalllock deleMemContextMutex; diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 71a3a39bb3f3a0779e43d407e681e1ef22705b6c..5bbc27397d8937147cdb9c88552cd322f878a310 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -287,6 +287,7 @@ extern int DetermineTimeZoneOffset(struct pg_tm* tm, pg_tz* tzp); extern void EncodeDateOnly(struct pg_tm* tm, int style, char* str); extern void EncodeTimeOnly(struct pg_tm* tm, fsec_t fsec, bool print_tz, int tz, int style, char* str); +extern void EncodeSpecialTimestamp(Timestamp dt, char* str); extern void EncodeDateTime(struct pg_tm* tm, fsec_t fsec, bool print_tz, int tz, const char* tzn, int style, char* str); extern void EncodeInterval(struct pg_tm* tm, fsec_t fsec, int style, char* str); diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index f2d02d82d90fd218f0eb78e48d5d4015c2473ec2..78d631db2a2e8e7c1924fd3f3a324239c674709c 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -280,6 +280,7 @@ extern TimestampTz time_t_to_timestamptz(pg_time_t tm); extern pg_time_t timestamptz_to_time_t(TimestampTz t); extern const char* timestamptz_to_str(TimestampTz t); +void timestamp_out(Timestamp ts, char* buf); extern int tm2timestamp(struct pg_tm* tm, const fsec_t fsec, const int* tzp, Timestamp* dt); extern int timestamp2tm(Timestamp dt, int* tzp, struct pg_tm* tm, fsec_t* fsec, const char** tzn, pg_tz* attimezone);