是否有文档描述PostgreSQL服务器坚持的元组格式?官方文档对此似乎很晦涩。
单个元组似乎很简单,可以弄清楚,但是当涉及到元组的数组、复合元组的数组以及复合元组的嵌套数组时,仅通过查看输出就不可能确定格式。
我问这个是在我最初尝试实现pg-tuple之后,一个解析器,今天仍然缺失,能够解析Node.js中的PostgreSQL元组
create type type_A as (
a int,
b text
);
- 复合文本:
(1,"hello world!")
(1,hello)
create type type_B as (
c type_A,
d type_A[]
);
简单值数组:
{"(2,two)","(3,three)"}
对于
type_B[]
我们可以得到:
{"("(7,inner)","{""(88,eight-1)"",""(99,nine-2)""}")","("(77,inner)","{""(888,eight-3)"",""(999,nine-4)""}")"}
对于复合类型的多维数组则更加复杂。
因为感觉根本没有规范,我已经开始扭转它。不确定是否可以完全完成,因为从一些最初的例子中,通常不清楚应用了什么格式规则。
正如Nick所说,根据docs:
如果字段类型是整数,则忽略空白,但不是如果是文本
和
复合输出例程将在field周围加上双引号值,如果它们是空字符串或包含括号、逗号、双引号、反斜杠或空格
和
在字段值中嵌入双引号和反斜杠翻了一倍。
现在引用Nick自己的话:
嵌套元素被转换为字符串,然后加引号/转义像其他字符串
一样
我在下面给出一个简短的例子,与它的嵌套值进行比较:
a=# create table playground (t text, ta text[],f float,fa float[]);
CREATE TABLE
a=# insert into playground select 'space here',array['','bs'],8.0,array[null,8.1];
INSERT 0 1
a=# insert into playground select 'no_space',array[null,'nospace'],9.0,array[9.1,8.0];
INSERT 0 1
a=# select playground,* from playground;
playground | t | ta | f | fa
---------------------------------------------------+------------+----------------+---+------------
("space here","{"""",""bs\\""}",8,"{NULL,8.1}") | space here | {"","bs\"} | 8 | {NULL,8.1}
(no_space,"{NULL,nospace}",9,"{9.1,8}") | no_space | {NULL,nospace} | 9 | {9.1,8}
(2 rows)
如果你需要更深层次的嵌套引号,请看:
a=# select nested,* from (select playground,* from playground) nested;
nested | playground | t | ta | f | fa
-------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+------------+----------------+---+------------
("(""space here"",""{"""""""",""""bs\\\\""""}"",8,""{NULL,8.1}"")","space here","{"""",""bs\\""}",8,"{NULL,8.1}") | ("space here","{"""",""bs\\""}",8,"{NULL,8.1}") | space here | {"","bs\"} | 8 | {NULL,8.1}
("(no_space,""{NULL,nospace}"",9,""{9.1,8}"")",no_space,"{NULL,nospace}",9,"{9.1,8}") | (no_space,"{NULL,nospace}",9,"{9.1,8}") | no_space | {NULL,nospace} | 9 | {9.1,8}
(2 rows)
如您所见,输出再次遵循上述规则。
对你的问题的简短回答是:
- 为什么数组通常在双引号内呈现,而一个空数组突然成为一个开放值?(空数组的文本表示不包含逗号或空格等)
- 为什么一个"突然被呈现为"?(
'one two'
的文本表示,根据上面的规则是"one\ two"
,最后的文本表示是""one\\two""
,这就是你得到的) - 为什么unicode格式的文本会改变的转义?那我们怎么分辨呢?(根据文件,
PostgreSQL也接受"转义"字符串常量SQL标准的扩展。指定转义字符串常量在开头写上字母E(大写或小写)单引号
),所以它不是unicode文本,而是您告诉postgres应该将文本中的转义解释为转义而不是符号的方式。例如,E'''
将被解释为'
, '''
将使其等待关闭'
进行解释。在您的示例E'\ text'
中,它的文本表示将是"\ text"
-我们为反斜杠添加反斜杠并在双引号中接受值-所有这些都在在线文档中描述。
- {和}转义的方式并不总是清楚(我无法回答这个问题,因为它本身不清楚)