SQLRU.net
Разработка приложений баз данных

Начало » Использование СУБД » Firebird, HQbird, InterBase » EXECUTE STATEMENT и "маркеры" кодовых страниц
EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2726] Mon, 10 July 2023 13:32 Переход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  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 и "маркеры" кодовых страниц [сообщение #2728 является ответом на сообщение #2726] Mon, 10 July 2023 14:12 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время в онлайне  SD
Сообщений: 417
Зарегистрирован: August 2022
Senior Member
Он её вообще не должен преобразовывать. Ибо это чревато искажением вложенных в неё строк с "маркерами" о чём я уже давно писал в девеле. А способа указать кодировку строки для конкретного запроса в API нет. Так что это "by design и не лечится".
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2729 является ответом на сообщение #2728] Mon, 10 July 2023 14:34 Переход к предыдущему сообщениюПереход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  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 'бла-бла-бла-бла-бла-бла';
...

Тут, наверное, все гораздо интереснее. Попозже посмотрю Smile

UPD1. Поправил пункты 1-2, чтобы было понятнее.

UPD2. И кстати, в третьем диалекте, если кодовая страница подключения NONE, квотированные имена объектов должны быть оттранслированы в UNICODE_FSS или UTF8 (FB4+).

[Обновления: Mon, 10 July 2023 17:51]

Известить модератора

Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2731 является ответом на сообщение #2729] Mon, 10 July 2023 15:55 Переход к предыдущему сообщениюПереход к следующему сообщению
basid в настоящее время не в онлайне  basid
Сообщений: 167
Зарегистрирован: June 2022
Географическое положение: Asia/Irkutsk
Senior Member
Насколько я понимаю, _кодировка'строка' означает, что "байты в строка" представлены в "кодировка".
Т.е. утверждение "должен этот му-му-му оттранслировать из WIN1251 в UTF8" - является несколько спорным.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2732 является ответом на сообщение #2731] Mon, 10 July 2023 16:05 Переход к предыдущему сообщениюПереход к следующему сообщению
МП в настоящее время не в онлайне  МП
Сообщений: 889
Зарегистрирован: August 2022
Географическое положение: бурятский тун...
Senior Member
нет.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2733 является ответом на сообщение #2731] Mon, 10 July 2023 16:46 Переход к предыдущему сообщениюПереход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  Dmitry Kovalenko
Сообщений: 51
Зарегистрирован: December 2022
Member
basid писал(а) Mon, 10 July 2023 15:55

Насколько я понимаю, _кодировка'строка' означает, что "байты в строка" представлены в "кодировка".
Да.

basid писал(а) Mon, 10 July 2023 15:55

Т.е. утверждение "должен этот му-му-му оттранслировать из WIN1251 в UTF8" - является несколько спорным.
Нет.

К серверу приехали текстовые данные в кодовой странице WIN1251. Сервер эти данные хочет интерпретировать как текст запроса. А это уже немного другое.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2734 является ответом на сообщение #2733] Tue, 11 July 2023 00:41 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время в онлайне  SD
Сообщений: 417
Зарегистрирован: 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 в настоящее время не в онлайне  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 и "маркеры" кодовых страниц [сообщение #2739 является ответом на сообщение #2735] Tue, 11 July 2023 15:13 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время в онлайне  SD
Сообщений: 417
Зарегистрирован: August 2022
Senior Member
Не обеспечивает клиент никакую "корректность кодовой страницы". Какие байты приложение после introducer напихало, такие он и должен передавать серверу. А тот уже - просто складывать их в кучку под табличкой "тут лежит <подставить значение introducer>".
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2740 является ответом на сообщение #2739] Tue, 11 July 2023 15:58 Переход к предыдущему сообщениюПереход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  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 и "маркеры" кодовых страниц [сообщение #2742 является ответом на сообщение #2740] Wed, 12 July 2023 00:53 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время в онлайне  SD
Сообщений: 417
Зарегистрирован: August 2022
Senior Member
Юникодные приложения неспособны сформировать строку для использования с интродюсерами. Совсем. То, что в апострофах после интродусера - не символы. Это последовательность байт. По стандарту. Соответствие между этими байтами и указанным интродюсером - на уровне "мамой клянусь", которому сервер и (почти) верит. Зачем и с какого перепою их вообще в стандарт добавили - у меня нет ни малейшей идеи.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2743 является ответом на сообщение #2742] Wed, 12 July 2023 10:48 Переход к предыдущему сообщениюПереход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  Dmitry Kovalenko
Сообщений: 51
Зарегистрирован: December 2022
Member
SD писал(а) Wed, 12 July 2023 00:53
Юникодные приложения неспособны сформировать строку для использования с интродюсерами. Совсем.
Юникодные приложения используют интродюсеры в качестве подсказки, что вот эту часть запроса нужно будет отправить на сервер в такой кодировке.

Это может быть использовано для кодовой страницы подключения NONE, когда нужно конкретно указать кодовую страницу текстовых данных, передаваемых прямо в тексте запроса.

SD писал(а) Wed, 12 July 2023 00:53
То, что в апострофах после интродусера - не символы. Это последовательность байт. По стандарту. Соответствие между этими байтами и указанным интродюсером - на уровне "мамой клянусь", которому сервер и (почти) верит. Зачем и с какого перепою их вообще в стандарт добавили - у меня нет ни малейшей идеи.
Дима, это символы Smile

Хотя бы потому что сервер, когда разбирает запрос, использует имя кодовой страницы, указанной в интродюсере, для преобразования этих символов к целевому виду. Например к кодовой странице колонки получателя.

insert TBL_CS__WIN1251 (COL_BLOB /*Has charset WIN1251*/) VALUES (_utf8 'тут будут UTF8-символы')

И если он не сможет их преобразовать - выкинется ошибка Malformed string.

/index.php/fa/153/0/

Теперь тоже самое с корректной обработкой интродюсера _utf8

/index.php/fa/154/0/

----
Мне кажется, что ты не догнал проблему, которую я описал в самом начале.

У меня с описанием всегда были проблемы Smile

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.

/index.php/fa/156/0/

---
Так понятнее?

UPD1. Мне последний гиф реально нравится. Там показано что клиент нормально отрабатывает свой (первый) интродюсер _utf8, а потом сервер наступает себе на хвост, потому что не отрабатывает второй. Можно в трекер его как есть, без камментов.

[Обновления: Wed, 12 July 2023 14:32]

Известить модератора

Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2744 является ответом на сообщение #2743] Wed, 12 July 2023 14:42 Переход к предыдущему сообщениюПереход к следующему сообщению
SD в настоящее время в онлайне  SD
Сообщений: 417
Зарегистрирован: August 2022
Senior Member
То, что видится некоторыми на экране и то, что творит сервер - совершенно всё равно. По стандарту это байты и они должны соответствовать кодировке, указанной в интродюсере.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2747 является ответом на сообщение #2744] Wed, 12 July 2023 16:12 Переход к предыдущему сообщениюПереход к следующему сообщению
Dmitry Kovalenko в настоящее время не в онлайне  Dmitry Kovalenko
Сообщений: 51
Зарегистрирован: December 2022
Member
SD писал(а) Wed, 12 July 2023 14:42
То, что видится некоторыми на экране и то, что творит сервер - совершенно всё равно. По стандарту это байты и они должны соответствовать кодировке, указанной в интродюсере.
... когда интродюсер является "оператором запроса", выполняемого в текущий момент времени.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2748 является ответом на сообщение #2747] Wed, 12 July 2023 16:46 Переход к предыдущему сообщениюПереход к следующему сообщению
МП в настоящее время не в онлайне  МП
Сообщений: 889
Зарегистрирован: August 2022
Географическое положение: бурятский тун...
Senior Member
Dmitry Kovalenko писал(а) Wed, 12 July 2023 16:12
SD писал(а) Wed, 12 July 2023 14:42
То, что видится некоторыми на экране и то, что творит сервер - совершенно всё равно. По стандарту это байты и они должны соответствовать кодировке, указанной в интродюсере.
... когда интродюсер является "оператором запроса", выполняемого в текущий момент времени.
+500!
но бодаться мне лень.
ибо бесперспективняк.
Re: EXECUTE STATEMENT и "маркеры" кодовых страниц [сообщение #2750 является ответом на сообщение #2748] Wed, 12 July 2023 18:00 Переход к предыдущему сообщению
kdv в настоящее время не в онлайне  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. ссылку на учебник логики не даю.
Предыдущая тема: RDB$ERROR и русский текст в EXECUTE STATEMENT
Следующая тема: [FB4] Таблица без колонок
Переход к форуму:
  


Текущее время: Sun Dec 22 15:49:18 GMT+3 2024

Общее время, затраченное на создание страницы: 0.00926 секунд