Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions | Variables

mbutils.c File Reference

#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"
Include dependency graph for mbutils.c:

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 ListConvProcList = NIL
static FmgrInfoToServerConvProc = NULL
static FmgrInfoToClientConvProc = NULL
static pg_enc2nameClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]
static pg_enc2nameDatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII]
static pg_enc2namePlatformEncoding = NULL
static bool backend_startup_complete = false
static int pending_client_encoding = PG_SQL_ASCII

Define Documentation

#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 Documentation

typedef struct ConvProcInfo ConvProcInfo

Function Documentation

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   ) 
Datum getdatabaseencoding ( PG_FUNCTION_ARGS   ) 
const char* GetDatabaseEncodingName ( void   ) 
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   ) 
char* pg_client_to_server ( const char *  s,
int  len 
)
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().

const char* pg_get_client_encoding_name ( void   ) 

Definition at line 301 of file mbutils.c.

References Assert, and pg_enc2name::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 
)
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 
)
int pg_mblen ( const 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 
)
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  ) 

Variable Documentation

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]

Definition at line 58 of file mbutils.c.

List* ConvProcList = NIL [static]

Definition at line 46 of file mbutils.c.

pg_enc2name* DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII] [static]

Definition at line 59 of file mbutils.c.

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]

Definition at line 60 of file mbutils.c.

FmgrInfo* ToClientConvProc = NULL [static]

Definition at line 53 of file mbutils.c.

FmgrInfo* ToServerConvProc = NULL [static]

Definition at line 52 of file mbutils.c.