Sor*_*ren 2 c linux postgresql debugging libc
在postgres 9.1和8.4中的简单比较测试中,得到以下奇怪的结果。
postgres=# select 1 one where 'A' < 'a';
one
-----
(0 rows) // ..... I would have expected 1 row
postgres=# select 1 one where 'A' < 'b';
one
-----
1
(1 row) // ...... this looks OK
postgres=# select 1 one where 'A' = 'a';
one
-----
(0 rows) // ...... This also looks OK
postgres=# select 1 one where 'A' > 'a';
one
-----
1
(1 row) // ...... This is inconsistent with the above results
Run Code Online (Sandbox Code Playgroud)
“ A”的ascii值为0x41,“ a”为0x61,因此,直接比较ascii值应意味着“ A”小于“ a”,或者如果某些情况下具有敏感性,那么至少A> b和区域性问题,但是再说一次-但是,使用标准Centos5和Fedora16安装将本地设置为标准us_EN.utf8,结果相同。
将调试器附加到postgres进程中,我已经能够找到问题的根源。
strcoll("A","a") returns 6;
Run Code Online (Sandbox Code Playgroud)
哪里
strcoll("A","b") returns -1;
Run Code Online (Sandbox Code Playgroud)
但是,这只能在postgres进程内部(例如,在附加gdb时)进行演示,并且如下所示的外部程序会给出完全合理的结果。
main()
{
char *a="a";
char *b="b";
char *A="A";
printf("%s\n",setlocale(2,"us_ENG.utf8"));
printf("%d\n",strcoll(A,a));
printf("%d\n",strcoll(A,b));
printf("%d\n",strcoll(a,a));
printf("%d\n",strcoll(b,b));
printf("%d\n",strcoll(a,A));
printf("%d\n",strcoll(b,A));
printf("%d\n",strcoll(b,a));
printf("%d\n",strcoll(A,A));
}
Run Code Online (Sandbox Code Playgroud)
问题是:是否有人对导致strcoll返回错误值的原因有任何想法,以及关于如何修复它以便我的示例SQL可以正常工作的任何建议。
更新:我尝试将数据库重新创建为initdb --locale=C,并且'A'<'a'在此处给出了预期的结果-但是,这不能解释为什么在创建为UTF-8的数据库中此操作会失败。
排序取决于您的数据库语言环境,而不是系统语言环境。(尽管应该注意,PostgreSQL依靠OS提供细节。在Postgres Wiki中有更多信息。)
ASCII值仅与非语言环境相关"C"。
看一下您当前的设置:
SELECT * FROM pg_settings WHERE name ~~ 'lc%';
Run Code Online (Sandbox Code Playgroud)
特别地,的设置LC_COLLATE是相关的。你也可以:
SHOW lc_collate;
Run Code Online (Sandbox Code Playgroud)
在PostgreSQL 9.1中,您可以更改每个语句适用的排序规则。尝试:
SELECT 1 AS one WHERE 'A' < 'a' COLLATE "C";
Run Code Online (Sandbox Code Playgroud)
在较旧的版本中,(大多数情况下)LC_COLLATE您受制于在创建数据库集群时选择的值。
| 归档时间: |
|
| 查看次数: |
574 次 |
| 最近记录: |