#include "postgres.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
Go to the source code of this file.
Data Structures | |
struct | ConvProcInfo |
Defines | |
#define | MAX_CONVERSION_GROWTH 4 |
Typedefs | |
typedef struct ConvProcInfo | ConvProcInfo |
Functions | |
static char * | perform_default_encoding_conversion (const char *src, int len, bool is_client_to_server) |
static int | cliplen (const char *str, int len, int limit) |
int | PrepareClientEncoding (int encoding) |
int | SetClientEncoding (int encoding) |
void | InitializeClientEncoding (void) |
int | pg_get_client_encoding (void) |
const char * | pg_get_client_encoding_name (void) |
unsigned char * | pg_do_encoding_conversion (unsigned char *src, int len, int src_encoding, int dest_encoding) |
Datum | pg_convert_to (PG_FUNCTION_ARGS) |
Datum | pg_convert_from (PG_FUNCTION_ARGS) |
Datum | pg_convert (PG_FUNCTION_ARGS) |
Datum | length_in_encoding (PG_FUNCTION_ARGS) |
Datum | pg_encoding_max_length_sql (PG_FUNCTION_ARGS) |
char * | pg_client_to_server (const char *s, int len) |
char * | pg_any_to_server (const char *s, int len, int encoding) |
char * | pg_server_to_client (const char *s, int len) |
char * | pg_server_to_any (const char *s, int len, int encoding) |
int | pg_mb2wchar (const char *from, pg_wchar *to) |
int | pg_mb2wchar_with_len (const char *from, pg_wchar *to, int len) |
int | pg_encoding_mb2wchar_with_len (int encoding, const char *from, pg_wchar *to, int len) |
int | pg_wchar2mb (const pg_wchar *from, char *to) |
int | pg_wchar2mb_with_len (const pg_wchar *from, char *to, int len) |
int | pg_encoding_wchar2mb_with_len (int encoding, const pg_wchar *from, char *to, int len) |
int | pg_mblen (const char *mbstr) |
int | pg_dsplen (const char *mbstr) |
int | pg_mbstrlen (const char *mbstr) |
int | pg_mbstrlen_with_len (const char *mbstr, int limit) |
int | pg_mbcliplen (const char *mbstr, int len, int limit) |
int | pg_encoding_mbcliplen (int encoding, const char *mbstr, int len, int limit) |
int | pg_mbcharcliplen (const char *mbstr, int len, int limit) |
void | SetDatabaseEncoding (int encoding) |
void | pg_bind_textdomain_codeset (const char *domainname) |
int | GetDatabaseEncoding (void) |
const char * | GetDatabaseEncodingName (void) |
Datum | getdatabaseencoding (PG_FUNCTION_ARGS) |
Datum | pg_client_encoding (PG_FUNCTION_ARGS) |
int | GetPlatformEncoding (void) |
Variables | |
static List * | ConvProcList = NIL |
static FmgrInfo * | ToServerConvProc = NULL |
static FmgrInfo * | ToClientConvProc = NULL |
static pg_enc2name * | ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII] |
static pg_enc2name * | DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII] |
static pg_enc2name * | PlatformEncoding = NULL |
static bool | backend_startup_complete = false |
static int | pending_client_encoding = PG_SQL_ASCII |
#define MAX_CONVERSION_GROWTH 4 |
Definition at line 27 of file mbutils.c.
Referenced by perform_default_encoding_conversion(), and pg_do_encoding_conversion().
typedef struct ConvProcInfo ConvProcInfo |
static int cliplen | ( | const char * | str, | |
int | len, | |||
int | limit | |||
) | [static] |
Definition at line 864 of file mbutils.c.
References Min.
Referenced by pg_encoding_mbcliplen(), and pg_mbcharcliplen().
{ int l = 0; len = Min(len, limit); while (l < len && str[l]) l++; return l; }
int GetDatabaseEncoding | ( | void | ) |
Definition at line 925 of file mbutils.c.
References Assert, and pg_enc2name::encoding.
Referenced by ascii(), ASN1_STRING_to_text(), BeginCopy(), chr(), CollationGetCollid(), convert_from_utf8(), convert_to_utf8(), cstr2sv(), db_encoding_strdup(), DefineCollation(), dsnowball_lexize(), Generic_Text_IC_like(), GenericMatchText(), get_collation_oid(), hv_fetch_string(), hv_store_string(), IsThereCollationInNamespace(), locate_stem_module(), p_isspecial(), pg_bind_textdomain_codeset(), pg_database_encoding_character_incrementer(), pg_database_encoding_max_length(), pg_generic_charinc(), pg_set_regex_collation(), pg_stat_statements(), pg_verifymbstr(), pgss_store(), PLyUnicode_Bytes(), PrepareClientEncoding(), read_extension_script_file(), SetClientEncoding(), sv2cstr(), t_readline(), to_ascii_default(), type_maximum_size(), unicode_to_sqlchar(), utf_e2u(), utf_u2e(), varstr_cmp(), write_console(), X509_NAME_to_text(), xml_in(), xml_is_document(), xml_recv(), and xmlparse().
{ Assert(DatabaseEncoding); return DatabaseEncoding->encoding; }
Datum getdatabaseencoding | ( | PG_FUNCTION_ARGS | ) |
Definition at line 939 of file mbutils.c.
References Assert, CStringGetDatum, DirectFunctionCall1, pg_enc2name::name, and namein().
{ Assert(DatabaseEncoding); return DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name)); }
const char* GetDatabaseEncodingName | ( | void | ) |
Definition at line 932 of file mbutils.c.
References Assert, and pg_enc2name::name.
Referenced by check_client_encoding(), CheckMyDatabase(), connect_pg_server(), dblink_connect(), get_collation_oid(), InitializeClientEncoding(), IsThereCollationInNamespace(), and locate_stem_module().
{ Assert(DatabaseEncoding); return DatabaseEncoding->name; }
int GetPlatformEncoding | ( | void | ) |
Definition at line 953 of file mbutils.c.
References pg_enc2name::encoding, encoding, NULL, pg_enc2name_tbl, and pg_get_encoding_from_locale().
Referenced by write_console().
{ if (PlatformEncoding == NULL) { /* try to determine encoding of server's environment locale */ int encoding = pg_get_encoding_from_locale("", true); if (encoding < 0) encoding = PG_SQL_ASCII; PlatformEncoding = &pg_enc2name_tbl[encoding]; } return PlatformEncoding->encoding; }
void InitializeClientEncoding | ( | void | ) |
Definition at line 267 of file mbutils.c.
References Assert, backend_startup_complete, ereport, errcode(), errmsg(), FATAL, GetDatabaseEncodingName(), name, pending_client_encoding, pg_enc2name_tbl, PrepareClientEncoding(), and SetClientEncoding().
Referenced by InitPostgres().
{ Assert(!backend_startup_complete); backend_startup_complete = true; if (PrepareClientEncoding(pending_client_encoding) < 0 || SetClientEncoding(pending_client_encoding) < 0) { /* * Oops, the requested conversion is not available. We couldn't fail * before, but we can now. */ ereport(FATAL, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("conversion between %s and %s is not supported", pg_enc2name_tbl[pending_client_encoding].name, GetDatabaseEncodingName()))); } }
Datum length_in_encoding | ( | PG_FUNCTION_ARGS | ) |
Definition at line 504 of file mbutils.c.
References ereport, errcode(), errmsg(), ERROR, NameStr, pg_char_to_encoding(), PG_GETARG_BYTEA_P, PG_GETARG_NAME, PG_RETURN_INT32, pg_verify_mbstr_len(), VARDATA, and VARSIZE.
{ bytea *string = PG_GETARG_BYTEA_P(0); char *src_encoding_name = NameStr(*PG_GETARG_NAME(1)); int src_encoding = pg_char_to_encoding(src_encoding_name); int len = VARSIZE(string) - VARHDRSZ; int retval; if (src_encoding < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid encoding name \"%s\"", src_encoding_name))); retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false); PG_RETURN_INT32(retval); }
static char * perform_default_encoding_conversion | ( | const char * | src, | |
int | len, | |||
bool | is_client_to_server | |||
) | [static] |
Definition at line 646 of file mbutils.c.
References CStringGetDatum, pg_enc2name::encoding, ereport, errcode(), errdetail(), errmsg(), ERROR, FunctionCall5, Int32GetDatum, MAX_CONVERSION_GROWTH, MaxAllocSize, NULL, and palloc().
Referenced by pg_any_to_server(), and pg_server_to_any().
{ char *result; int src_encoding, dest_encoding; FmgrInfo *flinfo; if (is_client_to_server) { src_encoding = ClientEncoding->encoding; dest_encoding = DatabaseEncoding->encoding; flinfo = ToServerConvProc; } else { src_encoding = DatabaseEncoding->encoding; dest_encoding = ClientEncoding->encoding; flinfo = ToClientConvProc; } if (flinfo == NULL) return (char *) src; /* * Allocate space for conversion result, being wary of integer overflow */ if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("out of memory"), errdetail("String of %d bytes is too long for encoding conversion.", len))); result = palloc(len * MAX_CONVERSION_GROWTH + 1); FunctionCall5(flinfo, Int32GetDatum(src_encoding), Int32GetDatum(dest_encoding), CStringGetDatum(src), CStringGetDatum(result), Int32GetDatum(len)); return result; }
char* pg_any_to_server | ( | const char * | s, | |
int | len, | |||
int | encoding | |||
) |
Definition at line 549 of file mbutils.c.
References Assert, pg_enc2name::encoding, ereport, errcode(), errmsg(), ERROR, i, IS_HIGHBIT_SET, name, perform_default_encoding_conversion(), pg_do_encoding_conversion(), pg_enc2name_tbl, PG_SQL_ASCII, PG_VALID_BE_ENCODING, and pg_verify_mbstr().
Referenced by CopyReadLine(), json_lex_string(), and pg_client_to_server().
{ Assert(DatabaseEncoding); Assert(ClientEncoding); if (len <= 0) return (char *) s; if (encoding == DatabaseEncoding->encoding || encoding == PG_SQL_ASCII) { /* * No conversion is needed, but we must still validate the data. */ (void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false); return (char *) s; } if (DatabaseEncoding->encoding == PG_SQL_ASCII) { /* * No conversion is possible, but we must still validate the data, * because the client-side code might have done string escaping using * the selected client_encoding. If the client encoding is ASCII-safe * then we just do a straight validation under that encoding. For an * ASCII-unsafe encoding we have a problem: we dare not pass such data * to the parser but we have no way to convert it. We compromise by * rejecting the data if it contains any non-ASCII characters. */ if (PG_VALID_BE_ENCODING(encoding)) (void) pg_verify_mbstr(encoding, s, len, false); else { int i; for (i = 0; i < len; i++) { if (s[i] == '\0' || IS_HIGHBIT_SET(s[i])) ereport(ERROR, (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), errmsg("invalid byte value for encoding \"%s\": 0x%02x", pg_enc2name_tbl[PG_SQL_ASCII].name, (unsigned char) s[i]))); } } return (char *) s; } if (ClientEncoding->encoding == encoding) return perform_default_encoding_conversion(s, len, true); else return (char *) pg_do_encoding_conversion( (unsigned char *) s, len, encoding, DatabaseEncoding->encoding); }
void pg_bind_textdomain_codeset | ( | const char * | domainname | ) |
Definition at line 888 of file mbutils.c.
References elog, encoding, GetDatabaseEncoding(), i, LOG, name, pg_enc2gettext::name, NULL, pg_enc2gettext_tbl, and pg_strcasecmp().
Referenced by CheckMyDatabase(), and pg_bindtextdomain().
{ #if defined(ENABLE_NLS) int encoding = GetDatabaseEncoding(); int i; /* * gettext() uses the codeset specified by LC_CTYPE by default, so if that * matches the database encoding we don't need to do anything. In CREATE * DATABASE, we enforce or trust that the locale's codeset matches * database encoding, except for the C locale. In C locale, we bind * gettext() explicitly to the right codeset. * * On Windows, though, gettext() tends to get confused so we always bind * it. */ #ifndef WIN32 const char *ctype = setlocale(LC_CTYPE, NULL); if (pg_strcasecmp(ctype, "C") != 0 && pg_strcasecmp(ctype, "POSIX") != 0) return; #endif for (i = 0; pg_enc2gettext_tbl[i].name != NULL; i++) { if (pg_enc2gettext_tbl[i].encoding == encoding) { if (bind_textdomain_codeset(domainname, pg_enc2gettext_tbl[i].name) == NULL) elog(LOG, "bind_textdomain_codeset failed"); break; } } #endif }
Datum pg_client_encoding | ( | PG_FUNCTION_ARGS | ) |
Definition at line 946 of file mbutils.c.
References Assert, CStringGetDatum, DirectFunctionCall1, pg_enc2name::name, and namein().
{ Assert(ClientEncoding); return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name)); }
char* pg_client_to_server | ( | const char * | s, | |
int | len | |||
) |
Definition at line 538 of file mbutils.c.
References Assert, pg_enc2name::encoding, and pg_any_to_server().
Referenced by exec_bind_message(), parse_fcall_arguments(), pq_getmsgstring(), and pq_getmsgtext().
{ Assert(ClientEncoding); return pg_any_to_server(s, len, ClientEncoding->encoding); }
Datum pg_convert | ( | PG_FUNCTION_ARGS | ) |
Definition at line 447 of file mbutils.c.
References ereport, errcode(), errmsg(), ERROR, NameStr, palloc(), pfree(), pg_char_to_encoding(), pg_do_encoding_conversion(), PG_FREE_IF_COPY, PG_GETARG_BYTEA_PP, PG_GETARG_NAME, PG_RETURN_BYTEA_P, pg_verify_mbstr_len(), SET_VARSIZE, VARDATA, VARDATA_ANY, VARHDRSZ, and VARSIZE_ANY_EXHDR.
Referenced by pg_convert_from(), and pg_convert_to().
{ bytea *string = PG_GETARG_BYTEA_PP(0); char *src_encoding_name = NameStr(*PG_GETARG_NAME(1)); int src_encoding = pg_char_to_encoding(src_encoding_name); char *dest_encoding_name = NameStr(*PG_GETARG_NAME(2)); int dest_encoding = pg_char_to_encoding(dest_encoding_name); const char *src_str; char *dest_str; bytea *retval; int len; if (src_encoding < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid source encoding name \"%s\"", src_encoding_name))); if (dest_encoding < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid destination encoding name \"%s\"", dest_encoding_name))); /* make sure that source string is valid */ len = VARSIZE_ANY_EXHDR(string); src_str = VARDATA_ANY(string); pg_verify_mbstr_len(src_encoding, src_str, len, false); dest_str = (char *) pg_do_encoding_conversion( (unsigned char *) src_str, len, src_encoding, dest_encoding); if (dest_str != src_str) len = strlen(dest_str); /* * build bytea data type structure. */ retval = (bytea *) palloc(len + VARHDRSZ); SET_VARSIZE(retval, len + VARHDRSZ); memcpy(VARDATA(retval), dest_str, len); if (dest_str != src_str) pfree(dest_str); /* free memory if allocated by the toaster */ PG_FREE_IF_COPY(string, 0); PG_RETURN_BYTEA_P(retval); }
Datum pg_convert_from | ( | PG_FUNCTION_ARGS | ) |
Definition at line 420 of file mbutils.c.
References CStringGetDatum, DirectFunctionCall1, DirectFunctionCall3, pg_enc2name::name, namein(), pg_convert(), PG_GETARG_DATUM, and PG_RETURN_DATUM.
{ Datum string = PG_GETARG_DATUM(0); Datum src_encoding_name = PG_GETARG_DATUM(1); Datum dest_encoding_name = DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name)); Datum result; result = DirectFunctionCall3(pg_convert, string, src_encoding_name, dest_encoding_name); /* * pg_convert returns a bytea, which we in turn return as text, relying on * the fact that they are both in fact varlena types, and thus * structurally identical. Although not all bytea values are valid text, * in this case it will be because we've told pg_convert to return one * that is valid as text in the current database encoding. */ PG_RETURN_DATUM(result); }
Datum pg_convert_to | ( | PG_FUNCTION_ARGS | ) |
Definition at line 395 of file mbutils.c.
References CStringGetDatum, DirectFunctionCall1, DirectFunctionCall3, pg_enc2name::name, namein(), pg_convert(), PG_GETARG_DATUM, and PG_RETURN_DATUM.
{ Datum string = PG_GETARG_DATUM(0); Datum dest_encoding_name = PG_GETARG_DATUM(1); Datum src_encoding_name = DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name)); Datum result; /* * pg_convert expects a bytea as its first argument. We're passing it a * text argument here, relying on the fact that they are both in fact * varlena types, and thus structurally identical. */ result = DirectFunctionCall3(pg_convert, string, src_encoding_name, dest_encoding_name); PG_RETURN_DATUM(result); }
unsigned char* pg_do_encoding_conversion | ( | unsigned char * | src, | |
int | len, | |||
int | src_encoding, | |||
int | dest_encoding | |||
) |
Definition at line 328 of file mbutils.c.
References CStringGetDatum, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, FindDefaultConversionProc(), Int32GetDatum, IsTransactionState(), LOG, MAX_CONVERSION_GROWTH, MaxAllocSize, ObjectIdGetDatum, OidFunctionCall5, OidIsValid, palloc(), pg_encoding_to_char(), PG_SQL_ASCII, PROCOID, and SearchSysCacheExists1.
Referenced by ASN1_STRING_to_text(), convert_charset(), db_encoding_strdup(), dsnowball_lexize(), hv_fetch_string(), hv_store_string(), pg_any_to_server(), pg_convert(), pg_server_to_any(), pg_stat_statements(), PLyUnicode_Bytes(), read_extension_script_file(), t_readline(), unicode_to_sqlchar(), utf_e2u(), utf_u2e(), X509_NAME_to_text(), and xml_recv().
{ unsigned char *result; Oid proc; if (!IsTransactionState()) return src; if (src_encoding == dest_encoding) return src; if (src_encoding == PG_SQL_ASCII || dest_encoding == PG_SQL_ASCII) return src; if (len <= 0) return src; proc = FindDefaultConversionProc(src_encoding, dest_encoding); if (!OidIsValid(proc)) { ereport(LOG, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist", pg_encoding_to_char(src_encoding), pg_encoding_to_char(dest_encoding)))); return src; } /* * XXX we should avoid throwing errors in OidFunctionCall. Otherwise we * are going into infinite loop! So we have to make sure that the * function exists before calling OidFunctionCall. */ if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(proc))) { elog(LOG, "cache lookup failed for function %u", proc); return src; } /* * Allocate space for conversion result, being wary of integer overflow */ if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("out of memory"), errdetail("String of %d bytes is too long for encoding conversion.", len))); result = palloc(len * MAX_CONVERSION_GROWTH + 1); OidFunctionCall5(proc, Int32GetDatum(src_encoding), Int32GetDatum(dest_encoding), CStringGetDatum(src), CStringGetDatum(result), Int32GetDatum(len)); return result; }
int pg_dsplen | ( | const char * | mbstr | ) |
Definition at line 744 of file mbutils.c.
References pg_wchar_tbl::dsplen, pg_enc2name::encoding, and pg_wchar_table.
Referenced by p_isspecial().
{ return ((*pg_wchar_table[DatabaseEncoding->encoding].dsplen) ((const unsigned char *) mbstr)); }
Datum pg_encoding_max_length_sql | ( | PG_FUNCTION_ARGS | ) |
Definition at line 524 of file mbutils.c.
References encoding, PG_GETARG_INT32, PG_RETURN_INT32, PG_RETURN_NULL, PG_VALID_ENCODING, and pg_wchar_table.
{ int encoding = PG_GETARG_INT32(0); if (PG_VALID_ENCODING(encoding)) PG_RETURN_INT32(pg_wchar_table[encoding].maxmblen); else PG_RETURN_NULL(); }
int pg_encoding_mb2wchar_with_len | ( | int | encoding, | |
const char * | from, | |||
pg_wchar * | to, | |||
int | len | |||
) |
Definition at line 707 of file mbutils.c.
References pg_wchar_table.
{ return (*pg_wchar_table[encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len); }
int pg_encoding_mbcliplen | ( | int | encoding, | |
const char * | mbstr, | |||
int | len, | |||
int | limit | |||
) |
Definition at line 807 of file mbutils.c.
References cliplen(), pg_wchar_tbl::mblen, pg_encoding_max_length(), and pg_wchar_table.
Referenced by generate_normalized_query(), pg_mbcliplen(), pgss_shmem_startup(), and pgss_store().
{ mblen_converter mblen_fn; int clen = 0; int l; /* optimization for single byte encoding */ if (pg_encoding_max_length(encoding) == 1) return cliplen(mbstr, len, limit); mblen_fn = pg_wchar_table[encoding].mblen; while (len > 0 && *mbstr) { l = (*mblen_fn) ((const unsigned char *) mbstr); if ((clen + l) > limit) break; clen += l; if (clen == limit) break; len -= l; mbstr += l; } return clen; }
int pg_encoding_wchar2mb_with_len | ( | int | encoding, | |
const pg_wchar * | from, | |||
char * | to, | |||
int | len | |||
) |
Definition at line 729 of file mbutils.c.
References pg_wchar_table.
{ return (*pg_wchar_table[encoding].wchar2mb_with_len) (from, (unsigned char *)to, len); }
int pg_get_client_encoding | ( | void | ) |
Definition at line 291 of file mbutils.c.
References Assert, and pg_enc2name::encoding.
Referenced by BeginCopy(), and xml_send().
{ Assert(ClientEncoding); return ClientEncoding->encoding; }
const char* pg_get_client_encoding_name | ( | void | ) |
Definition at line 301 of file mbutils.c.
References Assert, and pg_enc2name::name.
{ Assert(ClientEncoding); return ClientEncoding->name; }
int pg_mb2wchar | ( | const char * | from, | |
pg_wchar * | to | |||
) |
Definition at line 693 of file mbutils.c.
References pg_enc2name::encoding, pg_wchar_tbl::mb2wchar_with_len, and pg_wchar_table.
{ return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, strlen(from)); }
int pg_mb2wchar_with_len | ( | const char * | from, | |
pg_wchar * | to, | |||
int | len | |||
) |
Definition at line 700 of file mbutils.c.
References pg_enc2name::encoding, pg_wchar_tbl::mb2wchar_with_len, and pg_wchar_table.
Referenced by check_ident_usermap(), CheckAffix(), NIAddAffix(), parse_ident_line(), RE_compile(), RE_compile_and_cache(), RE_execute(), replace_text_regexp(), setup_regexp_matches(), text_position_setup(), and TParserInit().
{ return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len); }
int pg_mbcharcliplen | ( | const char * | mbstr, | |
int | len, | |||
int | limit | |||
) |
Definition at line 839 of file mbutils.c.
References cliplen(), pg_database_encoding_max_length(), and pg_mblen().
Referenced by bpchar(), bpchar_input(), text_left(), text_right(), varchar(), and varchar_input().
{ int clen = 0; int nch = 0; int l; /* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return cliplen(mbstr, len, limit); while (len > 0 && *mbstr) { l = pg_mblen(mbstr); nch++; if (nch > limit) break; clen += l; len -= l; mbstr += l; } return clen; }
int pg_mbcliplen | ( | const char * | mbstr, | |
int | len, | |||
int | limit | |||
) |
Definition at line 797 of file mbutils.c.
References pg_enc2name::encoding, and pg_encoding_mbcliplen().
Referenced by bpchar_name(), ChooseIndexColumnNames(), ExecBuildSlotValueDescription(), limit_printout_length(), make_greater_string(), makeObjectName(), namein(), pgstat_report_activity(), pgstat_report_appname(), text_name(), text_to_cstring_buffer(), and truncate_identifier().
{ return pg_encoding_mbcliplen(DatabaseEncoding->encoding, mbstr, len, limit); }
int pg_mblen | ( | const char * | mbstr | ) |
Definition at line 737 of file mbutils.c.
References pg_enc2name::encoding, pg_wchar_tbl::mblen, and pg_wchar_table.
Referenced by addFlagValue(), appendStringInfoRegexpSubstr(), charlen_to_bytelen(), check_replace_text_has_escape_char(), dotrim(), extract_mb_char(), find_word(), findchar(), findwrd(), gbt_var_node_cp_len(), get_modifiers(), get_wildcard_part(), getlexeme(), gettoken_query(), gettoken_tsvector(), infix(), initSuffixTree(), json_lex_string(), levenshtein_internal(), lpad(), lquery_in(), ltree_in(), make_trigrams(), map_sql_identifier_to_xml_name(), map_xml_name_to_sql_identifier(), match_prosrc_to_literal(), NIImportAffixes(), NIImportDictionary(), NIImportOOAffixes(), parse_affentry(), pg_mbcharcliplen(), pg_mbstrlen(), pg_mbstrlen_with_len(), readstoplist(), report_json_context(), rpad(), RS_compile(), RS_execute(), RS_isRegis(), text_reverse(), text_substring(), text_to_array_internal(), thesaurusRead(), TParserGet(), translate(), ts_stat_sql(), tsvectorout(), unaccent_lexize(), and wchareq().
{ return ((*pg_wchar_table[DatabaseEncoding->encoding].mblen) ((const unsigned char *) mbstr)); }
int pg_mbstrlen | ( | const char * | mbstr | ) |
Definition at line 751 of file mbutils.c.
References pg_database_encoding_max_length(), and pg_mblen().
Referenced by text_format_append_string().
{ int len = 0; /* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return strlen(mbstr); while (*mbstr) { mbstr += pg_mblen(mbstr); len++; } return len; }
int pg_mbstrlen_with_len | ( | const char * | mbstr, | |
int | limit | |||
) |
Definition at line 771 of file mbutils.c.
References pg_database_encoding_max_length(), and pg_mblen().
Referenced by bpchar(), bpchar_input(), bpcharlen(), levenshtein_internal(), lpad(), match_prosrc_to_query(), parser_errposition(), plpgsql_scanner_errposition(), rpad(), text_left(), text_length(), text_right(), and text_substring().
{ int len = 0; /* optimization for single byte encoding */ if (pg_database_encoding_max_length() == 1) return limit; while (limit > 0 && *mbstr) { int l = pg_mblen(mbstr); limit -= l; mbstr += l; len++; } return len; }
char* pg_server_to_any | ( | const char * | s, | |
int | len, | |||
int | encoding | |||
) |
Definition at line 619 of file mbutils.c.
References Assert, pg_enc2name::encoding, perform_default_encoding_conversion(), pg_do_encoding_conversion(), and PG_SQL_ASCII.
Referenced by CopyAttributeOutCSV(), CopyAttributeOutText(), CopyTo(), and pg_server_to_client().
{ Assert(DatabaseEncoding); Assert(ClientEncoding); if (len <= 0) return (char *) s; if (encoding == DatabaseEncoding->encoding || encoding == PG_SQL_ASCII || DatabaseEncoding->encoding == PG_SQL_ASCII) return (char *) s; /* assume data is valid */ if (ClientEncoding->encoding == encoding) return perform_default_encoding_conversion(s, len, false); else return (char *) pg_do_encoding_conversion( (unsigned char *) s, len, DatabaseEncoding->encoding, encoding); }
char* pg_server_to_client | ( | const char * | s, | |
int | len | |||
) |
Definition at line 608 of file mbutils.c.
References Assert, pg_enc2name::encoding, and pg_server_to_any().
Referenced by pq_puttextmessage(), pq_sendcountedtext(), pq_sendstring(), and pq_sendtext().
{ Assert(ClientEncoding); return pg_server_to_any(s, len, ClientEncoding->encoding); }
int pg_wchar2mb | ( | const pg_wchar * | from, | |
char * | to | |||
) |
Definition at line 715 of file mbutils.c.
References pg_enc2name::encoding, pg_wchar_strlen(), pg_wchar_table, and pg_wchar_tbl::wchar2mb_with_len.
{ return (*pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len) (from, (unsigned char *)to, pg_wchar_strlen(from)); }
int pg_wchar2mb_with_len | ( | const pg_wchar * | from, | |
char * | to, | |||
int | len | |||
) |
Definition at line 722 of file mbutils.c.
References pg_enc2name::encoding, pg_wchar_table, and pg_wchar_tbl::wchar2mb_with_len.
Referenced by convertPgWchar(), and regexp_fixed_prefix().
{ return (*pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len) (from, (unsigned char *)to, len); }
int PrepareClientEncoding | ( | int | encoding | ) |
Definition at line 88 of file mbutils.c.
References backend_startup_complete, ConvProcInfo::c_encoding, FindDefaultConversionProc(), fmgr_info_cxt(), GetDatabaseEncoding(), IsTransactionState(), lcons(), lfirst, MemoryContextAlloc(), MemoryContextSwitchTo(), OidIsValid, PG_SQL_ASCII, PG_VALID_FE_ENCODING, ConvProcInfo::s_encoding, ConvProcInfo::to_client_info, ConvProcInfo::to_server_info, and TopMemoryContext.
Referenced by check_client_encoding(), and InitializeClientEncoding().
{ int current_server_encoding; ListCell *lc; if (!PG_VALID_FE_ENCODING(encoding)) return -1; /* Can't do anything during startup, per notes above */ if (!backend_startup_complete) return 0; current_server_encoding = GetDatabaseEncoding(); /* * Check for cases that require no conversion function. */ if (current_server_encoding == encoding || current_server_encoding == PG_SQL_ASCII || encoding == PG_SQL_ASCII) return 0; if (IsTransactionState()) { /* * If we're in a live transaction, it's safe to access the catalogs, * so look up the functions. We repeat the lookup even if the info is * already cached, so that we can react to changes in the contents of * pg_conversion. */ Oid to_server_proc, to_client_proc; ConvProcInfo *convinfo; MemoryContext oldcontext; to_server_proc = FindDefaultConversionProc(encoding, current_server_encoding); if (!OidIsValid(to_server_proc)) return -1; to_client_proc = FindDefaultConversionProc(current_server_encoding, encoding); if (!OidIsValid(to_client_proc)) return -1; /* * Load the fmgr info into TopMemoryContext (could still fail here) */ convinfo = (ConvProcInfo *) MemoryContextAlloc(TopMemoryContext, sizeof(ConvProcInfo)); convinfo->s_encoding = current_server_encoding; convinfo->c_encoding = encoding; fmgr_info_cxt(to_server_proc, &convinfo->to_server_info, TopMemoryContext); fmgr_info_cxt(to_client_proc, &convinfo->to_client_info, TopMemoryContext); /* Attach new info to head of list */ oldcontext = MemoryContextSwitchTo(TopMemoryContext); ConvProcList = lcons(convinfo, ConvProcList); MemoryContextSwitchTo(oldcontext); /* * We cannot yet remove any older entry for the same encoding pair, * since it could still be in use. SetClientEncoding will clean up. */ return 0; /* success */ } else { /* * If we're not in a live transaction, the only thing we can do is * restore a previous setting using the cache. This covers all * transaction-rollback cases. The only case it might not work for is * trying to change client_encoding on the fly by editing * postgresql.conf and SIGHUP'ing. Which would probably be a stupid * thing to do anyway. */ foreach(lc, ConvProcList) { ConvProcInfo *oldinfo = (ConvProcInfo *) lfirst(lc); if (oldinfo->s_encoding == current_server_encoding && oldinfo->c_encoding == encoding) return 0; } return -1; /* it's not cached, so fail */ } }
int SetClientEncoding | ( | int | encoding | ) |
Definition at line 186 of file mbutils.c.
References backend_startup_complete, ConvProcInfo::c_encoding, GetDatabaseEncoding(), lfirst, list_delete_cell(), list_head(), lnext, pending_client_encoding, pfree(), pg_enc2name_tbl, PG_SQL_ASCII, PG_VALID_FE_ENCODING, ConvProcInfo::s_encoding, ConvProcInfo::to_client_info, and ConvProcInfo::to_server_info.
Referenced by assign_client_encoding(), and InitializeClientEncoding().
{ int current_server_encoding; bool found; ListCell *lc; ListCell *prev; ListCell *next; if (!PG_VALID_FE_ENCODING(encoding)) return -1; /* Can't do anything during startup, per notes above */ if (!backend_startup_complete) { pending_client_encoding = encoding; return 0; } current_server_encoding = GetDatabaseEncoding(); /* * Check for cases that require no conversion function. */ if (current_server_encoding == encoding || current_server_encoding == PG_SQL_ASCII || encoding == PG_SQL_ASCII) { ClientEncoding = &pg_enc2name_tbl[encoding]; ToServerConvProc = NULL; ToClientConvProc = NULL; return 0; } /* * Search the cache for the entry previously prepared by * PrepareClientEncoding; if there isn't one, we lose. While at it, * release any duplicate entries so that repeated Prepare/Set cycles don't * leak memory. */ found = false; prev = NULL; for (lc = list_head(ConvProcList); lc; lc = next) { ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc); next = lnext(lc); if (convinfo->s_encoding == current_server_encoding && convinfo->c_encoding == encoding) { if (!found) { /* Found newest entry, so set up */ ClientEncoding = &pg_enc2name_tbl[encoding]; ToServerConvProc = &convinfo->to_server_info; ToClientConvProc = &convinfo->to_client_info; found = true; } else { /* Duplicate entry, release it */ ConvProcList = list_delete_cell(ConvProcList, lc, prev); pfree(convinfo); continue; /* prev mustn't advance */ } } prev = lc; } if (found) return 0; /* success */ else return -1; /* it's not cached, so fail */ }
void SetDatabaseEncoding | ( | int | encoding | ) |
Definition at line 875 of file mbutils.c.
References Assert, elog, pg_enc2name::encoding, ERROR, pg_enc2name_tbl, and PG_VALID_BE_ENCODING.
Referenced by CheckMyDatabase().
{ if (!PG_VALID_BE_ENCODING(encoding)) elog(ERROR, "invalid database encoding: %d", encoding); DatabaseEncoding = &pg_enc2name_tbl[encoding]; Assert(DatabaseEncoding->encoding == encoding); }
bool backend_startup_complete = false [static] |
Definition at line 68 of file mbutils.c.
Referenced by InitializeClientEncoding(), PrepareClientEncoding(), and SetClientEncoding().
pg_enc2name* ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII] [static] |
List* ConvProcList = NIL [static] |
pg_enc2name* DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII] [static] |
int pending_client_encoding = PG_SQL_ASCII [static] |
Definition at line 69 of file mbutils.c.
Referenced by InitializeClientEncoding(), and SetClientEncoding().
pg_enc2name* PlatformEncoding = NULL [static] |
FmgrInfo* ToClientConvProc = NULL [static] |
FmgrInfo* ToServerConvProc = NULL [static] |