Длина схемы PostgreSQL и Search_Path - PullRequest
0 голосов
/ 03 апреля 2019

Я создаю новую схему на 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-байтовое имя.

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

Причина этого заключается в том, что все имена объектов относятся к типу данных 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.

Это усечение подняло NOTICE с начала ( commit 0672a3c081 с июня 2000 г.), поэтому я был бы удивлен, если бы вы не увидели это уведомление (если вы не установили для client_min_messages значение warning или error).

search_path - это обычная строка C без ограничения длины, поэтому она может содержать имена схем, длина которых превышает 63 байта, но поскольку записи преобразуются в name, дополнительные символы фактически игнорируются.

Это не красиво, и я бы сказал, что сообщение должно быть, по крайней мере, WARNING. Вы можете добавить его в список рассылки хакеров (или написать для него патч). Повышение уровня до ERROR было бы самым чистым решением, но было бы плохо для обратной совместимости.

0 голосов
/ 03 апреля 2019

Какую версию Postgres вы используете, и более важно, какой клиент вы используете для подключения к Postgres?

В Postgres 11, с помощью psql, 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?

...