formatting.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,989 行 · 第 1/5 页
C
2,989 行
} return 0; } else if (flag == FROM_CHAR) { sscanf(inout, "%1d", &tmfc->q); return 0 + SKIP_THth(suf); } break; case DCH_CC: if (flag == TO_CHAR) { i = tm->tm_year / 100 + 1; if (i <= 99 && i >= -99) sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, i); else sprintf(inout, "%d", i); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout) - 1; } else if (flag == FROM_CHAR) { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->cc); return strdigits_len(inout) - 1 + SKIP_THth(suf); } else { sscanf(inout, "%02d", &tmfc->cc); return 1 + SKIP_THth(suf); } } break; case DCH_Y_YYY: if (flag == TO_CHAR) { i = YEAR_ABS(tm->tm_year) / 1000; 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)); return strlen(p_inout) - 1; } else if (flag == FROM_CHAR) { int cc; sscanf(inout, "%d,%03d", &cc, &tmfc->year); tmfc->year += (cc * 1000); return strdigits_len(inout) + 3 + SKIP_THth(suf); } break; case DCH_YYYY: if (flag == TO_CHAR) { if (tm->tm_year <= 9999 && tm->tm_year >= -9998) sprintf(inout, "%0*d", S_FM(suf) ? 0 : 4, YEAR_ABS(tm->tm_year)); else sprintf(inout, "%d", YEAR_ABS(tm->tm_year)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout) - 1; } else if (flag == FROM_CHAR) { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->year); return strdigits_len(inout) - 1 + SKIP_THth(suf); } else { sscanf(inout, "%04d", &tmfc->year); return 3 + SKIP_THth(suf); } } break; case DCH_YYY: if (flag == TO_CHAR) { snprintf(buff, sizeof(buff), "%03d", YEAR_ABS(tm->tm_year)); i = strlen(buff); strcpy(inout, buff + (i - 3)); if (S_THth(suf)) { str_numth(p_inout, inout, S_TH_TYPE(suf)); return 4; } return 2; } else if (flag == FROM_CHAR) { sscanf(inout, "%03d", &tmfc->year); /* * 3-digit year: '100' ... '999' = 1100 ... 1999 '000' ... * '099' = 2000 ... 2099 */ if (tmfc->year >= 100) tmfc->year += 1000; else tmfc->year += 2000; return 2 + SKIP_THth(suf); } break; case DCH_YY: if (flag == TO_CHAR) { snprintf(buff, sizeof(buff), "%02d", YEAR_ABS(tm->tm_year)); i = strlen(buff); strcpy(inout, buff + (i - 2)); if (S_THth(suf)) { str_numth(p_inout, inout, S_TH_TYPE(suf)); return 3; } return 1; } else if (flag == FROM_CHAR) { sscanf(inout, "%02d", &tmfc->year); /* * 2-digit year: '00' ... '69' = 2000 ... 2069 '70' ... * '99' = 1970 ... 1999 */ if (tmfc->year < 70) tmfc->year += 2000; else tmfc->year += 1900; return 1 + SKIP_THth(suf); } break; case DCH_Y: if (flag == TO_CHAR) { snprintf(buff, sizeof(buff), "%1d", YEAR_ABS(tm->tm_year)); i = strlen(buff); strcpy(inout, buff + (i - 1)); 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->year); /* * 1-digit year: always +2000 */ tmfc->year += 2000; return 0 + SKIP_THth(suf); } break; case DCH_RM: if (flag == TO_CHAR) { sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, rm_months_upper[12 - tm->tm_mon]); if (S_FM(suf)) 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); CHECK_SEQ_SEARCH(len, "RM"); if (S_FM(suf)) return len - 1; else return 3; } break; case DCH_rm: if (flag == TO_CHAR) { sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, rm_months_lower[12 - tm->tm_mon]); if (S_FM(suf)) return strlen(p_inout) - 1; else return 3; } else if (flag == FROM_CHAR) { tmfc->mm = 12 - seq_search(inout, rm_months_lower, ALL_LOWER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "rm"); 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); 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; case DCH_J: if (flag == TO_CHAR) { sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout) - 1; } else if (flag == FROM_CHAR) { sscanf(inout, "%d", &tmfc->j); return strdigits_len(inout) - 1 + SKIP_THth(suf); } break; } return -1;}static DCHCacheEntry *DCH_cache_getnew(char *str){ DCHCacheEntry *ent = NULL; /* counter overload check - paranoia? */ if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32) { DCHCounter = 0; for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) ent->age = (++DCHCounter); } /* * Cache is full - needs remove any older entry */ if (n_DCHCache > DCH_CACHE_FIELDS) { DCHCacheEntry *old = DCHCache + 0;#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);#endif for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) { if (ent->age < old->age) old = ent; }#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);#endif StrNCpy(old->str, str, DCH_CACHE_SIZE + 1); /* old->format fill parser */ old->age = (++DCHCounter); return old; } else {#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);#endif ent = DCHCache + n_DCHCache; StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1); /* ent->format fill parser */ ent->age = (++DCHCounter); ++n_DCHCache; return ent; } return (DCHCacheEntry *) NULL; /* never */}static DCHCacheEntry *DCH_cache_search(char *str){ int i = 0; DCHCacheEntry *ent; /* counter overload check - paranoia? */ if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32) { DCHCounter = 0; for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) ent->age = (++DCHCounter); } for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) { if (i == n_DCHCache) break; if (strcmp(ent->str, str) == 0) { ent->age = (++DCHCounter); return ent; } i++; } return (DCHCacheEntry *) NULL;}static text *datetime_to_char_body(TmToChar *tmtc, text *fmt){ FormatNode *format; struct tm *tm = NULL; char *fmt_str, *result; bool incache; int fmt_len = VARSIZE(fmt) - VARHDRSZ; tm = tmtcTm(tmtc); tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7; tm->tm_yday = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(tm->tm_year, 1, 1) + 1; /* * Convert fmt to C string */ fmt_str = (char *) palloc(fmt_len + 1); memcpy(fmt_str, VARDATA(fmt), fmt_len); *(fmt_str + fmt_len) = '\0'; /* * Allocate result */ result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1); /* * Allocate new memory if format picture is bigger than static cache * and not use cache (call parser always) */ if (fmt_len > DCH_CACHE_SIZE) { format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode)); incache = FALSE; parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index, DCH_TYPE, NULL); (format + fmt_len)->type = NODE_TYPE_END; /* Paranoia? */ } else { /* * Use cache buffers */ DCHCacheEntry *ent; incache = TRUE; if ((ent = DCH_cache_search(fmt_str)) == NULL) { ent = DCH_cache_getnew(fmt_str); /* * Not in the cache, must run parser and save a new * format-picture to the cache. */ parse_format(ent->format, fmt_str, DCH_keywords, DCH_suff, DCH_index, DCH_TYPE, NULL); (ent->format + fmt_len)->type = NODE_TYPE_END; /* Paranoia? */#ifdef DEBUG_TO_FROM_CHAR /* dump_node(ent->format, fmt_len); */ /* dump_index(DCH_keywords, DCH_index); */#endif } format = ent->format; } DCH_processor(format, result, TO_CHAR, (void *) tmtc); if (!incache) pfree(format); pfree(fmt_str); /* * for result is allocated max memory, which current format-picture * needs, now it allocate result with real size */ if (result && *result) { int len = strlen(result); if (len) { text *res = (text *) palloc(len + 1 + VARHDRSZ); memcpy(VARDATA(res), result, len); VARATT_SIZEP(res) = len + VARHDRSZ; pfree(result); return res; } } pfree(result); return NULL;}/**************************************************************************** * Public routines ***************************************************************************//* ------------------- * TIMESTAMP to_char() * ------------------- */Datumtimestamp_to_char(PG_FUNCTION_ARGS){ Timestamp dt = PG_GETARG_TIMESTAMP(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt)) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); if (!(res = datetime_to_char_body(&tmtc, fmt))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}Datumtimestamptz_to_char(PG_FUNCTION_ARGS){ TimestampTz dt = PG_GETARG_TIMESTAMP(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; int tz; if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt)) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc)) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); if (!(res = datetime_to_char_body(&tmtc, fmt))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}/* ------------------- * INTERVAL to_char() * ------------------- */Datuminterval_to_char(PG_FUNCTION_ARGS){ Interval *it = PG_GETARG_INTERVAL_P(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; if ((VARSIZE(fmt) - VARHDRSZ) <= 0) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); if (interval2tm(*it, tmtcTm(&tmtc), &tmtcFsec(&tmtc)) != 0) PG_RETURN_NULL(); if (!(res = datetime_to_char_body(&tmtc, fmt))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}/* --------------------- * TO_TIMESTAMP() * * Make Timestamp from date_str which is formatted at argument 'fmt' * ( to_timestamp is reverse to_char() ) * --------------------- */Datumto_timestamp(PG_FUNCTION_ARGS){ text *date_txt = PG_GETARG_TEXT_P(0); text *fmt = PG_GETARG_TEXT_P(1); Timestamp result; int tz; struct tm tm; fsec_t fsec; do_to_timestamp(date_txt, fmt, &tm, &fsec); tz = DetermineLocalTimeZone(&tm); if (tm2timestamp(&tm, fsec, &tz, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); PG_RETURN_TIMESTAMP(result);}/* ---------- * TO_DATE * Make Date from date_str which is formated at argument 'fmt' * ---------- */Datumto_date(PG_FUNCTION_ARGS){ text *date_txt = PG_GETARG_TEXT_P(0); text *fmt = PG_GETARG_TEXT_P(1); DateADT result; struct tm tm; fsec_t fsec; do_to_timestamp(date_txt, fmt, &tm, &fsec); result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result);}/* * do_to_timestamp: shared code for to_timestamp and to_date * * Parse the 'date_txt' according to 'fmt', return results as a struct tm * and fractional seconds. */static voiddo_to_timestamp(text *date_txt, text *fmt, struct tm *tm, fsec_t *fsec){ FormatNode *format; TmFromChar tmfc; int fmt_len; ZERO_tm(tm); *fsec = 0; ZERO_tmfc(&tmfc); fmt_len = VARSIZE(fmt) - VARHDRSZ; if (fmt_len) { int date_len; char *fmt_str; char *date_str; bool incache; fmt_str = (char *) palloc(fmt_len + 1); memcpy(fmt_str, VARDATA(fmt), fmt_len); *(fmt_str + fmt_len) = '\0'; /* * Allocate new memory if fo
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?