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:
parent
a7032690f9
commit
fccde77ecb
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue