|
|
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
В prepared выражение: SELECT $1::text отправляю в бинарном формате(!) аргумент типа Int8 (число 123) - в ответ приходит не обычная ошибка типа "неверный формат двоичных данных в параметре Вind 1", а такая: ОШИБКА: неверная последовательность байт для кодировки \"UTF8\": 0x00\n Примерно понятно откуда Постгрес берёт этот нулевой байт (в сетевом порядке байтов число 123 начинается с него), но непонятно почему он не проверяет сначала тип аргумента. Эдак ведь можно "удачно" заслать число, которое будет воспринято как корректная строка со всеми вытекающими. Это баг или фича? Для других типов такой проблемы не замечено. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:23 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Weed, пример передаваемых данных в студию (bind command и особенно "The result-column format codes. Each must presently be zero (text) or one (binary)." её часть). Скорее всего, вы передаёте-таки в текстовом режиме. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:27 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Vladimir SitnikovWeed, пример передаваемых данных в студию (bind command Что такое bind command? и особенно "The result-column format codes. Each must presently be zero (text) or one (binary)." её часть). Скорее всего, вы передаёте-таки в текстовом режиме. Если бы это было так то замена ::text в приведённом выше примере на какой-нибудь ::int4 давала бы аналогичный результат, однако сервер начинает отвечать уже про несоответствие типов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:32 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Weed, WeedЧто такое bind command? http://www.postgresql.org/docs/9.5/static/protocol-message-formats.html -> "Bind command" Weedотправляю в бинарном формате(!) Откуда уверенность, что формат именно бинарный? Где код, которым производится отправка? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:36 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
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. Weedотправляю в бинарном формате(!) Откуда уверенность, что формат именно бинарный? Где код, которым производится отправка?[/quot] https://github.com/denizzzka/dpq2 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:44 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Код: plaintext Вот тут как раз крыжики это, видимо, нули, а скобка в конце это 0x7b == 123 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 20:54 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
WeedЭто вот не оно? Делается через вызов libpq trace Да, похоже на то. Возможно, стоит wireshark'ом посмотреть какие конкретно байты ходят. Или в самом libpq как-то больше логов включать. С D-драйвером можно только пожелать "счастливой отладки". Непростое это занятие делать клиенты к базам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 21:44 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Одно могу сказать: запрос SELECT $1::text с int8 параметром в binary режиме точно работает. Проверял на pgjdbc. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.03.2016, 21:46 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Wireshark показывает то же самое: (Возможно, хитрость в том, что я для prepare не передаю типы параметров и их количество. Но документация это разрешает, да и для других типов правильная ошибка выводится.) Vladimir SitnikovОдно могу сказать: запрос SELECT $1::text с int8 параметром в binary режиме точно работает. Проверял на pgjdbc. Давно? Могли же и сломать... Моя версия постгреса из Debian 9.5.1-1 (64 битная) А что подразумевается под "работает"? (Работать не должно ведь - ошибка типов должна быть показана) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2016, 03:28 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
Weed Возможно, хитрость в том, что я для prepare не передаю типы параметров и их количество Так делать точно не стоит. Текущая версия PostgreSQL не умеет приводить типы параметров. Ваша проблема в том, что при parse не указан тип $1 и PG решает, что это должен быть varchar. Дальше выполняете bind/exec, передавая int8, и, разумеется, оно падает, т.к. PG ожидает varchar. Выход только один -- при parse передавать типы параметров. Ещё один случай когда нужны типы при parse -- это когда есть функции/процедуры с одинаковым названием, но разными типами. Для того, чтобы база поняла какую функцию вызывать, нужен тип на этапе parse. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2016, 09:04 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
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. не отправляет типы передаваемых данных, хотя и принимает их. Для аргумента она отправляет только длину и сами данные. И поэтому с другими типами всё хорошо у меня - они отличаются по размерам и постгрес это сразу может увидеть. А типы переменной длины типа текста пытаются принимать значения любой длины, в том числе и 8-байтные. Отсюда и такая ошибка. Зачем тогда PQsendQueryPrepared принимает paramFormats? Очень загадочная багофича! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2016, 11:00 |
|
||
|
Бинарный протокол для аргументов и строки
|
|||
|---|---|---|---|
|
#18+
WeedЗачем тогда PQsendQueryPrepared принимает paramFormats? Отвечаю сам себе: это формат данных (текстовый или бинарный). Форматы же аргументов Oid вообще не передаются при запросе на сервер. Хех, вот так открытие! Очень чуднО. (Вопрос закрыт.) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2016, 11:05 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=39192727&tid=1997352]: |
0ms |
get settings: |
7ms |
get forum list: |
20ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
165ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
64ms |
get tp. blocked users: |
2ms |
| others: | 201ms |
| total: | 483ms |

| 0 / 0 |
