powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Бинарный протокол для аргументов и строки
12 сообщений из 12, страница 1 из 1
Бинарный протокол для аргументов и строки
    #39192720
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В prepared выражение:

SELECT $1::text

отправляю в бинарном формате(!) аргумент типа Int8 (число 123) - в ответ приходит не обычная ошибка типа "неверный формат двоичных данных в параметре Вind 1", а такая:

ОШИБКА: неверная последовательность байт для кодировки \"UTF8\": 0x00\n

Примерно понятно откуда Постгрес берёт этот нулевой байт (в сетевом порядке байтов число 123 начинается с него), но непонятно почему он не проверяет сначала тип аргумента. Эдак ведь можно "удачно" заслать число, которое будет воспринято как корректная строка со всеми вытекающими.

Это баг или фича? Для других типов такой проблемы не замечено.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192724
Vladimir Sitnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Weed, пример передаваемых данных в студию (bind command и особенно "The result-column format codes. Each must presently be zero (text) or one (binary)." её часть).
Скорее всего, вы передаёте-таки в текстовом режиме.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192727
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vladimir SitnikovWeed, пример передаваемых данных в студию (bind command


Что такое bind command?

и особенно "The result-column format codes. Each must presently be zero (text) or one (binary)." её часть).
Скорее всего, вы передаёте-таки в текстовом режиме.

Если бы это было так то замена ::text в приведённом выше примере на какой-нибудь ::int4 давала бы аналогичный результат, однако сервер начинает отвечать уже про несоответствие типов.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192731
Vladimir Sitnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Weed,

WeedЧто такое bind command?
http://www.postgresql.org/docs/9.5/static/protocol-message-formats.html -> "Bind command"

Weedотправляю в бинарном формате(!)
Откуда уверенность, что формат именно бинарный?
Где код, которым производится отправка?
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192739
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vladimir SitnikovWeed,

WeedЧто такое bind command?
http://www.postgresql.org/docs/9.5/static/protocol-message-formats.html -> "Bind command"


