Prevent to_char(interval) from dumping core on month-related formats

when a zero-month interval is given.  Per discussion with Karel.
Also, some desultory const-labeling of constant tables.  More could be
done along that line.
This commit is contained in:
Tom Lane 2005-03-26 00:41:31 +00:00
parent a7032690f9
commit fccde77ecb
1 changed files with 41 additions and 25 deletions

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
* formatting.c * formatting.c
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.85 2005/03/25 16:08:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.86 2005/03/26 00:41:31 tgl Exp $
* *
* *
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
@ -133,18 +133,19 @@ typedef struct FormatNode FormatNode;
typedef struct typedef struct
{ {
char *name; /* keyword */ const char *name; /* keyword */
/* action for keyword */ int len; /* keyword length */
int len, /* keyword length */ int (*action) (int arg, char *inout, /* action for keyword */
(*action) (int arg, char *inout, int suf, int flag, FormatNode *node, void *data), int suf, int flag,
id; /* keyword id */ FormatNode *node, void *data);
int id; /* keyword id */
bool isitdigit; /* is expected output/input digit */ bool isitdigit; /* is expected output/input digit */
} KeyWord; } KeyWord;
struct FormatNode struct FormatNode
{ {
int type; /* node type */ int type; /* node type */
KeyWord *key; /* if node type is KEYWORD */ const KeyWord *key; /* if node type is KEYWORD */
int character, /* if node type is CHAR */ int character, /* if node type is CHAR */
suffix; /* keyword suffix */ suffix; /* keyword suffix */
}; };
@ -648,7 +649,7 @@ typedef enum
* KeyWords for DATE-TIME version * KeyWords for DATE-TIME version
* ---------- * ----------
*/ */
static KeyWord DCH_keywords[] = { static const KeyWord DCH_keywords[] = {
/* keyword, len, func, type, isitdigit is in Index */ /* keyword, len, func, type, isitdigit is in Index */
{"A.D.", 4, dch_date, DCH_A_D, FALSE}, /* A */ {"A.D.", 4, dch_date, DCH_A_D, FALSE}, /* A */
{"A.M.", 4, dch_time, DCH_A_M, FALSE}, {"A.M.", 4, dch_time, DCH_A_M, FALSE},
@ -745,7 +746,7 @@ static KeyWord DCH_keywords[] = {
* KeyWords for NUMBER version (now, isitdigit info is not needful here..) * KeyWords for NUMBER version (now, isitdigit info is not needful here..)
* ---------- * ----------
*/ */
static KeyWord NUM_keywords[] = { static const KeyWord NUM_keywords[] = {
/* keyword, len, func. type is in Index */ /* keyword, len, func. type is in Index */
{",", 1, NULL, NUM_COMMA}, /* , */ {",", 1, NULL, NUM_COMMA}, /* , */
{".", 1, NULL, NUM_DEC}, /* . */ {".", 1, NULL, NUM_DEC}, /* . */
@ -792,7 +793,7 @@ static KeyWord NUM_keywords[] = {
* KeyWords index for DATE-TIME version * KeyWords index for DATE-TIME version
* ---------- * ----------
*/ */
static int DCH_index[KeyWord_INDEX_SIZE] = { static const int DCH_index[KeyWord_INDEX_SIZE] = {
/* /*
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
*/ */
@ -816,7 +817,7 @@ static int DCH_index[KeyWord_INDEX_SIZE] = {
* KeyWords index for NUMBER version * KeyWords index for NUMBER version
* ---------- * ----------
*/ */
static int NUM_index[KeyWord_INDEX_SIZE] = { static const int NUM_index[KeyWord_INDEX_SIZE] = {
/* /*
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
*/ */
@ -876,15 +877,16 @@ typedef struct NUMProc
* Functions * Functions
* ---------- * ----------
*/ */
static KeyWord *index_seq_search(char *str, KeyWord *kw, int *index); static const KeyWord *index_seq_search(char *str, const KeyWord *kw,
const int *index);
static KeySuffix *suff_search(char *str, KeySuffix *suf, int type); static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);
static void NUMDesc_prepare(NUMDesc *num, FormatNode *n); static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
static void parse_format(FormatNode *node, char *str, KeyWord *kw, static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
KeySuffix *suf, int *index, int ver, NUMDesc *Num); KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
static char *DCH_processor(FormatNode *node, char *inout, int flag, void *data); static char *DCH_processor(FormatNode *node, char *inout, int flag, void *data);
#ifdef DEBUG_TO_FROM_CHAR #ifdef DEBUG_TO_FROM_CHAR
static void dump_index(KeyWord *k, int *index); static void dump_index(const KeyWord *k, const int *index);
static void dump_node(FormatNode *node, int max); static void dump_node(FormatNode *node, int max);
#endif #endif
@ -924,8 +926,8 @@ static void NUM_cache_remove(NUMCacheEntry *ent);
* (can't be used binary search in format parsing) * (can't be used binary search in format parsing)
* ---------- * ----------
*/ */
static KeyWord * static const KeyWord *
index_seq_search(char *str, KeyWord *kw, int *index) index_seq_search(char *str, const KeyWord *kw, const int *index)
{ {
int poz; int poz;
@ -934,8 +936,7 @@ index_seq_search(char *str, KeyWord *kw, int *index)
if ((poz = *(index + (*str - ' '))) > -1) if ((poz = *(index + (*str - ' '))) > -1)
{ {
const KeyWord *k = kw + poz;
KeyWord *k = kw + poz;
do do
{ {
@ -1167,8 +1168,8 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
* ---------- * ----------
*/ */
static void static void
parse_format(FormatNode *node, char *str, KeyWord *kw, parse_format(FormatNode *node, char *str, const KeyWord *kw,
KeySuffix *suf, int *index, int ver, NUMDesc *Num) KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
{ {
KeySuffix *s; KeySuffix *s;
FormatNode *n; FormatNode *n;
@ -1594,7 +1595,7 @@ seq_search(char *name, char **array, int type, int max, int *len)
* ---------- * ----------
*/ */
static void static void
dump_index(KeyWord *k, int *index) dump_index(const KeyWord *k, const int *index)
{ {
int i, int i,
count = 0, count = 0,
@ -2182,6 +2183,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
} }
break; break;
case DCH_MONTH: case DCH_MONTH:
if (!tm->tm_mon)
return -1;
strcpy(workbuff, months_full[tm->tm_mon - 1]); strcpy(workbuff, months_full[tm->tm_mon - 1]);
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(workbuff)); sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(workbuff));
if (S_FM(suf)) if (S_FM(suf))
@ -2190,6 +2193,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return 8; return 8;
case DCH_Month: case DCH_Month:
if (!tm->tm_mon)
return -1;
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
if (S_FM(suf)) if (S_FM(suf))
return strlen(p_inout) - 1; return strlen(p_inout) - 1;
@ -2197,6 +2202,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return 8; return 8;
case DCH_month: case DCH_month:
if (!tm->tm_mon)
return -1;
sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]); sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
*inout = pg_tolower((unsigned char) *inout); *inout = pg_tolower((unsigned char) *inout);
if (S_FM(suf)) if (S_FM(suf))
@ -2205,15 +2212,21 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return 8; return 8;
case DCH_MON: case DCH_MON:
if (!tm->tm_mon)
return -1;
strcpy(inout, months[tm->tm_mon - 1]); strcpy(inout, months[tm->tm_mon - 1]);
inout = str_toupper(inout); inout = str_toupper(inout);
return 2; return 2;
case DCH_Mon: case DCH_Mon:
if (!tm->tm_mon)
return -1;
strcpy(inout, months[tm->tm_mon - 1]); strcpy(inout, months[tm->tm_mon - 1]);
return 2; return 2;
case DCH_mon: case DCH_mon:
if (!tm->tm_mon)
return -1;
strcpy(inout, months[tm->tm_mon - 1]); strcpy(inout, months[tm->tm_mon - 1]);
*inout = pg_tolower((unsigned char) *inout); *inout = pg_tolower((unsigned char) *inout);
return 2; return 2;
@ -2228,7 +2241,6 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return strlen(p_inout) - 1; return strlen(p_inout) - 1;
else else
return 1; return 1;
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
@ -2388,7 +2400,6 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return strlen(p_inout) - 1; return strlen(p_inout) - 1;
else else
return 1; return 1;
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
@ -2407,6 +2418,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
case DCH_Q: case DCH_Q:
if (flag == TO_CHAR) if (flag == TO_CHAR)
{ {
if (!tm->tm_mon)
return -1;
sprintf(inout, "%d", (tm->tm_mon - 1) / 3 + 1); sprintf(inout, "%d", (tm->tm_mon - 1) / 3 + 1);
if (S_THth(suf)) if (S_THth(suf))
{ {
@ -2414,7 +2427,6 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
return 2; return 2;
} }
return 0; return 0;
} }
else if (flag == FROM_CHAR) else if (flag == FROM_CHAR)
{ {
@ -2613,6 +2625,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
case DCH_RM: case DCH_RM:
if (flag == TO_CHAR) if (flag == TO_CHAR)
{ {
if (!tm->tm_mon)
return -1;
sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, sprintf(inout, "%*s", S_FM(suf) ? 0 : -4,
rm_months_upper[12 - tm->tm_mon]); rm_months_upper[12 - tm->tm_mon]);
if (S_FM(suf)) if (S_FM(suf))
@ -2634,6 +2648,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
case DCH_rm: case DCH_rm:
if (flag == TO_CHAR) if (flag == TO_CHAR)
{ {
if (!tm->tm_mon)
return -1;
sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, sprintf(inout, "%*s", S_FM(suf) ? 0 : -4,
rm_months_lower[12 - tm->tm_mon]); rm_months_lower[12 - tm->tm_mon]);
if (S_FM(suf)) if (S_FM(suf))