暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

我的 PostgreSQL 数据库是空的!

原创 2022-08-11
1464

Table of Contents

本文作者是个有趣的人,总要找一些别人想不到的角度去想问题,下面介绍的是,要在 postgresql 数据库中,创建看起来名称为空的库,schema,role,table等,然后在表中插入看起来没有数据的数据。

1.介绍

作为读者-我喜欢做的一件事,就是挑战PostgreSQL到极致。前段时间我发了关于《It’s beer o’clock for PostgreSQL》的帖子。《Not so equal texts in PostgreSQL - and how to compare texts in a more elaborate way》是另一个有趣的例子。在某些时候,我也会写关于《与星共舞》的博客。
今天什么都不是。空的。所有的数据都去哪儿了?

不久前,我在Twitter上发布了这张截图(由于访问不到Twitter所以无法贴上来),据我所知,没有人找到正确答案。

截图看起来好像什么也没有。空的名称、空的架构名称、空的角色名称、空的数据库名称,甚至没有数据。然而,这一切以某种方式联系到一起。让我们来深挖背后原因。

并不是一无所有,它是有一些“东西”的,但是你看不见。我的目的是要有尽可能多的 “” (空格或零字符)。

在计算机中,可以有一个空的空格字符,也称为"零宽度"。对于计算机来说,这当然是一个符合规则的字符。打印出来的时候什么都没有。
以下的尝试就是找到巧妙地将"空的空格字符或零宽度空间"用于名称和数据的方法。

2.如何得到一个零宽度?

在编辑器中构建这个示例时,在将它粘贴到psql shell之前,我使用了emptycharacter.com网站。它有一个按钮,复制一个空白到剪贴板。还有其他的方式和网站,只是这个对我来说很有效。

3.如何构建DDL?

在我的例子中,大多数对象的名称都是一个零空间宽度。这包括数据库名、角色名、模式名和类型名:

CREATE ROLE "‎" WITH login;
CREATE DATABASE "‎" WITH OWNER "‎";
\c "‎"

CREATE SCHEMA "‎";
SET search_path TO "‎";
CREATE TYPE "‎"."‎" AS ("‎" TEXT);

但是,表名要使用两个零宽度的空格宽度:否则它与前面创建的类型冲突,后者已经是一个零宽度的空格宽度。这两个对象都在零宽度的空白模式中,因为搜索路径被设置为该模式。

CREATE TABLE "‎"."‎‎" ("‎" "‎"."‎" UNIQUE);
ALTER TABLE "‎"."‎‎" OWNER TO "‎";
\dt
\d+ "‎"."‎‎"
=# \dt
       List of relations
 Schema | Name | Type  | Owner 
--------+------+-------+-------
       |    | table | 
(1 row)

=# \d+ "".""
                                      Table "."
 Column | Type | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+------+-----------+----------+---------+----------+--------------+-------------
       | ""  |           |          |         | extended |              | 
Indexes:
    "__key" UNIQUE CONSTRAINT, btree ("")
Access method: heap

目前为止,看起来是如此的空。

4.我还需要更多的 “空”

只有空的结构是不够的,我也想要空数据。在我的示例中,我构建了5条INSERT语句,它们显然都没有向表中插入任何东西,但也没有违反UNIQUE约束。

此时您可能已经猜到了:5个INSERT语句插入了5个不同数量的零宽度空格。必须使用ROW()构造函数,因为我之前创建了一个基于基本TEXT类型的新类型。关于ROW()这种类型的细节我将在我的 “Advanced Datatypes” 演讲中解释。

INSERT INTO "‎"."‎‎" VALUES (ROW('‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎‎‎'));

当我查询数据时,看起来里面什么都没有。但是通过LENGTH()函数查询它,里面显示其中的数据最多有5个字符。

=# SELECT "", LENGTH(("")."") FROM ""."";
        | length 
---------+--------
 ()     |      1
 ()    |      2
 ()   |      3
 ()  |      4
 () |      5
(5 rows)

5.总结

All in all this was rather easy to build, once I figured out the part with the non-printable zero-.width whitespace. The only problem was the tablename which could not be the same as the type name (which I wanted in there because otherwise the \d will show TEXT and not a seemingly empty type).

Full example

Here is the full source code for this example:
总之,这是相当容易建立,就是我需要找出不可显示的零宽度的空格。唯一的问题是表名不能与类型名相同(我想应该是\d显示TEXT,而不是一个看似空的类型)。

下面是这个例子的完整源代码:

\set ON_ERROR_STOP on
\c postgres
-- DROP DATABASE "‎";
-- DROP ROLE "‎";

CREATE ROLE "‎" WITH login;
CREATE DATABASE "‎" WITH OWNER "‎";
\c "‎"

CREATE SCHEMA "‎";
SET search_path TO "‎";
CREATE TYPE "‎"."‎" AS ("‎" TEXT);
CREATE TABLE "‎"."‎‎" ("‎" "‎"."‎" UNIQUE);
ALTER TABLE "‎"."‎‎" OWNER TO "‎";
\dt
\d+ "‎"."‎‎"


-- INSERT INTO "‎"."‎‎" VALUES (ROW(''));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎‎'));
INSERT INTO "‎"."‎‎" VALUES (ROW('‎‎‎‎‎'));

SELECT "‎", LENGTH(("‎")."‎") FROM "‎"."‎‎";

原文标题:My PostgreSQL database is empty!
原文作者:Andreas ‘ads’ Scherbaum
原文地址:https://andreas.scherbaum.la/blog/archives/1113-My-PostgreSQL-database-is-empty!.html

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论