Это вот не оно? Делается через вызов libpq trace

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
To backend> Msg B
To backend> ""
To backend> "echo"
To backend (2#)> 1
To backend (2#)> 1
To backend (2#)> 1
To backend (4#)> 8
To backend> ^@^@^@^@^@^@^@{
To backend (2#)> 1
To backend (2#)> 1
To backend> Msg complete, length 33
To backend> Msg D
To backend> P
To backend> ""
To backend> Msg complete, length 7
To backend> Msg E
To backend> ""
To backend (4#)> 0
To backend> Msg complete, length 10
To backend> Msg S
To backend> Msg complete, length 5
From backend> E
From backend (#4)> 169
From backend> S
From backend> "ОШИБКА"
From backend> C
From backend> "22021"
From backend> M
From backend> "неверная последовательность байт для кодировки "UTF8": 0x00"
From backend> F
From backend> "wchar.c"
From backend> L
From backend> "2017"
From backend> R
From backend> "report_invalid_encoding"
From backend> ^@
From backend> Z
From backend (#4)> 5
From backend> Z
From backend (#4)> 5
From backend> I

Weedотправляю в бинарном формате(!)
Откуда уверенность, что формат именно бинарный?
Где код, которым производится отправка?[/quot]

https://github.com/denizzzka/dpq2
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192746
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
To backend> ^@^@^@^@^@^@^@{

Вот тут как раз крыжики это, видимо, нули, а скобка в конце это 0x7b == 123
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192765
Vladimir Sitnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
WeedЭто вот не оно? Делается через вызов libpq trace
Да, похоже на то.

Возможно, стоит wireshark'ом посмотреть какие конкретно байты ходят.
Или в самом libpq как-то больше логов включать.

С D-драйвером можно только пожелать "счастливой отладки". Непростое это занятие делать клиенты к базам.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192767
Vladimir Sitnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Одно могу сказать: запрос SELECT $1::text с int8 параметром в binary режиме точно работает.
Проверял на pgjdbc.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192850
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Wireshark показывает то же самое:
(Возможно, хитрость в том, что я для prepare не передаю типы параметров и их количество. Но документация это разрешает, да и для других типов правильная ошибка выводится.)



Vladimir SitnikovОдно могу сказать: запрос SELECT $1::text с int8 параметром в binary режиме точно работает.
Проверял на pgjdbc.

Давно? Могли же и сломать... Моя версия постгреса из Debian 9.5.1-1 (64 битная)
А что подразумевается под "работает"? (Работать не должно ведь - ошибка типов должна быть показана)
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39192908
Vladimir Sitnikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Weed Возможно, хитрость в том, что я для prepare не передаю типы параметров и их количество
Так делать точно не стоит.
Текущая версия PostgreSQL не умеет приводить типы параметров.

Ваша проблема в том, что при parse не указан тип $1 и PG решает, что это должен быть varchar.
Дальше выполняете bind/exec, передавая int8, и, разумеется, оно падает, т.к. PG ожидает varchar.

Выход только один -- при parse передавать типы параметров.

Ещё один случай когда нужны типы при parse -- это когда есть функции/процедуры с одинаковым названием, но разными типами.
Для того, чтобы база поняла какую функцию вызывать, нужен тип на этапе parse.
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39193036
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vladimir SitnikovWeed Возможно, хитрость в том, что я для prepare не передаю типы параметров и их количество
Так делать точно не стоит.
Текущая версия PostgreSQL не умеет приводить типы параметров.

Ваша проблема в том, что при parse не указан тип $1 и PG решает, что это должен быть varchar.
Дальше выполняете bind/exec, передавая int8, и, разумеется, оно падает, т.к. PG ожидает varchar.
Я именно этого и добиваюсь. Проблема в том, что падает он не с той ошибкой, что должна быть.

Выход только один -- при parse передавать типы параметров.
nParams is the number of parameters for which types are pre-specified in the array paramTypes[]. (The array pointer can be NULL when nParams is zero.) paramTypes[] specifies, by OID, the data types to be assigned to the parameter symbols. If paramTypes is NULL, or any particular element in the array is zero, the server assigns a data type to the parameter symbol in the same way it would do for an untyped literal string. Also, the query can use parameter symbols with numbers higher than nParams; data types will be inferred for these symbols as well. (See PQdescribePrepared for a means to find out what data types were inferred.)

То есть, оно должно само определять их типы в выражении (и оно таки их определяет!)

Кажется, я нашёл в чём проблема тут. Если посмотреть на переданные на сервер данные:



то видно, что тип данных Int8 (его десятичный номер 20) там не фигурирует. То есть, функция

Код: plaintext
1.
2.
3.
4.
5.
6.
int PQsendQueryPrepared(PGconn *conn,
                        const char *stmtName,
                        int nParams,
                        const char * const *paramValues,
                        const int *paramLengths,
                        const int *paramFormats,
                        int resultFormat);

не отправляет типы передаваемых данных, хотя и принимает их. Для аргумента она отправляет только длину и сами данные.

И поэтому с другими типами всё хорошо у меня - они отличаются по размерам и постгрес это сразу может увидеть. А типы переменной длины типа текста пытаются принимать значения любой длины, в том числе и 8-байтные. Отсюда и такая ошибка.

Зачем тогда PQsendQueryPrepared принимает paramFormats? Очень загадочная багофича!
...
Рейтинг: 0 / 0
Бинарный протокол для аргументов и строки
    #39193045
Weed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WeedЗачем тогда PQsendQueryPrepared принимает paramFormats?

Отвечаю сам себе: это формат данных (текстовый или бинарный). Форматы же аргументов Oid вообще не передаются при запросе на сервер.

Хех, вот так открытие! Очень чуднО.

(Вопрос закрыт.)
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Бинарный протокол для аргументов и строки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]