我在Postgres上创建了一个新的架构,其长度大于63 bytes
个字符。
CREATE SCHEMA "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz";
上面的语句创建了一个模式abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghi
Postgres自动删除多余的字节,并仅用63个字节创建模式(我期待一个错误)。
然后我运行以下命令:
SET search_path TO 'abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz';
SHOW search_path;
CREATE TABLE deepak(item varchar);
INSERT INTO deepak SELECT 'a';
TABLE "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz".deepak;
我的问题是
search_path
返回全名,但使新的63字节的名称架构处于活动状态。这是怎么发生的?select
语句也可以选择table deepak
。怎么可能?我也检查了information_schema.schemata
和pg_tables
。这些表中存在63字节的名称。
答案 0 :(得分:0)
您正在使用哪个版本的Postgres,更重要的是您使用哪个客户端连接到Postgres?
在带有psql的Postgres 11下,Postgres将模式名称截断为63个字节,但告诉我它是这样做的:
test=> CREATE SCHEMA "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz";
NOTICE: identifier "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz" will be truncated to "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghi"
CREATE SCHEMA
test=> SET search_path TO 'abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz';
SET
test=> SHOW search_path;
search_path
----------------------------------------------------------------------------------
abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz
(1 row)
test=> CREATE TABLE deepak(item varchar);
CREATE TABLE
test=> INSERT INTO deepak SELECT 'a';
INSERT 0 1
test=> \dt deepak
List of relations
Schema | Name | Type | Owner
-----------------------------------------------------------------+--------+-------+----------
abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghi | deepak | table | laetitia
(1 row)
test=> TABLE "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz".deepak;
NOTICE: identifier "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz" will be truncated to "abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghi"
item
------
a
(1 row)
由于它总是会截断标识符,因此查询很好...您是否希望收到错误?还是更清楚地知道模式名称是否在search_path
中被截断了?
答案 1 :(得分:0)
其原因是所有对象名称均为数据类型name
。比较pg_namespace
的定义,该定义是包含架构的系统目录:
\d pg_namespace
Table "pg_catalog.pg_namespace"
Column | Type | Collation | Nullable | Default
----------+-----------+-----------+----------+---------
nspname | name | | not null |
nspowner | oid | | not null |
nspacl | aclitem[] | | |
Indexes:
"pg_namespace_nspname_index" UNIQUE, btree (nspname)
"pg_namespace_oid_index" UNIQUE, btree (oid)
name
在src/include/c.h
中定义(NAMEDATALEN
为64,但是最后一个字节为0,因此有效长度为63):
/*
* Representation of a Name: effectively just a C string, but null-padded to
* exactly NAMEDATALEN bytes. The use of a struct is historical.
*/
typedef struct nameData
{
char data[NAMEDATALEN];
} NameData;
typedef NameData *Name;
#define NameStr(name) ((name).data)
解析器处理标识符时,会将其截断为NAMEDATALEN-1
。
从2000年6月开始(commit 0672a3c081)开始,这种删减方法就产生了NOTICE
,因此,如果您没有看到该通知,我会感到惊讶(除非您设置了client_min_messages
到warning
或error
)。
search_path
是一个没有长度限制的常规C字符串,因此它可以包含超过63个字节的模式名称,但是由于条目被强制转换为name
,因此多余的字符将被有效地忽略。
这并不漂亮,我认为该消息至少应为WARNING
。您可能希望将其与黑客邮件列表一起使用(或为其编写补丁)。将级别提高到ERROR
是最干净的解决方案,但对向后兼容性不利。