Начало » Использование СУБД » Firebird, HQbird, InterBase » EXECUTE STATEMENT и "маркеры" кодовых страниц
EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2726] |
Mon, 10 July 2023 13:32 |
Dmitry Kovalenko
Сообщений: 51 Зарегистрирован: December 2022
|
Member |
|
|
По следам вот этого топика провел такой смелый эксперимент с EXECUTE STATEMENT
Походу эта штука не рюхает указание кодовых страниц перед текстом.
---
Юзается исключение:
CREATE EXCEPTION EXC$CHECK_DATA '---------';
--- Тесты
Кодовая страница подключение NONE.
(1) запрос из приложения:
execute block as begin EXECUTE STATEMENT _utf8 'execute block as begin EXCEPTION EXC$CHECK_DATA _win1251 ''куку''; end'; end
На сервер будет передана запрос
execute block as begin EXECUTE STATEMENT _utf8 'execute block as begin EXCEPTION EXC$CHECK_DATA _win1251 ''РєСѓРєСѓ''; end'; end
Возвращается ошибка
Цитата:exception 4
EXC$CHECK_DATA
РєСѓРєСѓ
At block line: 1, col: 24"
То есть сервер не приводит ''РєСѓРєСѓ'' к кодовой странице win1251.
Но интерпретирует её как WIN1251, потом приводит к UTF8 и возвращает вот это страшное РєСѓРєСѓ.
С помощью Notepad++ и двух преобразований из РєСѓРєСѓ получается исходное куку.
2) Запрос из приложения
execute block as begin EXECUTE STATEMENT _win1251 'execute block as begin EXCEPTION EXC$CHECK_DATA _utf8 ''куку''; end'; end
На сервер он будет передан как есть.
И сервер выдаст ошибку
Цитата:Dynamic SQL Error
SQL error code = -104
Malformed string
At block line: 1, col: 24
Потому что русское "куку" не является UTF8-строкой.
3) Запрос из приложения
execute block as begin EXECUTE STATEMENT 'execute block as begin EXCEPTION EXC$CHECK_DATA _utf8 ''РєСѓРєСѓ''; end'; end
Он будет передан на сервер без преобразований
Сервер вернет ошибку
Цитата:EXC$CHECK_DATA.
РєСѓРєСѓ.
At block line: 1, col: 24.
Тут сервер возвращает _utf8 ''РєСѓРєСѓ'' как есть.
---
Вообщем суть в том, что EXECUTE STATEMENT выступая в роли клиента по отношению к серверу, должен более умно преобразовывать переданную ему строку.
Да?
|
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2729 является ответом на сообщение #2728] |
Mon, 10 July 2023 14:34 |
Dmitry Kovalenko
Сообщений: 51 Зарегистрирован: December 2022
|
Member |
|
|
SD писал(а) Mon, 10 July 2023 14:12Он её вообще не должен преобразовывать. Ибо это чревато искажением вложенных в неё строк с "маркерами" о чём я уже давно писал в девеле. А способа указать кодировку строки для конкретного запроса в API нет. Так что это "by design и не лечится".
Если смотреть со стороны клиента.
1. Есть UNICODE-строка с запросом, в которой присутствует _win1251 'бла-бла-бла-бла-бла-бла'.
2. Клиент конвертирует текст запроса в кодовую страницу подключения, но вот это бла-бла-бла-бла-бла-бла должно быть оттранслировано в win1251. Если не может оттранслировать - выкидывается ошибка. Полученная "смешанная" строка передается на сервер.
3. Сервер начинает интерпретировать бла-бла-бла-бла-бла-бла как запрос.
4. Если в бла-бла-бла-бла-бла-бла встречается строка _utf8 'му-му-му', то сервер должен этот му-му-му оттранслировать из WIN1251 в UTF8.
----
Если смотреть со стороны хранимой процедуры.
CREATE SP MY_SP
...
VAR=_win1251 'бла-бла-бла-бла-бла-бла';
...
Тут, наверное, все гораздо интереснее. Попозже посмотрю
UPD1. Поправил пункты 1-2, чтобы было понятнее.
UPD2. И кстати, в третьем диалекте, если кодовая страница подключения NONE, квотированные имена объектов должны быть оттранслированы в UNICODE_FSS или UTF8 (FB4+).
[Обновления: Mon, 10 July 2023 17:51] Известить модератора
|
|
|
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2734 является ответом на сообщение #2733] |
Tue, 11 July 2023 00:41 |
SD
Сообщений: 411 Зарегистрирован: August 2022
|
Senior Member |
|
|
По стандарту (тому самому, ANSI) строка с charset introducer это проста пачка байт. Так что максимум, что с ней можно сделать, это преобразовать в нужную кодировку из указанной в префиксе (префикс при этом, естественно, отваливается). Если префикс _utf8, то эти текстовые данные - в utf8, никакого WIN1251.
[Обновления: Tue, 11 July 2023 00:42] Известить модератора
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2735 является ответом на сообщение #2734] |
Tue, 11 July 2023 09:32 |
Dmitry Kovalenko
Сообщений: 51 Зарегистрирован: December 2022
|
Member |
|
|
SD писал(а) Tue, 11 July 2023 00:41По стандарту (тому самому, ANSI) строка с charset introducer это проста пачка байт. Так что максимум, что с ней можно сделать, это преобразовать в нужную кодировку из указанной в префиксе (префикс при этом, естественно, отваливается). Если префикс _utf8, то эти текстовые данные - в utf8, никакого WIN1251.
Ты путаешь роли клиента и сервера / текст с данными и текст с запросом.
Строку с charset introducer формирует вызывающая сторона (клиент).
" ..... _codepage '<текст в кодировке codepage>' .... ".
Что это за <текст ...>, клиент разбирать не обязан (да это и ненужно/невозможно). Он обеспечивает только корректность его кодовой страницы.
Сервер получает эту строку и внезапно решает, что <текст> это запрос.
Теперь сервер выступает в роли клиента (вызывающей стороны) и должен обработать в <текст> внутренние "charset introducer-ы", чтобы следующий по цепочке сервер смог корректно обработать этот запрос.
И так далее.
А если сервер решает, что <текст в кодировке codepage> это просто данные, то ничего он там разбирать не будет.
---
Ну можно еще рассматривать запрос как контейнер данных, в который находятся другие контейнеры.
[Обновления: Tue, 11 July 2023 10:41] Известить модератора
|
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2740 является ответом на сообщение #2739] |
Tue, 11 July 2023 15:58 |
Dmitry Kovalenko
Сообщений: 51 Зарегистрирован: December 2022
|
Member |
|
|
SD писал(а) Tue, 11 July 2023 15:13Не обеспечивает клиент никакую "корректность кодовой страницы". Какие байты приложение после introducer напихало, такие он и должен передавать серверу. А тот уже - просто складывать их в кучку под табличкой "тут лежит <подставить значение introducer>".
Про какие байты ты говоришь в юникодном приложении?
Когда сервер обрабатывает текст запроса EXECUTE STATEMENT он сам становится клиентом.
UPD. Там нет "байтов". Там есть символы, кодовая страница которых указана в introducer. Хотя если бы можно было указать _octets '<....>', то там были бы байты. Но, если я все правильно понимаю, кодовую страницу OCTETS в качестве introducer указывать нельзя.
[Обновления: Tue, 11 July 2023 16:20] Известить модератора
|
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2743 является ответом на сообщение #2742] |
Wed, 12 July 2023 10:48 |
Dmitry Kovalenko
Сообщений: 51 Зарегистрирован: December 2022
|
Member |
|
|
SD писал(а) Wed, 12 July 2023 00:53Юникодные приложения неспособны сформировать строку для использования с интродюсерами. Совсем.
Юникодные приложения используют интродюсеры в качестве подсказки, что вот эту часть запроса нужно будет отправить на сервер в такой кодировке.
Это может быть использовано для кодовой страницы подключения NONE, когда нужно конкретно указать кодовую страницу текстовых данных, передаваемых прямо в тексте запроса.
SD писал(а) Wed, 12 July 2023 00:53 То, что в апострофах после интродусера - не символы. Это последовательность байт. По стандарту. Соответствие между этими байтами и указанным интродюсером - на уровне "мамой клянусь", которому сервер и (почти) верит. Зачем и с какого перепою их вообще в стандарт добавили - у меня нет ни малейшей идеи.
Дима, это символы
Хотя бы потому что сервер, когда разбирает запрос, использует имя кодовой страницы, указанной в интродюсере, для преобразования этих символов к целевому виду. Например к кодовой странице колонки получателя.
insert TBL_CS__WIN1251 (COL_BLOB /*Has charset WIN1251*/) VALUES (_utf8 'тут будут UTF8-символы')
И если он не сможет их преобразовать - выкинется ошибка Malformed string.
Теперь тоже самое с корректной обработкой интродюсера _utf8
----
Мне кажется, что ты не догнал проблему, которую я описал в самом начале.
У меня с описанием всегда были проблемы
1. Если я сохраняю текст
insert TBL_CS__WIN1251 (COL_BLOB) VALUES (_utf8 'тут будут UTF8-символы')
в колонке таблицы, то все символы этого текста будут принадлежать кодовой странице этой колонки. В данном случае - win1251.
2. Если я передаю этот текст в качестве запроса, то последовательность символов тут будут UTF8-символы должна принадлежать кодовой странице UTF8, как это указано в интродюсере _utf8.
---
Теперь давай таки сохраним этот текст 'insert ... (_utf8 'тут будут UTF8-символы')'. Смотрим пункт первый. Весь текст в блобе представлен в кодовой странице WIN1251.
Потом внутри EXECUTE BLOCK (то есть на сервере) прочитаем этот текст и выполним через EXECUTE STATEMENT.
И что мы видим? Malformed string!
По шагам.
- Сервер загружает текст из win1251-блоба.
- Потом пытается использовать этот текст в качестве запроса без предварительной обработки интродюсеров.
- Нарывается на Malformed string, как на первой картинке с IBE.
---
Так понятнее?
UPD1. Мне последний гиф реально нравится. Там показано что клиент нормально отрабатывает свой (первый) интродюсер _utf8, а потом сервер наступает себе на хвост, потому что не отрабатывает второй. Можно в трекер его как есть, без камментов.
[Обновления: Wed, 12 July 2023 14:32] Известить модератора
|
|
|
|
|
|
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2750 является ответом на сообщение #2748] |
Wed, 12 July 2023 18:00 |
kdv
Сообщений: 98 Зарегистрирован: June 2022
|
Member |
|
|
я сюда в исходное сообщение не заглядывал, но КМК исходный посыл бредовый.
Вот это вот
EXECUTE STATEMENT _utf8 'execute block as begin EXCEPTION EXC$CHECK_DATA _win1251 ''куку''; end'
почему нет конкатенации || между куку и прочим, и почему куку не передается параметром?
Тут же написано
execute statement _utf8, потом строка В ЭТОМ САМОМ UTF8, и внезапно почему-то куку в UTF8 должно кем-то преобразовываться в win1251???
по идее, аналогичные мысли уже были написаны комментаторами выше.
p.s. ссылку на учебник логики не даю.
|
|
|
Переход к форуму:
Текущее время: Sun Nov 24 02:13:46 GMT+3 2024
Общее время, затраченное на создание страницы: 0.01453 секунд
|