EDB*Plus的client_encoding问题

本文探讨了PostgreSQL中client_encoding配置的实际效果,并通过源代码分析揭示了其背后的机制。当使用psql连接到数据库时,实际使用的字符集由数据库自身编码决定而非postgresql.conf文件中的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

磨砺技术珠矶,践行数据之道,追求卓越价值

回到上一级页面:PostgreSQL内部结构与源代码研究索引页    回到顶级页面:PostgreSQL索引页

[作者 高健@博客园  luckyjackgao@gmail.com] 

 

我的PPAS下,edb数据库的Encoding是 UTF8:

edb=# \l
                                        List of databases
   Name    |    Owner     | Encoding |   Collate   |    Ctype    |       Access 
privileges       
-----------+--------------+----------+-------------+-------------+--------------
-----------------
 edb       | enterprisedb | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | enterprisedb | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | enterprisedb | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/enterprisedb              +
           |              |          |             |             | enterprisedb=CTc/enterprisedb
 template1 | enterprisedb | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/enterprisedb              +
           |              |          |             |             | enterprisedb=CTc/enterprisedb
(4 rows)

edb=# 。

而我在postgresql.conf里面去设置 client_encoding,无论如何也无法生效。

client_encoding = sql_ascii             # actually, defaults to database
                                        # encoding

重新启动后也不行:

edb=# show client_encoding;
 client_encoding 
-----------------
 UTF8
(1 row)

edb=# 

也就是说,client_encoding的值,就算是设置了,也未必起作用。

查看社区版PostgreSQL的源代码作参考,看看是为何:

当我用psql连接到数据库时,CheckMyDatabase函数就会被执行。

我注意到其中的这一段:

    /* If we have no other source of client_encoding, use server encoding */  
    SetConfigOption("client_encoding", GetDatabaseEncodingName(),                                
                    PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); 

在准备client_encoding的时候,它用了 GetDatabaseEncodingName()函数,来返回数据库的Encoding名称。

可以认为,其实postgresql.conf里的 client_encoding的设定是没有用处的,因为内部运算的时候直接拿来了所连接的数据库的Encoding。也可以说,client_encoding是一个历史遗留问题,是PostgreSQL的开发者的失误造成的!

/*                                    
 * CheckMyDatabase -- fetch information from the pg_database entry for our DB
 */                                    
static void                                    
CheckMyDatabase(const char *name, bool am_superuser)                                    
{                                    
                        
    HeapTuple    tup;                            
    Form_pg_database dbform;                                
    char       *collate;                            
    char       *ctype;                            
                                    
    /* Fetch our pg_database row normally, via syscache */                                
    tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));                                
    if (!HeapTupleIsValid(tup))                                
        elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);                            
    dbform = (Form_pg_database) GETSTRUCT(tup);                                
                                    
    /* This recheck is strictly paranoia */                                
    if (strcmp(name, NameStr(dbform->datname)) != 0)                                
        ereport(FATAL,                            
                (errcode(ERRCODE_UNDEFINED_DATABASE),                    
                 errmsg("database \"%s\" has disappeared from pg_database",                    
                        name),            
                 errdetail("Database OID %u now seems to belong to \"%s\".",                    
                           MyDatabaseId, NameStr(dbform->datname))));            
                                    
    /*                                
     * Check permissions to connect to the database.    
     * These checks are not enforced when in standalone mode, so that there is  
     * a way to recover from disabling all access to all databases, for                                
     * example "UPDATE pg_database SET datallowconn = false;".                                
     *                                
     * We do not enforce them for autovacuum worker processes either.                                
     */                                
    if (IsUnderPostmaster && !IsAutoVacuumWorkerProcess())                                
    {                                
        /*                            
         * Check that the database is currently allowing connections.                            
         */                            
        if (!dbform->datallowconn)                            
            ereport(FATAL,                        
                    (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),                
             errmsg("database \"%s\" is not currently accepting connections",                        
                    name)));                
                                    
        /*                            
         * Check privilege to connect to the database.    (The am_superuser test                        
         * is redundant, but since we have the flag, might as well check it                            
         * and save a few cycles.)                            
         */                            
        if (!am_superuser &&                            
            pg_database_aclcheck(MyDatabaseId, GetUserId(),                        
                                 ACL_CONNECT) != ACLCHECK_OK)    
            ereport(FATAL,                        
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),                
                     errmsg("permission denied for database \"%s\"", name),                
                     errdetail("User does not have CONNECT privilege.")));                
                                    
        /*                            
         * Check connection limit for this database.                            
         *                            
         * There is a race condition here --- we create our PGPROC before                            
         * checking for other PGPROCs.    If two backends did this at about the                        
         * same time, they might both think they were over the limit, while                            
         * ideally one should succeed and one fail.  Getting that to work                            
         * exactly seems more trouble than it is worth, however; instead we                            
         * just document that the connection limit is approximate.                            
         */                            
        if (dbform->datconnlimit >= 0 &&                            
            !am_superuser &&                        
            CountDBBackends(MyDatabaseId) > dbform->datconnlimit)                        
            ereport(FATAL,                        
                    (errcode(ERRCODE_TOO_MANY_CONNECTIONS),                
                     errmsg("too many connections for database \"%s\"",                
                            name)));        
    }                                
                                    
    /*                                
     * OK, we're golden.  Next to-do item is to save the encoding info out of 
     * the pg_database tuple.                                
     */                                
    SetDatabaseEncoding(dbform->encoding);                                
    /* Record it as a GUC internal option, too */                                
    SetConfigOption("server_encoding", GetDatabaseEncodingName(),                                
                    PGC_INTERNAL, PGC_S_OVERRIDE);                
                                    
                                    
    /* If we have no other source of client_encoding, use server encoding */  
    SetConfigOption("client_encoding", GetDatabaseEncodingName(),                                
                    PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);                
                                    
    /* assign locale variables */                                
    collate = NameStr(dbform->datcollate);                                
    ctype = NameStr(dbform->datctype);                                
                                    
    if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)                                
        ereport(FATAL,                            
            (errmsg("database locale is incompatible with operating system"),                        
             errdetail("The database was initialized with LC_COLLATE \"%s\", "                        
                       " which is not recognized by setlocale().", collate),                
             errhint("Recreate the database with another locale or install the missing locale.")));                        
                                    
    if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)                                
        ereport(FATAL,                            
            (errmsg("database locale is incompatible with operating system"),                        
             errdetail("The database was initialized with LC_CTYPE \"%s\", "                        
                       " which is not recognized by setlocale().", ctype),                
             errhint("Recreate the database with another locale or install the missing locale.")));                        
                                    
    /* Make the locale settings visible as GUC variables, too */                                
    SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE);                                
    SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE);                                
                                    
    /* Use the right encoding in translated messages */                                
    #ifdef ENABLE_NLS                                
    pg_bind_textdomain_codeset(textdomain(NULL));                                
    #endif                                
                                    
    ReleaseSysCache(tup);           
                            
}                                    

 

 

