/* * Load a timezone from file or from cache. * Does not verify that the timezone is acceptable! */ struct pg_tz * pg_tzset(const char *name) { pg_tz_cache *tzp; struct state tzstate; char uppername[TZ_STRLEN_MAX + 1]; char canonname[TZ_STRLEN_MAX + 1]; char *p; if (strlen(name) > TZ_STRLEN_MAX) return NULL; /* not going to fit */ if (!timezone_cache) if (!init_timezone_hashtable()) return NULL; /* * Upcase the given name to perform a case-insensitive hashtable search. * (We could alternatively downcase it, but we prefer upcase so that we * can get consistently upcased results from tzparse() in case the name is * a POSIX-style timezone spec.) */ p = uppername; while (*name) *p++ = pg_toupper((unsigned char) *name++); *p = '\0'; tzp = (pg_tz_cache *) hash_search(timezone_cache, uppername, HASH_FIND, NULL); if (tzp) { /* Timezone found in cache, nothing more to do */ return &tzp->tz; } if (tzload(uppername, canonname, &tzstate, TRUE) != 0) { if (uppername[0] == ':' || tzparse(uppername, &tzstate, FALSE) != 0) { /* Unknown timezone. Fail our call instead of loading GMT! */ return NULL; } /* For POSIX timezone specs, use uppercase name as canonical */ strcpy(canonname, uppername); } /* Save timezone in the cache */ tzp = (pg_tz_cache *) hash_search(timezone_cache, uppername, HASH_ENTER, NULL); /* hash_search already copied uppername into the hash key */ strcpy(tzp->tz.TZname, canonname); memcpy(&tzp->tz.state, &tzstate, sizeof(tzstate)); return &tzp->tz; }
Datum plvstr_is_prefix_text (PG_FUNCTION_ARGS) { text *str = PG_GETARG_TEXT_PP(0); text *prefix = PG_GETARG_TEXT_PP(1); bool case_sens = PG_GETARG_BOOL(2); bool mb_encode; int str_len = VARSIZE_ANY_EXHDR(str); int pref_len = VARSIZE_ANY_EXHDR(prefix); int i; char *ap, *bp; mb_encode = pg_database_encoding_max_length() > 1; if (mb_encode && !case_sens) { str = (text*)DatumGetPointer(DirectFunctionCall1(lower, PointerGetDatum(str))); prefix = (text*)DatumGetPointer(DirectFunctionCall1(lower, PointerGetDatum(prefix))); } ap = VARDATA_ANY(str); bp = VARDATA_ANY(prefix); for (i = 0; i < pref_len; i++) { if (i >= str_len) break; if (case_sens || mb_encode) { if (*ap++ != *bp++) break; } else if (!mb_encode) { if (pg_toupper((unsigned char) *ap++) != pg_toupper((unsigned char) *bp++)) break; } } PG_RETURN_BOOL(i == pref_len); }
/* cash_words() * This converts an int4 as well but to a representation using words * Obviously way North American centric - sorry */ Datum cash_words(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); uint64 val; char buf[256]; char *p = buf; Cash m0; Cash m1; Cash m2; Cash m3; Cash m4; Cash m5; Cash m6; /* work with positive numbers */ if (value < 0) { value = -value; strcpy(buf, "minus "); p += 6; } else buf[0] = '\0'; /* Now treat as unsigned, to avoid trouble at INT_MIN */ val = (uint64) value; m0 = val % INT64CONST(100); /* cents */ m1 = (val / INT64CONST(100)) % 1000; /* hundreds */ m2 = (val / INT64CONST(100000)) % 1000; /* thousands */ m3 = (val / INT64CONST(100000000)) % 1000; /* millions */ m4 = (val / INT64CONST(100000000000)) % 1000; /* billions */ m5 = (val / INT64CONST(100000000000000)) % 1000; /* trillions */ m6 = (val / INT64CONST(100000000000000000)) % 1000; /* quadrillions */ if (m6) { strcat(buf, num_word(m6)); strcat(buf, " quadrillion "); } if (m5) { strcat(buf, num_word(m5)); strcat(buf, " trillion "); } if (m4) { strcat(buf, num_word(m4)); strcat(buf, " billion "); } if (m3) { strcat(buf, num_word(m3)); strcat(buf, " million "); } if (m2) { strcat(buf, num_word(m2)); strcat(buf, " thousand "); } if (m1) strcat(buf, num_word(m1)); if (!*p) strcat(buf, "zero"); strcat(buf, (val / 100) == 1 ? " dollar and " : " dollars and "); strcat(buf, num_word(m0)); strcat(buf, m0 == 1 ? " cent" : " cents"); /* capitalize output */ buf[0] = pg_toupper((unsigned char) buf[0]); /* return as text datum */ PG_RETURN_TEXT_P(cstring_to_text(buf)); }
/* cash_words() * This converts a int4 as well but to a representation using words * Obviously way North American centric - sorry */ Datum cash_words(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); uint64 val; char buf[256]; char *p = buf; Cash m0; Cash m1; Cash m2; Cash m3; Cash m4; Cash m5; Cash m6; text *result; /* work with positive numbers */ if (value < 0) { value = -value; strcpy(buf, "minus "); p += 6; } else buf[0] = '\0'; /* Now treat as unsigned, to avoid trouble at INT_MIN */ val = (uint64) value; m0 = val % 100ll; /* cents */ m1 = (val / 100ll) % 1000; /* hundreds */ m2 = (val / 100000ll) % 1000; /* thousands */ m3 = val / 100000000ll % 1000; /* millions */ m4 = val / 100000000000ll % 1000; /* billions */ m5 = val / 100000000000000ll % 1000; /* trillions */ m6 = val / 100000000000000000ll % 1000; /* quadrillions */ if (m6) { strcat(buf, num_word(m6)); strcat(buf, " quadrillion "); } if (m5) { strcat(buf, num_word(m5)); strcat(buf, " trillion "); } if (m4) { strcat(buf, num_word(m4)); strcat(buf, " billion "); } if (m3) { strcat(buf, num_word(m3)); strcat(buf, " million "); } if (m2) { strcat(buf, num_word(m2)); strcat(buf, " thousand "); } if (m1) strcat(buf, num_word(m1)); if (!*p) strcat(buf, "zero"); strcat(buf, (val / 100) == 1 ? " dollar and " : " dollars and "); strcat(buf, num_word(m0)); strcat(buf, m0 == 1 ? " cent" : " cents"); /* capitalize output */ buf[0] = pg_toupper((unsigned char) buf[0]); /* make a text type for output */ result = (text *) palloc(strlen(buf) + VARHDRSZ); SET_VARSIZE(result, strlen(buf) + VARHDRSZ); memcpy(VARDATA(result), buf, strlen(buf)); PG_RETURN_TEXT_P(result); }