From e2252604404eedd326f1c4ec54e76973e95afd3a Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 1 Jul 2000 21:27:14 +0000 Subject: [PATCH] Back out Karels to_char changes. --- doc/src/sgml/func.sgml | 13 +- src/backend/utils/adt/formatting.c | 790 +++++++++++------------- src/test/regress/expected/timestamp.out | 64 +- 3 files changed, 406 insertions(+), 461 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 731f24902e..0023a28b0a 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -785,11 +785,11 @@ W - week of month (1-5) where first week start on the first day of the month + week of month WW - week number of year (1-53) where first week start on the first day of the year + week number of year CC @@ -871,12 +871,9 @@ to_timestamp and to_date - skip multiple blank space in converted string if the FX option - is not used. FX must be specified as the first item - in the template; for example - to_timestamp('2000 JUN','YYYY MON') is right, but - to_timestamp('2000 JUN','FXYYYY MON') returns error, - because to_timestamp() expects one blank space only. + skip blank space if the FX option is + not used. FX must be specified as the first item + in the template. diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index f7e38aaa13..be11b5300f 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,8 +1,7 @@ - /* ----------------------------------------------------------------------- * formatting.c * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.15 2000/07/01 14:10:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.16 2000/07/01 21:27:11 momjian Exp $ * * * Portions Copyright (c) 1999-2000, PostgreSQL, Inc @@ -68,8 +67,11 @@ #include "postgres.h" #include "utils/builtins.h" -#include "utils/pg_locale.h" +#include "utils/date.h" +#include "utils/datetime.h" #include "utils/formatting.h" +#include "utils/int8.h" +#include "utils/pg_locale.h" /* ---------- * Routines type @@ -103,8 +105,8 @@ * External (defined in PgSQL dt.c (timestamp utils)) * ---------- */ -extern char *months[], /* month abbreviation */ - *days[]; /* full days */ +extern char *months[], /* month abbreviation */ + *days[]; /* full days */ /* ---------- * Format parser structs @@ -112,27 +114,27 @@ extern char *months[], /* month abbreviation */ */ typedef struct { - char *name; /* suffix string */ - int len, /* suffix length */ - id, /* used in node->suffix */ - type; /* prefix / postfix */ + char *name; /* suffix string */ + int len, /* suffix length */ + id, /* used in node->suffix */ + type; /* prefix / postfix */ } KeySuffix; typedef struct { - char *name; /* keyword */ - /* action for keyword */ - int len, /* keyword length */ - (*action) (), - id; /* keyword id */ + char *name; /* keyword */ + /* action for keyword */ + int len, /* keyword length */ + (*action) (), + id; /* keyword id */ } KeyWord; typedef struct { - int type; /* node type */ - KeyWord *key; /* if node type is KEYWORD */ - int character, /* if node type is CHAR */ - suffix; /* keyword suffix */ + int type; /* node type */ + KeyWord *key; /* if node type is KEYWORD */ + int character, /* if node type is CHAR */ + suffix; /* keyword suffix */ } FormatNode; #define NODE_TYPE_END 1 @@ -232,12 +234,20 @@ static char *numth[] = {"st", "nd", "rd", "th", NULL}; #define TH_LOWER 2 +#ifdef DEBUG_TO_FROM_CHAR +#define NOTICE_TM {\ + elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\ + tm->tm_sec, tm->tm_year,\ + tm->tm_min, tm->tm_wday, tm->tm_hour, tm->tm_yday,\ + tm->tm_mday, tm->tm_isdst,tm->tm_mon);\ + } +#endif /* ---------- * Flags for DCH version * ---------- */ -static int DCH_global_flag = 0; +static int DCH_global_flag = 0; #define DCH_F_FX 0x01 @@ -250,15 +260,15 @@ static int DCH_global_flag = 0; */ typedef struct { - int pre, /* (count) numbers before decimal */ - post, /* (count) numbers after decimal */ - lsign, /* want locales sign */ - flag, /* number parametrs */ - pre_lsign_num, /* tmp value for lsign */ - multi, /* multiplier for 'V' */ - zero_start, /* position of first zero */ - zero_end, /* position of last zero */ - need_locale; /* needs it locale */ + int pre, /* (count) numbers before decimal */ + post, /* (count) numbers after decimal */ + lsign, /* want locales sign */ + flag, /* number parametrs */ + pre_lsign_num, /* tmp value for lsign */ + multi, /* multiplier for 'V' */ + zero_start, /* position of first zero */ + zero_end, /* position of last zero */ + need_locale; /* needs it locale */ } NUMDesc; /* ---------- @@ -268,14 +278,14 @@ typedef struct #define NUM_F_DECIMAL 0x01 #define NUM_F_LDECIMAL 0x02 #define NUM_F_ZERO 0x04 -#define NUM_F_BLANK 0x08 +#define NUM_F_BLANK 0x08 #define NUM_F_FILLMODE 0x10 -#define NUM_F_LSIGN 0x20 +#define NUM_F_LSIGN 0x20 #define NUM_F_BRACKET 0x40 -#define NUM_F_MINUS 0x80 +#define NUM_F_MINUS 0x80 #define NUM_F_PLUS 0x100 -#define NUM_F_ROMAN 0x200 -#define NUM_F_MULTI 0x400 +#define NUM_F_ROMAN 0x200 +#define NUM_F_MULTI 0x400 #define NUM_LSIGN_PRE -1 #define NUM_LSIGN_POST 1 @@ -287,20 +297,20 @@ typedef struct */ #define IS_DECIMAL(_f) ((_f)->flag & NUM_F_DECIMAL) #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL) -#define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO) +#define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO) #define IS_BLANK(_f) ((_f)->flag & NUM_F_BLANK) #define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE) #define IS_BRACKET(_f) ((_f)->flag & NUM_F_BRACKET) #define IS_MINUS(_f) ((_f)->flag & NUM_F_MINUS) #define IS_LSIGN(_f) ((_f)->flag & NUM_F_LSIGN) -#define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS) +#define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS) #define IS_ROMAN(_f) ((_f)->flag & NUM_F_ROMAN) #define IS_MULTI(_f) ((_f)->flag & NUM_F_MULTI) /* ---------- * Format picture cache * (cache size: - * Number part = NUM_CACHE_SIZE * NUM_CACHE_FIELDS + * Number part = NUM_CACHE_SIZE * NUM_CACHE_FIELDS * Date-time part = DCH_CACHE_SIZE * DCH_CACHE_FIELDS * ) * ---------- @@ -314,14 +324,14 @@ typedef struct { FormatNode format[DCH_CACHE_SIZE + 1]; char str[DCH_CACHE_SIZE + 1]; - int age; + int age; } DCHCacheEntry; typedef struct { FormatNode format[NUM_CACHE_SIZE + 1]; char str[NUM_CACHE_SIZE + 1]; - int age; + int age; NUMDesc Num; } NUMCacheEntry; @@ -337,50 +347,12 @@ static int NUMCounter = 0; #define MAX_INT32 (2147483640) -/* ---------- - * For char->date/time conversion - * ---------- - */ -typedef struct { - int hh, am, pm, mi, ss, ssss, d, dd, ddd, mm, yyyy, bc, ww, w, cc, q, j; -} TmFromChar; - -#define ZERO_tmfc( _X ) \ - do { \ - (_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \ - (_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->bc= \ - (_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \ - } while(0) - -#ifdef DEBUG_TO_FROM_CHAR - -#define NOTICE_TMFC \ - elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nyyyy %d\nbc %d\nww %d\nw %d\ncc %d\nq %d\nj %d", \ - tmfc->hh, tmfc->am, tmfc->pm, tmfc->mi, tmfc->ss, \ - tmfc->ssss, tmfc->d, tmfc->dd, tmfc->ddd, tmfc->mm, \ - tmfc->yyyy, tmfc->bc, tmfc->ww, tmfc->w, tmfc->cc, \ - tmfc->q, tmfc->j); - -#define NOTICE_TM \ - elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\ - tm->tm_sec, tm->tm_year,\ - tm->tm_min, tm->tm_wday, tm->tm_hour, tm->tm_yday,\ - tm->tm_mday, tm->tm_isdst,tm->tm_mon) -#endif - -#define ZERO_tm( _X ) \ - do { \ - (_X)->tm_sec = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \ - (_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \ - (_X)->tm_mday = (_X)->tm_mon = 1; \ - } while (0); - /* ---------- * Private global-modul definitions * ---------- */ -static struct tm _tm, *tm = &_tm; -static TmFromChar _tmfc, *tmfc = &_tmfc; +static struct tm _tm, + *tm = &_tm; /* ---------- * Utils @@ -857,6 +829,7 @@ index_seq_search(char *str, KeyWord *kw, int *index) if ((poz = *(index + (*str - ' '))) > -1) { + KeyWord *k = kw + poz; do @@ -1190,6 +1163,7 @@ DCH_processor(FormatNode *node, char *inout, int flag) { if (n->type == NODE_TYPE_ACTION) { + int len; /* ---------- @@ -1201,15 +1175,18 @@ DCH_processor(FormatNode *node, char *inout, int flag) s += len; else if (len == -1) continue; + } else { + /* ---------- * Remove to output char from input in TO_CHAR * ---------- */ if (flag == TO_CHAR) *s = n->character; + else { /* ---------- @@ -1218,12 +1195,14 @@ DCH_processor(FormatNode *node, char *inout, int flag) */ if (isspace(n->character) && IS_FX == 0) { - while (*s != '\0' && isspace(*(s + 1))) + while (*s != '\0' && isspace((int) *(s + 1))) ++s; } } } + ++s; /* ! */ + } if (flag == TO_CHAR) @@ -1282,14 +1261,17 @@ static char * get_th(char *num, int type) { int len = strlen(num), - last; + last, seclast; last = *(num + (len - 1)); if (!isdigit((unsigned char) last)) elog(ERROR, "get_th: '%s' is not number.", num); - /* 11 || 12 */ - if (len == 2 && (last == '1' || last == '2') && *num == '1') + /* + * All "teens" (1[0-9]) get 'TH/th', + * while [02-9][123] still get 'ST/st', 'ND/nd', 'RD/rd', respectively + */ + if ((len > 1) && ((seclast = num[len-2]) == '1')) last = 0; switch (last) @@ -1529,15 +1511,14 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node) { switch (arg) { - case DCH_FX: - DCH_global_flag |= DCH_F_FX; - break; + + case DCH_FX: + DCH_global_flag |= DCH_F_FX; + break; } return -1; } -#define AMPM_ERROR elog(ERROR, "to_timestamp(): bad AM/PM string") - /* ---------- * Master function of TIME for: * TO_CHAR - write (inout) formated string @@ -1551,82 +1532,67 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) switch (arg) { - case DCH_A_M: + + case DCH_A_M: case DCH_P_M: if (flag == TO_CHAR) { - strcpy(inout, ((tm->tm_hour > 11 - && tm->tm_hour < 24) ? P_M_STR : A_M_STR)); + strcpy(inout, (tm->tm_hour > 13 ? P_M_STR : A_M_STR)); return 3; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, P_M_STR, 4) == 0) - tmfc->pm = TRUE; - else if (strncmp(inout, A_M_STR, 4) == 0) - tmfc->am = TRUE; - else - AMPM_ERROR; + if (strncmp(inout, P_M_STR, 4) == 0 && tm->tm_hour < 13) + tm->tm_hour += 12; return 3; } - break; + case DCH_AM: case DCH_PM: if (flag == TO_CHAR) { - strcpy(inout, ((tm->tm_hour > 11 - && tm->tm_hour < 24) ? PM_STR : AM_STR)); + strcpy(inout, (tm->tm_hour > 13 ? PM_STR : AM_STR)); return 1; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, PM_STR, 2) == 0) - tmfc->pm = TRUE; - else if (strncmp(inout, AM_STR, 2) == 0) - tmfc->am = TRUE; - else - AMPM_ERROR; + if (strncmp(inout, PM_STR, 2) == 0 && tm->tm_hour < 13) + tm->tm_hour += 12; return 1; } - break; + case DCH_a_m: case DCH_p_m: if (flag == TO_CHAR) { - strcpy(inout, ((tm->tm_hour > 11 - && tm->tm_hour < 24) ? p_m_STR : a_m_STR)); + strcpy(inout, (tm->tm_hour > 13 ? p_m_STR : a_m_STR)); return 3; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, p_m_STR, 4) == 0) - tmfc->pm = TRUE; - else if (strncmp(inout, a_m_STR, 4) == 0) - tmfc->am = TRUE; - else - AMPM_ERROR; + if (strncmp(inout, p_m_STR, 4) == 0 && tm->tm_hour < 13) + tm->tm_hour += 12; return 3; } - break; + case DCH_am: case DCH_pm: if (flag == TO_CHAR) { - strcpy(inout, ((tm->tm_hour > 11 - && tm->tm_hour < 24) ? pm_STR : am_STR)); + strcpy(inout, (tm->tm_hour > 13 ? pm_STR : am_STR)); return 1; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, pm_STR, 2) == 0) - tmfc->pm = TRUE; - else if (strncmp(inout, am_STR, 2) == 0) - tmfc->am = TRUE; - else - AMPM_ERROR; + if (strncmp(inout, pm_STR, 2) == 0 && tm->tm_hour < 13) + tm->tm_hour += 12; return 1; } - break; + case DCH_HH: case DCH_HH12: if (flag == TO_CHAR) @@ -1640,21 +1606,22 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 1; + } else if (flag == FROM_CHAR) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->hh); - return int4len((int4) tmfc->hh) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_hour); + return int4len((int4) tm->tm_hour) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->hh); + sscanf(inout, "%02d", &tm->tm_hour); return 1 + SKIP_THth(suf); } } - break; + case DCH_HH24: if (flag == TO_CHAR) { @@ -1671,16 +1638,16 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->hh); - return int4len((int4) tmfc->hh) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_hour); + return int4len((int4) tm->tm_hour) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->hh); + sscanf(inout, "%02d", &tm->tm_hour); return 1 + SKIP_THth(suf); } } - break; + case DCH_MI: if (flag == TO_CHAR) { @@ -1697,16 +1664,15 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->mi); - return int4len((int4) tmfc->mi) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_min); + return int4len((int4) tm->tm_min) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->mi); + sscanf(inout, "%02d", &tm->tm_min); return 1 + SKIP_THth(suf); } } - break; case DCH_SS: if (flag == TO_CHAR) { @@ -1717,21 +1683,21 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 1; + } else if (flag == FROM_CHAR) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->ss); - return int4len((int4) tmfc->ss) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_sec); + return int4len((int4) tm->tm_sec) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->ss); + sscanf(inout, "%02d", &tm->tm_sec); return 1 + SKIP_THth(suf); } } - break; case DCH_SSSS: if (flag == TO_CHAR) { @@ -1742,12 +1708,8 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout) - 1; } - else if (flag == FROM_CHAR) - { - sscanf(inout, "%d", &tmfc->ssss); - return int4len((int4) tmfc->ssss) - 1 + SKIP_THth(suf); - } - break; + else if (flag == FROM_CHAR) + elog(ERROR, "to_timestamp(): SSSS is not supported"); } return -1; } @@ -1784,94 +1746,117 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) { if (arg == DCH_MONTH || arg == DCH_Month || arg == DCH_month) { - tmfc->mm = seq_search(inout, months_full, ONE_UPPER, FULL_SIZ, &len) +1; + + tm->tm_mon = seq_search(inout, months_full, ONE_UPPER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "MONTH/Month/month"); + ++tm->tm_mon; if (S_FM(suf)) return len - 1; else return 8; + } else if (arg == DCH_MON || arg == DCH_Mon || arg == DCH_mon) { - tmfc->mm = seq_search(inout, months, ONE_UPPER, MAX_MON_LEN, &len) +1; + + tm->tm_mon = seq_search(inout, months, ONE_UPPER, MAX_MON_LEN, &len); CHECK_SEQ_SEARCH(len, "MON/Mon/mon"); + ++tm->tm_mon; return 2; + } else if (arg == DCH_DAY || arg == DCH_Day || arg == DCH_day) { - tmfc->d = seq_search(inout, days, ONE_UPPER, FULL_SIZ, &len); + + tm->tm_wday = seq_search(inout, days, ONE_UPPER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "DAY/Day/day"); if (S_FM(suf)) return len - 1; else return 8; + } else if (arg == DCH_DY || arg == DCH_Dy || arg == DCH_dy) { - tmfc->d = seq_search(inout, days, ONE_UPPER, MAX_DY_LEN, &len); + + tm->tm_wday = seq_search(inout, days, ONE_UPPER, MAX_DY_LEN, &len); CHECK_SEQ_SEARCH(len, "DY/Dy/dy"); return 2; + } } switch (arg) { + case DCH_A_D: case DCH_B_C: if (flag == TO_CHAR) { strcpy(inout, (tm->tm_year < 0 ? B_C_STR : A_D_STR)); return 3; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, B_C_STR, 4) == 0) - tmfc->bc = TRUE; + if (strncmp(inout, B_C_STR, 4) == 0 && tm->tm_year > 0) + tm->tm_year = -(tm->tm_year); + if (tm->tm_year < 0) + tm->tm_year = tm->tm_year + 1; return 3; } - break; + case DCH_AD: case DCH_BC: if (flag == TO_CHAR) { strcpy(inout, (tm->tm_year < 0 ? BC_STR : AD_STR)); return 1; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, BC_STR, 2) == 0) - tmfc->bc = TRUE; + if (strncmp(inout, BC_STR, 2) == 0 && tm->tm_year > 0) + tm->tm_year = -(tm->tm_year); + if (tm->tm_year < 0) + tm->tm_year = tm->tm_year + 1; return 1; } - break; + case DCH_a_d: case DCH_b_c: if (flag == TO_CHAR) { strcpy(inout, (tm->tm_year < 0 ? b_c_STR : a_d_STR)); return 3; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, b_c_STR, 4) == 0) - tmfc->bc = TRUE; + if (strncmp(inout, b_c_STR, 4) == 0 && tm->tm_year > 0) + tm->tm_year = -(tm->tm_year); + if (tm->tm_year < 0) + tm->tm_year = tm->tm_year + 1; return 3; } - break; + case DCH_ad: case DCH_bc: if (flag == TO_CHAR) { strcpy(inout, (tm->tm_year < 0 ? bc_STR : ad_STR)); return 1; + } else if (flag == FROM_CHAR) { - if (strncmp(inout, bc_STR, 2) == 0) - tmfc->bc = TRUE; + if (strncmp(inout, bc_STR, 2) == 0 && tm->tm_year > 0) + tm->tm_year = -(tm->tm_year); + if (tm->tm_year < 0) + tm->tm_year = tm->tm_year + 1; return 1; } - break; + case DCH_MONTH: strcpy(inout, months_full[tm->tm_mon - 1]); sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout)); @@ -1879,14 +1864,14 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 8; - + case DCH_Month: sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); if (S_FM(suf)) return strlen(p_inout) - 1; else return 8; - + case DCH_month: sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); *inout = tolower(*inout); @@ -1894,12 +1879,12 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 8; - + case DCH_MON: strcpy(inout, months[tm->tm_mon - 1]); inout = str_toupper(inout); return 2; - + case DCH_Mon: strcpy(inout, months[tm->tm_mon - 1]); return 2; @@ -1919,21 +1904,22 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 1; + } else if (flag == FROM_CHAR) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->mm); - return int4len((int4) tmfc->mm) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_mon); + return int4len((int4) tm->tm_mon) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->mm); + sscanf(inout, "%02d", &tm->tm_mon); return 1 + SKIP_THth(suf); } } - break; + case DCH_DAY: strcpy(inout, days[tm->tm_wday]); sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout)); @@ -1981,21 +1967,22 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 2; + } else if (flag == FROM_CHAR) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->ddd); - return int4len((int4) tmfc->ddd) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_yday); + return int4len((int4) tm->tm_yday) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%03d", &tmfc->ddd); + sscanf(inout, "%03d", &tm->tm_yday); return 2 + SKIP_THth(suf); } } - break; + case DCH_DD: if (flag == TO_CHAR) { @@ -2006,21 +1993,21 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 1; + } else if (flag == FROM_CHAR) { if (S_FM(suf)) { - sscanf(inout, "%d", &tmfc->dd); - return int4len((int4) tmfc->dd) - 1 + SKIP_THth(suf); + sscanf(inout, "%d", &tm->tm_mday); + return int4len((int4) tm->tm_mday) - 1 + SKIP_THth(suf); } else { - sscanf(inout, "%02d", &tmfc->dd); + sscanf(inout, "%02d", &tm->tm_mday); return 1 + SKIP_THth(suf); } } - break; case DCH_D: if (flag == TO_CHAR) { @@ -2034,15 +2021,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) } else if (flag == FROM_CHAR) { - sscanf(inout, "%1d", &tmfc->d); + sscanf(inout, "%1d", &tm->tm_wday); + if (tm->tm_wday) + --tm->tm_wday; return 0 + SKIP_THth(suf); } - break; + case DCH_WW: if (flag == TO_CHAR) { sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, - (tm->tm_yday-1) / 7 + 1); + (tm->tm_yday - tm->tm_wday + 7) / 7); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); if (S_FM(suf) || S_THth(suf)) @@ -2051,20 +2040,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return 1; } - else if (flag == FROM_CHAR) - { - if (S_FM(suf)) - { - sscanf(inout, "%d", &tmfc->ww); - return int4len((int4) tmfc->ww) - 1 + SKIP_THth(suf); - } - else - { - sscanf(inout, "%02d", &tmfc->ww); - return 1 + SKIP_THth(suf); - } - } - break; + else if (flag == FROM_CHAR) + elog(ERROR, "to_datatime(): WW is not supported"); case DCH_Q: if (flag == TO_CHAR) { @@ -2078,11 +2055,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) } else if (flag == FROM_CHAR) - { - sscanf(inout, "%1d", &tmfc->q); - return 0 + SKIP_THth(suf); - } - break; + elog(ERROR, "to_datatime(): Q is not supported"); + case DCH_CC: if (flag == TO_CHAR) { @@ -2097,11 +2071,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) } else if (flag == FROM_CHAR) - { - sscanf(inout, "%d", &tmfc->cc); - return int4len((int4) tmfc->cc) + SKIP_THth(suf) -1; - } - break; + elog(ERROR, "to_datatime(): CC is not supported"); case DCH_Y_YYY: if (flag == TO_CHAR) { @@ -2109,23 +2079,35 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) sprintf(inout, "%d,%03d", i, YEAR_ABS(tm->tm_year) - (i * 1000)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); + + /* + * if (tm->tm_year < 0) strcat(inout, BC_STR_ORIG); + */ return strlen(p_inout) - 1; + } else if (flag == FROM_CHAR) { - int cc; + int cc, + yy; - sscanf(inout, "%d,%03d", &cc, &tmfc->yyyy); - tmfc->yyyy += (cc * 1000); + sscanf(inout, "%d,%03d", &cc, &yy); + tm->tm_year = (cc * 1000) + yy; - if (!S_FM(suf) && tmfc->yyyy <= 9999 && tmfc->yyyy >= -9999) + if (!S_FM(suf) && tm->tm_year <= 9999 && tm->tm_year >= -9999) len = 5; else - len = int4len((int4) tmfc->yyyy) + 1; + len = int4len((int4) tm->tm_year) + 1; len += SKIP_THth(suf); + + /* + * AC/BC if (is_acdc(inout+len, &len) < 0 && tm->tm_year > + * 0) tm->tm_year = -(tm->tm_year); if (tm->tm_year < 0) + * tm->tm_year = tm->tm_year+1; + */ return len - 1; } - break; + case DCH_YYYY: if (flag == TO_CHAR) { @@ -2135,19 +2117,30 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) sprintf(inout, "%d", YEAR_ABS(tm->tm_year)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); + + /* + * if (tm->tm_year < 0) strcat(inout, BC_STR_ORIG); + */ return strlen(p_inout) - 1; + } else if (flag == FROM_CHAR) { - sscanf(inout, "%d", &tmfc->yyyy); - if (!S_FM(suf) && tmfc->yyyy <= 9999 && tmfc->yyyy >= -9999) + sscanf(inout, "%d", &tm->tm_year); + if (!S_FM(suf) && tm->tm_year <= 9999 && tm->tm_year >= -9999) len = 4; else - len = int4len((int4) tmfc->yyyy); + len = int4len((int4) tm->tm_year); len += SKIP_THth(suf); + + /* + * AC/BC if (is_acdc(inout+len, &len) < 0 && tm->tm_year > + * 0) tm->tm_year = -(tm->tm_year); if (tm->tm_year < 0) + * tm->tm_year = tm->tm_year+1; + */ return len - 1; } - break; + case DCH_YYY: if (flag == TO_CHAR) { @@ -2160,13 +2153,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return 4; } return 2; + } else if (flag == FROM_CHAR) { - sscanf(inout, "%03d", &tmfc->yyyy); + int yy; + + sscanf(inout, "%03d", &yy); + tm->tm_year = (tm->tm_year / 1000) * 1000 + yy; return 2 + SKIP_THth(suf); } - break; + case DCH_YY: if (flag == TO_CHAR) { @@ -2179,13 +2176,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return 3; } return 1; + } else if (flag == FROM_CHAR) { - sscanf(inout, "%02d", &tmfc->yyyy); + int yy; + + sscanf(inout, "%02d", &yy); + tm->tm_year = (tm->tm_year / 100) * 100 + yy; return 1 + SKIP_THth(suf); } - break; + case DCH_Y: if (flag == TO_CHAR) { @@ -2202,10 +2203,13 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) } else if (flag == FROM_CHAR) { - sscanf(inout, "%1d", &tmfc->yyyy); + int yy; + + sscanf(inout, "%1d", &yy); + tm->tm_year = (tm->tm_year / 10) * 10 + yy; return 0 + SKIP_THth(suf); } - break; + case DCH_RM: if (flag == TO_CHAR) { @@ -2215,17 +2219,19 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; else return 3; + } else if (flag == FROM_CHAR) { - tmfc->mm = 12 - seq_search(inout, rm_months_upper, ALL_UPPER, FULL_SIZ, &len); + tm->tm_mon = 11 - seq_search(inout, rm_months_upper, ALL_UPPER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "RM"); + ++tm->tm_mon; if (S_FM(suf)) return len - 1; else return 3; } - break; + case DCH_rm: if (flag == TO_CHAR) { @@ -2239,31 +2245,30 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) } else if (flag == FROM_CHAR) { - tmfc->mm = 12 - seq_search(inout, rm_months_lower, ALL_UPPER, FULL_SIZ, &len); + tm->tm_mon = 11 - seq_search(inout, rm_months_lower, ALL_UPPER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "rm"); + ++tm->tm_mon; if (S_FM(suf)) return len - 1; else return 3; } - break; + case DCH_W: if (flag == TO_CHAR) { - sprintf(inout, "%d", (tm->tm_mday-1) / 7 + 1); + sprintf(inout, "%d", (tm->tm_mday - tm->tm_wday + 7) / 7); if (S_THth(suf)) { str_numth(p_inout, inout, S_TH_TYPE(suf)); return 2; } return 0; + } else if (flag == FROM_CHAR) - { - sscanf(inout, "%1d", &tmfc->w); - return 0 + SKIP_THth(suf); - } - break; + elog(ERROR, "to_datatime(): W is not supported"); + case DCH_J: if (flag == TO_CHAR) { @@ -2273,11 +2278,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node) return strlen(p_inout) - 1; } else if (flag == FROM_CHAR) - { - sscanf(inout, "%d", &tmfc->j); - return int4len((int4) tmfc->j) + SKIP_THth(suf) -1; - } - break; + elog(ERROR, "to_datatime(): J is not supported"); } return -1; } @@ -2369,7 +2370,6 @@ DCH_cache_search(char *str) } - /**************************************************************************** * Public routines ***************************************************************************/ @@ -2378,9 +2378,11 @@ DCH_cache_search(char *str) * TIMESTAMP to_char() * ------------------- */ -text * -timestamp_to_char(Timestamp *dt, text *fmt) +Datum +timestamp_to_char(PG_FUNCTION_ARGS) { + Timestamp dt = PG_GETARG_TIMESTAMP(0); + text *fmt = PG_GETARG_TEXT_P(1); text *result, *result_tmp; FormatNode *format; @@ -2392,26 +2394,33 @@ timestamp_to_char(Timestamp *dt, text *fmt) flag = 0, x = 0; - if ((!PointerIsValid(dt)) || (!PointerIsValid(fmt))) - return NULL; - len = VARSIZE(fmt) - VARHDRSZ; - if ((!len) || (TIMESTAMP_NOT_FINITE(*dt))) - return textin(""); + if ((!len) || (TIMESTAMP_NOT_FINITE(dt))) + return PointerGetDatum(textin("")); - ZERO_tm( tm ); + tm->tm_sec = 0; + tm->tm_year = 0; + tm->tm_min = 0; + tm->tm_wday = 0; + tm->tm_hour = 0; + tm->tm_yday = 0; + tm->tm_mday = 1; + tm->tm_isdst = 0; + tm->tm_mon = 1; - if (TIMESTAMP_IS_EPOCH(*dt)) + if (TIMESTAMP_IS_EPOCH(dt)) { - x = timestamp2tm(SetTimestamp(*dt), NULL, tm, &fsec, NULL); + x = timestamp2tm(SetTimestamp(dt), NULL, tm, &fsec, NULL); + } - else if (TIMESTAMP_IS_CURRENT(*dt)) + else if (TIMESTAMP_IS_CURRENT(dt)) { - x = timestamp2tm(SetTimestamp(*dt), &tz, tm, &fsec, &tzn); + x = timestamp2tm(SetTimestamp(dt), &tz, tm, &fsec, &tzn); + } else - x = timestamp2tm(*dt, &tz, tm, &fsec, &tzn); + x = timestamp2tm(dt, &tz, tm, &fsec, &tzn); if (x != 0) elog(ERROR, "to_char(): Unable to convert timestamp to tm"); @@ -2437,9 +2446,10 @@ timestamp_to_char(Timestamp *dt, text *fmt) * Allocate new memory if format picture is bigger than static cache * and not use cache (call parser always) - flag=1 show this variant * ---------- - */ + */ if (len > DCH_CACHE_SIZE) { + format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode)); flag = 1; @@ -2447,9 +2457,11 @@ timestamp_to_char(Timestamp *dt, text *fmt) DCH_suff, DCH_index, DCH_TYPE, NULL); (format + len)->type = NODE_TYPE_END; /* Paranoa? */ + } else { + /* ---------- * Use cache buffers * ---------- @@ -2501,7 +2513,7 @@ timestamp_to_char(Timestamp *dt, text *fmt) VARSIZE(result) = len + VARHDRSZ; pfree(result_tmp); - return result; + PG_RETURN_TEXT_P(result); } @@ -2512,28 +2524,34 @@ timestamp_to_char(Timestamp *dt, text *fmt) * ( to_timestamp is reverse to_char() ) * --------------------- */ -Timestamp * -to_timestamp(text *date_str, text *fmt) +Datum +to_timestamp(PG_FUNCTION_ARGS) { - FormatNode *format; - int flag = 0; - Timestamp *result; - char *str; - int len = 0, - fsec = 0, - tz = 0, - x = 0; + text *date_str = PG_GETARG_TEXT_P(0); + text *fmt = PG_GETARG_TEXT_P(1); + FormatNode *format; + int flag = 0; + Timestamp result; + char *str; + int len = 0, + fsec = 0, + tz = 0; - if ((!PointerIsValid(date_str)) || (!PointerIsValid(fmt))) - return NULL; + tm->tm_sec = 0; + tm->tm_year = 0; + tm->tm_min = 0; + tm->tm_wday = 0; + tm->tm_hour = 0; + tm->tm_yday = 0; + tm->tm_mday = 1; + tm->tm_isdst = 0; + tm->tm_mon = 1; - result = palloc(sizeof(Timestamp)); - len = VARSIZE(fmt) - VARHDRSZ; - - ZERO_tmfc(tmfc); + len = VARSIZE(fmt) - VARHDRSZ; if (len) { + /* ---------- * Convert VARDATA() to string * ---------- @@ -2549,6 +2567,7 @@ to_timestamp(text *date_str, text *fmt) */ if (len > DCH_CACHE_SIZE) { + format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode)); flag = 1; @@ -2559,6 +2578,7 @@ to_timestamp(text *date_str, text *fmt) } else { + /* ---------- * Use cache buffers * ---------- @@ -2569,6 +2589,7 @@ to_timestamp(text *date_str, text *fmt) if ((ent = DCH_cache_search(str)) == NULL) { + ent = DCH_cache_getnew(str); /* ---------- @@ -2604,101 +2625,6 @@ to_timestamp(text *date_str, text *fmt) pfree(format); } - /* -------------------------------------------------------------- - * Convert values that user define for FROM_CHAR (to_date/to_timestamp) - * to standard 'tm' - * ---------- - */ - ZERO_tm( tm ); - -#ifdef DEBUG_TO_FROM_CHAR - NOTICE_TMFC; -#endif - if (tmfc->ssss) - { - if (tmfc->ssss > 3600) - tm->tm_sec = x - ((tm->tm_min = (x = tmfc->ssss - - ((tm->tm_hour= tmfc->ssss / 3600) * 3600)) / 60) * 60); - else if (tmfc->ssss > 60) - tm->tm_sec = tmfc->ssss - ((tm->tm_min = tmfc->ssss / 60) * 60); - else - tm->tm_sec = tmfc->ssss; - } - - if (tmfc->cc) - tm->tm_year = (tmfc->cc-1) * 100; - - if (tmfc->ww) - tmfc->ddd = (tmfc->ww - 1) * 7 + 1; - - if (tmfc->w) - tmfc->dd = (tmfc->w - 1) * 7 + 1; - - if (tmfc->ss) tm->tm_sec = tmfc->ss; - if (tmfc->mi) tm->tm_min = tmfc->mi; - if (tmfc->hh) tm->tm_hour = tmfc->hh; - - if (tmfc->pm || tmfc->am) - { - if (tm->tm_hour < 1 || tm->tm_hour > 12) - elog(ERROR, "to_timestamp(): AM/PM hour must be between 1 and 12"); - - if (tmfc->pm && tm->tm_hour < 12) - tm->tm_hour += 12; - - else if (tmfc->am && tm->tm_hour == 12) - tm->tm_hour = 0; - } - - switch (tmfc->q) - { - case 1: tm->tm_mday = 1; tm->tm_mon = 1; break; - case 2: tm->tm_mday = 1; tm->tm_mon = 4; break; - case 3: tm->tm_mday = 1; tm->tm_mon = 7; break; - case 4: tm->tm_mday = 1; tm->tm_mon = 10; break; - } - - if (tmfc->j) - j2date(tmfc->j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - if (tmfc->yyyy) - tm->tm_year = tmfc->yyyy; - if (tmfc->bc && tm->tm_year > 0) - tm->tm_year = -(tm->tm_year); - if (tm->tm_year < 0) - tm->tm_year = tm->tm_year + 1; - if (tmfc->d) tm->tm_wday = tmfc->d; - if (tmfc->dd) tm->tm_mday = tmfc->dd; - if (tmfc->ddd) tm->tm_yday = tmfc->ddd; - if (tmfc->mm) tm->tm_mon = tmfc->mm; - - if (tmfc->ddd && (tm->tm_mon <=1 || tm->tm_mday <=1)) - { - /* count mday and mon from yday */ - int *y, i; - - int ysum[2][13] = { - { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0 }, - { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 0 }}; - - if (!tm->tm_year) - elog(ERROR, "to_timestamp() cat't convert yday without year information"); - - y = ysum[ isleap(tm->tm_year) ]; - - for (i=0; i <= 11; i++) - { - if (tm->tm_yday < y[i]) - break; - } - if (tm->tm_mon <=1) - tm->tm_mon = i+1; - - if (tm->tm_mday <=1) - tm->tm_mday = i == 0 ? tm->tm_yday : - tm->tm_yday - y[i-1]; - } - /* -------------------------------------------------------------- */ - #ifdef DEBUG_TO_FROM_CHAR NOTICE_TM; #endif @@ -2744,10 +2670,10 @@ to_timestamp(text *date_str, text *fmt) #ifdef DEBUG_TO_FROM_CHAR NOTICE_TM; #endif - if (tm2timestamp(tm, fsec, &tz, result) != 0) - elog(ERROR, "to_datatime(): can't convert 'tm' to timestamp."); + if (tm2timestamp(tm, fsec, &tz, &result) != 0) + elog(ERROR, "to_timestamp(): can't convert 'tm' to timestamp."); - return result; + PG_RETURN_TIMESTAMP(result); } /* ---------- @@ -2755,10 +2681,13 @@ to_timestamp(text *date_str, text *fmt) * Make Date from date_str which is formated at argument 'fmt' * ---------- */ -DateADT -to_date(text *date_str, text *fmt) +Datum +to_date(PG_FUNCTION_ARGS) { - return timestamp_date(to_timestamp(date_str, fmt)); + /* Quick hack: since our inputs are just like to_timestamp, + * hand over the whole input info struct... + */ + return DirectFunctionCall1(timestamp_date, to_timestamp(fcinfo)); } /********************************************************************** @@ -3922,13 +3851,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, * ---------- */ #define NUM_TOCHAR_prepare { \ - if (!PointerIsValid(fmt)) \ - return NULL; \ \ len = VARSIZE(fmt) - VARHDRSZ; \ \ - if (!len) \ - return textin(""); \ + if (len <= 0) \ + return PointerGetDatum(textin("")); \ \ result = (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \ format = NUM_cache(len, &Num, VARDATA(fmt), &flag); \ @@ -3965,26 +3892,24 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, * NUMERIC to_number() (convert string to numeric) * ------------------- */ -Numeric -numeric_to_number(text *value, text *fmt) +Datum +numeric_to_number(PG_FUNCTION_ARGS) { + text *value = PG_GETARG_TEXT_P(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; - Numeric result; + Datum result; FormatNode *format; char *numstr; int flag = 0; int len = 0; - int scale, precision; - if ((!PointerIsValid(value)) || (!PointerIsValid(fmt))) - return NULL; - len = VARSIZE(fmt) - VARHDRSZ; - if (!len) - return numeric_in(NULL, 0, 0); + if (len <= 0) + PG_RETURN_NULL(); format = NUM_cache(len, &Num, VARDATA(fmt), &flag); @@ -3999,7 +3924,10 @@ numeric_to_number(text *value, text *fmt) if (flag) pfree(format); - result = numeric_in(numstr, 0, ((precision << 16) | scale) + VARHDRSZ); + result = DirectFunctionCall3(numeric_in, + CStringGetDatum(numstr), + ObjectIdGetDatum(InvalidOid), + Int32GetDatum(((precision << 16) | scale) + VARHDRSZ)); pfree(numstr); return result; } @@ -4008,9 +3936,11 @@ numeric_to_number(text *value, text *fmt) * NUMERIC to_char() * ------------------ */ -text * -numeric_to_char(Numeric value, text *fmt) +Datum +numeric_to_char(PG_FUNCTION_ARGS) { + Numeric value = PG_GETARG_NUMERIC(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; text *result, @@ -4022,7 +3952,7 @@ numeric_to_char(Numeric value, text *fmt) char *numstr, *orgnum, *p; - Numeric x = NULL; + Numeric x; NUM_TOCHAR_prepare; @@ -4032,10 +3962,11 @@ numeric_to_char(Numeric value, text *fmt) */ if (IS_ROMAN(&Num)) { - x = numeric_round(value, 0); + x = DatumGetNumeric(DirectFunctionCall2(numeric_round, + NumericGetDatum(value), + Int32GetDatum(0))); numstr = orgnum = int_to_roman(numeric_int4(x)); pfree(x); - } else { @@ -4043,8 +3974,10 @@ numeric_to_char(Numeric value, text *fmt) if (IS_MULTI(&Num)) { - Numeric a = int4_numeric(10); - Numeric b = int4_numeric(Num.multi); + Numeric a = DatumGetNumeric(DirectFunctionCall1(int4_numeric, + Int32GetDatum(10))); + Numeric b = DatumGetNumeric(DirectFunctionCall1(int4_numeric, + Int32GetDatum(Num.multi))); x = numeric_power(a, b); val = numeric_mul(value, x); @@ -4054,8 +3987,11 @@ numeric_to_char(Numeric value, text *fmt) Num.pre += Num.multi; } - x = numeric_round(val, Num.post); - orgnum = numeric_out(x); + x = DatumGetNumeric(DirectFunctionCall2(numeric_round, + NumericGetDatum(val), + Int32GetDatum(Num.post))); + orgnum = DatumGetCString(DirectFunctionCall1(numeric_out, + NumericGetDatum(x))); pfree(x); if (*orgnum == '-') @@ -4088,16 +4024,18 @@ numeric_to_char(Numeric value, text *fmt) } NUM_TOCHAR_finish; - return result; + PG_RETURN_TEXT_P(result); } /* --------------- * INT4 to_char() * --------------- */ -text * -int4_to_char(int32 value, text *fmt) +Datum +int4_to_char(PG_FUNCTION_ARGS) { + int32 value = PG_GETARG_INT32(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; text *result, @@ -4118,7 +4056,6 @@ int4_to_char(int32 value, text *fmt) if (IS_ROMAN(&Num)) { numstr = orgnum = int_to_roman(value); - } else { @@ -4171,16 +4108,18 @@ int4_to_char(int32 value, text *fmt) } NUM_TOCHAR_finish; - return result; + PG_RETURN_TEXT_P(result); } /* --------------- * INT8 to_char() * --------------- */ -text * -int8_to_char(int64 *value, text *fmt) +Datum +int8_to_char(PG_FUNCTION_ARGS) { + int64 value = PG_GETARG_INT64(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; text *result, @@ -4200,8 +4139,9 @@ int8_to_char(int64 *value, text *fmt) */ if (IS_ROMAN(&Num)) { - numstr = orgnum = int_to_roman(int84(value)); - + /* Currently don't support int8 conversion to roman... */ + numstr = orgnum = int_to_roman(DatumGetInt32( + DirectFunctionCall1(int84, Int64GetDatum(value)))); } else { @@ -4209,11 +4149,15 @@ int8_to_char(int64 *value, text *fmt) { double multi = pow((double) 10, (double) Num.multi); - orgnum = int8out(int8mul(value, dtoi8((float64) &multi))); + value = DatumGetInt64(DirectFunctionCall2(int8mul, + Int64GetDatum(value), + DirectFunctionCall1(dtoi8, + Float8GetDatum(multi)))); Num.pre += Num.multi; } - else - orgnum = int8out(value); + + orgnum = DatumGetCString(DirectFunctionCall1(int8out, + Int64GetDatum(value))); len = strlen(orgnum); if (*orgnum == '-') @@ -4252,16 +4196,18 @@ int8_to_char(int64 *value, text *fmt) } NUM_TOCHAR_finish; - return result; + PG_RETURN_TEXT_P(result); } /* ----------------- * FLOAT4 to_char() * ----------------- */ -text * -float4_to_char(float32 value, text *fmt) +Datum +float4_to_char(PG_FUNCTION_ARGS) { + float4 value = PG_GETARG_FLOAT4(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; text *result, @@ -4278,30 +4224,30 @@ float4_to_char(float32 value, text *fmt) if (IS_ROMAN(&Num)) { - numstr = orgnum = int_to_roman((int) rint(*value)); + numstr = orgnum = int_to_roman((int) rint(value)); } else { - float32 val = value; + float4 val = value; if (IS_MULTI(&Num)) { float multi = pow((double) 10, (double) Num.multi); - val = float4mul(value, (float32) &multi); + val = value * multi; Num.pre += Num.multi; } orgnum = (char *) palloc(MAXFLOATWIDTH + 1); - len = sprintf(orgnum, "%.0f", fabs(*val)); + len = sprintf(orgnum, "%.0f", fabs(val)); if (Num.pre > len) plen = Num.pre - len; if (len >= FLT_DIG) Num.post = 0; else if (Num.post + len > FLT_DIG) Num.post = FLT_DIG - len; - sprintf(orgnum, "%.*f", Num.post, *val); + sprintf(orgnum, "%.*f", Num.post, val); if (*orgnum == '-') { /* < 0 */ @@ -4330,16 +4276,18 @@ float4_to_char(float32 value, text *fmt) } NUM_TOCHAR_finish; - return result; + PG_RETURN_TEXT_P(result); } /* ----------------- * FLOAT8 to_char() * ----------------- */ -text * -float8_to_char(float64 value, text *fmt) +Datum +float8_to_char(PG_FUNCTION_ARGS) { + float8 value = PG_GETARG_FLOAT8(0); + text *fmt = PG_GETARG_TEXT_P(1); NUMDesc Num; FormatNode *format; text *result, @@ -4356,29 +4304,29 @@ float8_to_char(float64 value, text *fmt) if (IS_ROMAN(&Num)) { - numstr = orgnum = int_to_roman((int) rint(*value)); + numstr = orgnum = int_to_roman((int) rint(value)); } else { - float64 val = value; + float8 val = value; if (IS_MULTI(&Num)) { double multi = pow((double) 10, (double) Num.multi); - val = float8mul(value, (float64) &multi); + val = value * multi; Num.pre += Num.multi; } orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1); - len = sprintf(orgnum, "%.0f", fabs(*val)); + len = sprintf(orgnum, "%.0f", fabs(val)); if (Num.pre > len) plen = Num.pre - len; if (len >= DBL_DIG) Num.post = 0; else if (Num.post + len > DBL_DIG) Num.post = DBL_DIG - len; - sprintf(orgnum, "%.*f", Num.post, *val); + sprintf(orgnum, "%.*f", Num.post, val); if (*orgnum == '-') { /* < 0 */ @@ -4407,5 +4355,5 @@ float8_to_char(float64 value, text *fmt) } NUM_TOCHAR_finish; - return result; + PG_RETURN_TEXT_P(result); } diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out index 15120b8758..72c02b1fa2 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -1023,7 +1023,7 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J') | | | - | 1,970 1970 970 70 0 20 1 01 01 001 01 5 2440588 + | 1,970 1970 970 70 0 20 1 01 00 001 01 5 2440588 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | | @@ -1032,8 +1032,8 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J') | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 - | 1,997 1997 997 97 7 20 1 01 01 002 02 5 2450451 - | 1,997 1997 997 97 7 20 1 01 01 002 02 5 2450451 + | 1,997 1997 997 97 7 20 1 01 00 002 02 5 2450451 + | 1,997 1997 997 97 7 20 1 01 00 002 02 5 2450451 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 @@ -1058,32 +1058,32 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J') | 1,997 1997 997 97 7 20 2 06 23 161 10 3 2450610 | 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490 | 1,997 1997 997 97 7 20 1 02 06 042 11 3 2450491 - | 1,997 1997 997 97 7 20 1 02 07 043 12 4 2450492 - | 1,997 1997 997 97 7 20 1 02 07 044 13 5 2450493 - | 1,997 1997 997 97 7 20 1 02 07 045 14 6 2450494 - | 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495 + | 1,997 1997 997 97 7 20 1 02 06 043 12 4 2450492 + | 1,997 1997 997 97 7 20 1 02 06 044 13 5 2450493 + | 1,997 1997 997 97 7 20 1 02 06 045 14 6 2450494 + | 1,997 1997 997 97 7 20 1 02 06 046 15 7 2450495 | 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496 | 0,097 0097 097 97 7 01 1 02 07 047 16 3 1686042 - | 0,097 0097 097 97 7 01 1 02 07 047 16 7 1756536 + | 0,097 0097 097 97 7 01 1 02 06 047 16 7 1756536 | 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157 | 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778 - | 1,697 1697 697 97 7 17 1 02 07 047 16 7 2340924 + | 1,697 1697 697 97 7 17 1 02 06 047 16 7 2340924 | 1,797 1797 797 97 7 18 1 02 07 047 16 5 2377448 | 1,897 1897 897 97 7 19 1 02 07 047 16 3 2413972 | 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496 - | 2,097 2097 097 97 7 21 1 02 07 047 16 7 2487021 + | 2,097 2097 097 97 7 21 1 02 06 047 16 7 2487021 | 1,996 1996 996 96 6 20 1 02 09 059 28 4 2450142 | 1,996 1996 996 96 6 20 1 02 09 060 29 5 2450143 | 1,996 1996 996 96 6 20 1 03 09 061 01 6 2450144 | 1,996 1996 996 96 6 20 4 12 53 365 30 2 2450448 | 1,996 1996 996 96 6 20 4 12 53 366 31 3 2450449 - | 1,997 1997 997 97 7 20 1 01 01 001 01 4 2450450 - | 1,997 1997 997 97 7 20 1 02 09 059 28 6 2450508 - | 1,997 1997 997 97 7 20 1 03 09 060 01 7 2450509 + | 1,997 1997 997 97 7 20 1 01 00 001 01 4 2450450 + | 1,997 1997 997 97 7 20 1 02 08 059 28 6 2450508 + | 1,997 1997 997 97 7 20 1 03 08 060 01 7 2450509 | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813 - | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814 - | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544 - | 2,000 2000 000 00 0 21 1 01 01 001 01 7 2451545 + | 1,997 1997 997 97 7 20 4 12 52 365 31 4 2450814 + | 1,999 1999 999 99 9 20 4 12 52 365 31 6 2451544 + | 2,000 2000 000 00 0 21 1 01 00 001 01 7 2451545 | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910 | 2,001 2001 001 01 1 21 1 01 01 001 01 2 2451911 (66 rows) @@ -1096,7 +1096,7 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM | | | - | 1,970 1970 970 70 0 20 1 1 1 1 1 5 2440588 + | 1,970 1970 970 70 0 20 1 1 0 1 1 5 2440588 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | | @@ -1105,8 +1105,8 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 - | 1,997 1997 997 97 7 20 1 1 1 2 2 5 2450451 - | 1,997 1997 997 97 7 20 1 1 1 2 2 5 2450451 + | 1,997 1997 997 97 7 20 1 1 0 2 2 5 2450451 + | 1,997 1997 997 97 7 20 1 1 0 2 2 5 2450451 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 @@ -1131,32 +1131,32 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM | 1,997 1997 997 97 7 20 2 6 23 161 10 3 2450610 | 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490 | 1,997 1997 997 97 7 20 1 2 6 42 11 3 2450491 - | 1,997 1997 997 97 7 20 1 2 7 43 12 4 2450492 - | 1,997 1997 997 97 7 20 1 2 7 44 13 5 2450493 - | 1,997 1997 997 97 7 20 1 2 7 45 14 6 2450494 - | 1,997 1997 997 97 7 20 1 2 7 46 15 7 2450495 + | 1,997 1997 997 97 7 20 1 2 6 43 12 4 2450492 + | 1,997 1997 997 97 7 20 1 2 6 44 13 5 2450493 + | 1,997 1997 997 97 7 20 1 2 6 45 14 6 2450494 + | 1,997 1997 997 97 7 20 1 2 6 46 15 7 2450495 | 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496 | 0,097 97 097 97 7 1 1 2 7 47 16 3 1686042 - | 0,097 97 097 97 7 1 1 2 7 47 16 7 1756536 + | 0,097 97 097 97 7 1 1 2 6 47 16 7 1756536 | 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157 | 1,097 1097 097 97 7 11 1 2 7 47 16 3 2121778 - | 1,697 1697 697 97 7 17 1 2 7 47 16 7 2340924 + | 1,697 1697 697 97 7 17 1 2 6 47 16 7 2340924 | 1,797 1797 797 97 7 18 1 2 7 47 16 5 2377448 | 1,897 1897 897 97 7 19 1 2 7 47 16 3 2413972 | 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496 - | 2,097 2097 097 97 7 21 1 2 7 47 16 7 2487021 + | 2,097 2097 097 97 7 21 1 2 6 47 16 7 2487021 | 1,996 1996 996 96 6 20 1 2 9 59 28 4 2450142 | 1,996 1996 996 96 6 20 1 2 9 60 29 5 2450143 | 1,996 1996 996 96 6 20 1 3 9 61 1 6 2450144 | 1,996 1996 996 96 6 20 4 12 53 365 30 2 2450448 | 1,996 1996 996 96 6 20 4 12 53 366 31 3 2450449 - | 1,997 1997 997 97 7 20 1 1 1 1 1 4 2450450 - | 1,997 1997 997 97 7 20 1 2 9 59 28 6 2450508 - | 1,997 1997 997 97 7 20 1 3 9 60 1 7 2450509 + | 1,997 1997 997 97 7 20 1 1 0 1 1 4 2450450 + | 1,997 1997 997 97 7 20 1 2 8 59 28 6 2450508 + | 1,997 1997 997 97 7 20 1 3 8 60 1 7 2450509 | 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813 - | 1,997 1997 997 97 7 20 4 12 53 365 31 4 2450814 - | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544 - | 2,000 2000 000 00 0 21 1 1 1 1 1 7 2451545 + | 1,997 1997 997 97 7 20 4 12 52 365 31 4 2450814 + | 1,999 1999 999 99 9 20 4 12 52 365 31 6 2451544 + | 2,000 2000 000 00 0 21 1 1 0 1 1 7 2451545 | 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910 | 2,001 2001 001 01 1 21 1 1 1 1 1 2 2451911 (66 rows)