[作者 高健@博客园  luckyjackgao@gmail.com]  

回到上一级页面:PostgreSQL内部结构与源代码研究索引页    回到顶级页面:PostgreSQL索引页

磨砺技术珠矶,践行数据之道,追求卓越价值

转载于:https://www.cnblogs.com/gaojian/p/3246327.html

undefined1 cef_browser_host_create_browser (longlong param_1,undefined8 param_2,longlong param_3,longlong param_4,undefined8 param_5, undefined8 param_6) { undefined1 uVar1; double in_XMM0_Qa; undefined1 auStack_248 [32]; undefined8 local_228; undefined8 local_220; undefined8 local_210; undefined ***local_208; longlong local_200; undefined1 local_1f8; undefined8 local_1f0; undefined8 local_1e8; undefined **local_1e0; undefined8 local_1d8; undefined1 local_1d0 [272]; longlong local_c0; undefined **local_b8; undefined8 local_b0; undefined8 uStack_a8; undefined8 local_a0; undefined8 uStack_98; undefined8 local_90; undefined8 uStack_88; undefined8 local_80; undefined8 uStack_78; undefined8 local_70; undefined8 uStack_68; undefined8 local_60; undefined8 uStack_58; longlong local_50; ulonglong local_48; /* 0x81d0 13219 cef_browser_host_create_browser */ local_48 = DAT_189b06ea8 ^ (ulonglong)auStack_248; v8::internal::ConvertDouble<double>(in_XMM0_Qa); uVar1 = 0; if ((param_1 != 0) && (param_4 != 0)) { local_60 = 0; uStack_58 = 0; local_70 = 0; uStack_68 = 0; local_80 = 0; uStack_78 = 0; local_90 = 0; uStack_88 = 0; local_a0 = 0; uStack_98 = 0; local_b0 = 0; uStack_a8 = 0; local_50 = 0; local_b8 = &PTR_FUN_18849f438; FUN_1800083a2(&local_b8,param_1,0); local_1e0 = &PTR_FUN_18849f448; memset(local_1d0,0,0x118); local_1d8 = 0x118; FUN_18000c900(param_4,&local_1d8,0); FUN_180008408(&local_1e8,param_6); FUN_180008480(&local_1f0,param_5); local_208 = &PTR_FUN_18849f050; local_200 = 0; local_1f8 = 0; if (param_3 != 0) { FUN_1800039c0(&local_208); local_200 = param_3; } local_1f8 = 0; FUN_1800084f8(&local_210,param_2); local_220 = local_1e8; local_228 = local_1f0; uVar1 = FUN_182edb8c8(&local_b8,local_210,&local_208,&local_1e0); local_208 = &PTR_FUN_18849f050; FUN_1800039c0(&local_208); local_1e0 = &PTR_FUN_18849f448; if (local_c0 == 0) { FUN_18000c89e(&local_1d8); } local_b8 = &PTR_FUN_18849f438; if (local_50 == 0) { cef_string_utf16_clear(&uStack_a8); } } FUN_18848a3e0(local_48 ^ (ulonglong)auStack_248); return uVar1; }
最新发布
08-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值