Начало » Использование СУБД » 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
						 Сообщений: 452 Зарегистрирован: 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
						 Сообщений: 105 Зарегистрирован: June 2022 
						
					 | 
					Senior Member  | 
					 | 
		 
		 
	 | 
 
	
		я сюда в исходное сообщение не заглядывал, но КМК исходный посыл бредовый. 
Вот это вот 
EXECUTE STATEMENT _utf8 'execute block as begin EXCEPTION EXC$CHECK_DATA _win1251 ''куку''; end' 
почему нет конкатенации || между куку и прочим, и почему куку не передается параметром? 
Тут же написано 
execute statement _utf8, потом строка В ЭТОМ САМОМ UTF8, и внезапно почему-то куку в UTF8 должно кем-то преобразовываться в win1251??? 
по идее, аналогичные мысли уже были написаны комментаторами выше. 
 
p.s. ссылку на учебник логики не даю.
		
		
		
 |  
	| 
		
	 | 
 
 
 |   
Переход к форуму:
 
 Текущее время: Tue Nov 04 18:17:07 GMT+3 2025 
 Общее время, затраченное на создание страницы: 0.00937 секунд 
 |