Страница 1 из 2
execute statement и чарсет подключения
Добавлено: 17 фев 2009, 10:00
mustafa
Server FB2.1.1 win, база WIN1251
----------------------------------------
Код: Выделить всё
create procedure TEST (NAME varchar(10))
returns (ID integer)
as
declare variable LSQL varchar(100);
begin
LSQL =
'select rdb$relation_id from rdb$database where rdb$character_set_name = '''
|| :NAME || '''';
for execute statement :LSQL into :ID
do
suspend;
end
Подключаемся с UTF8, выполняем: select * from TEST('проверка');
получаем ошибку:
SQL error code = -104.
Malformed string.
т.е. execute statement для строки запроса берёт чарсет подключения к базе игнорируя чарсет базы/переменной?
И ещё. встроенные функции bin_and, bin_or, bin_xor позволяют задавать всего один аргумент. что не есть хорошо.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 11:39
hvlad
mustafa писал(а):Server FB2.1.1 win, база WIN1251
----------------------------------------
Код: Выделить всё
create procedure TEST (NAME varchar(10))
returns (ID integer)
as
declare variable LSQL varchar(100);
begin
LSQL =
'select rdb$relation_id from rdb$database where rdb$character_set_name = '''
|| :NAME || '''';
for execute statement :LSQL into :ID
do
suspend;
end
Подключаемся с UTF8, выполняем: select * from TEST('проверка');
получаем ошибку:
SQL error code = -104.
Malformed string.
И запрос, конечно же, тоже формируем в UTF8 ?
mustafa писал(а):т.е. execute statement для строки запроса берёт чарсет подключения к базе игнорируя чарсет базы/переменной?
А то без execute statement этот пример будет себя вести не так ?
mustafa писал(а):И ещё. встроенные функции bin_and, bin_or, bin_xor позволяют задавать всего один аргумент. что не есть хорошо.
Не хорошо писать глупости, не проверив их сначала

Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 12:31
mustafa
hvlad писал(а):И запрос, конечно же, тоже формируем в UTF8 ?
строка(параметр) в fbclient передаётся в UTF-8.
hvlad писал(а):mustafa писал(а):т.е. execute statement для строки запроса берёт чарсет подключения к базе игнорируя чарсет базы/переменной?
А то без execute statement этот пример будет себя вести не так ?
не понял.
на этот же запрос в процедуре, только без execute statement, сервер ошибок не выдаёт.
т.е. если там написать так: select rdb$relation_id from rdb$database where rdb$character_set_name = :NAME into :ID;
hvlad писал(а):mustafa писал(а):И ещё. встроенные функции bin_and, bin_or, bin_xor позволяют задавать всего один аргумент. что не есть хорошо.
Не хорошо писать глупости, не проверив их сначала

проверил прямо сейчас: select bin_and(0) from rdb$database; вернул 0. а надо бы чтоб ругался
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 12:44
mustafa
Вдогонку: если переменную объявить как UTF8(т.е. с чарсетом отличным от чарсета базы), то при подключении с UTF8 всё будет работать, но если подключиться с WIN1251(чарсетом базы), то ругани не будет, но и найти ничего не найдёт, даже если значение(ессно в WIN1251) будет иметься в таблице.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 12:58
MadLizard
mustafa писал(а):строка(параметр) в fbclient передаётся в UTF-8.
Каким образом? А если попробовать "select * from TEST(_win1251 'проверка')"?
mustafa писал(а):проверил прямо сейчас: select bin_and(0) from rdb$database; вернул 0. а надо бы чтоб ругался
На что ругался? Единственное, на что ему следует ругаться, это нечитание документации пользователями
Аргументов у этой функции может быть от одного и до... N. Нет, N - много. До M.
С уважением,
Денис Редозубов.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 13:17
mustafa
MadLizard писал(а):На что ругался? Единственное, на что ему следует ругаться, это нечитание документации пользователями
Аргументов у этой функции может быть от одного и до... N. Нет, N - много. До M.

я о том что по логике должно быть не от 1-го, а от 2-х и до много. это же не унарные типа abs.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 13:27
MadLizard
mustafa писал(а):я о том что по логике должно быть не от 1-го, а от 2-х и до много. это же не унарные типа abs.
Это функции над непустым множеством. А в непустом множестве бывает и всего один элемент.
С уважением,
Денис Редозубов.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 13:48
mustafa
MadLizard писал(а):Это функции над непустым множеством. А в непустом множестве бывает и всего один элемент.
Если б это были агрегатные функции, так и не спрашивал бы (кстати от агрегатных bin_xxx я б не отказался

).
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 14:11
hvlad
mustafa писал(а):hvlad писал(а):И запрос, конечно же, тоже формируем в UTF8 ?
строка(параметр) в fbclient передаётся в UTF-8.
И где в вышепреведенном примере параметр ?
mustafa писал(а):hvlad писал(а):mustafa писал(а):т.е. execute statement для строки запроса берёт чарсет подключения к базе игнорируя чарсет базы/переменной?
А то без execute statement этот пример будет себя вести не так ?
не понял.
Сделай то, что сам же написал выше - станет понятно
mustafa писал(а):hvlad писал(а):mustafa писал(а):И ещё. встроенные функции bin_and, bin_or, bin_xor позволяют задавать всего один аргумент. что не есть хорошо.
Не хорошо писать глупости, не проверив их сначала

проверил прямо сейчас: select bin_and(0) from rdb$database; вернул 0. а надо бы чтоб ругался
Я прочитал так, как написано. А написано, что они позволяют задавать всего один аргумент, т.е. не позволяют задавать больше одного.
Впрочем, не вижу почему возможность задать один аргумент - это плохо
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 18:01
mustafa
hvlad писал(а):И где в вышепреведенном примере параметр ?
запускал и из isql и из IBExpert и из своей проги как есть, а уточнил про параметр т.к. проверил ещё и в своей проге где параметр передавался собственно как параметр.
результат всегда один и тот же.
hvlad писал(а):mustafa писал(а):не понял.
Сделай то, что сам же написал выше - станет понятно

Прости, ну скажи плиз что я должен понять? что второй вариант работает прекрасно? но мне то нужен execute statement.
а сейчас я понимаю, что если мне необходимо использовать execute statement, то я обязан подключаться _только_ с чарсетом базы!
hvlad писал(а):Я прочитал так, как написано. А написано, что они позволяют задавать всего один аргумент, т.е. не позволяют задавать больше одного.
Впрочем, не вижу почему возможность задать один аргумент - это плохо
Эт моё косноязычие - без наводящих вопросов никак.
может и неплохо, только бессмысленно. и при разработке ошибки (были уже как с udf-функций перебрались).
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 18:31
kdv
IBExpert и из своей проги как есть
http://www.ibase.ru/unicode_faq.html
faq не дописан, могут быть косяки. но ibexpert проверен.
Re: execute statement и чарсет подключения
Добавлено: 17 фев 2009, 20:16
mustafa
У меня свой маленький класс-оболочка над api FB.
при подключении с UTF8 транслирую юникод(UTF-16) в UTF-8. ну или в текущую кодовую страницу, если в чарсете указано что-то отличное от "UTF8". соответственно и обратно из UTF-8 в UTF-16 при получении.
и всё прекрасно работает.
кроме процедур, содержащих execute statement.
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 09:03
kdv
ок. тогда
1 почему база в win1251?
2 у процедуры входной параметр какой чарсет имеет?
3 что если явно пересоздать процедуру, указав у всех переменных процедуры (входных и локальных) чарсет юникода?
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 11:24
mustafa
kdv писал(а):1 почему база в win1251?
потому что до того все подключались с WIN1251 и в дальнейшем так будет, но в данный момент в одном из модулей программы я вынужден подключаться по UTF8.
kdv писал(а):2 у процедуры входной параметр какой чарсет имеет?
по умолчанию. т.е. чарсет базы WIN1251.
kdv писал(а):3 что если явно пересоздать процедуру, указав у всех переменных процедуры (входных и локальных) чарсет юникода?
в этом случае при подключении с UTF8 процедура работает.
но, при этом, если подключиться из другого модуля уже с WIN1251, то нет ни ругани "Malformed string", ни результата процедуры.
Чарсет(подключение) | ЧарсетSQL(сделал две переменные для текста запроса в процедуре)
-------------- | ------------
1. WIN1251 | WIN1251 - ok (нет трансляции - чарсет базы и подключения совпадают)
2. WIN1251 | UTF8 - нет результата (нет трансляции - чарсет базы и подключения совпадают)
3. UTF8 | UTF8 - ok (трансляция в чарсет базы)
4. UTF8 | WIN1251 - ошибка "Malformed string" (трансляция в чарсет базы)
т.е. execute statement считает что переданная ему строка запроса всегда в чарсете подключения и в случае несоответствия приводит к чарсету базы.
отсюда и проблема - попытка преобразования WIN1251(якобы из UTF8) в WIN1251 для (4) и отсутствие необходимого преобразования в случае (2).
получается что в процедуре необходимо анализировать с каким чарсетом подключился клиент и приводить к нему текст запроса перед передачей его execute statement.

Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 13:47
kdv
(трансляция в чарсет базы)
просто замечу - нет никакого "чарсета базы", и никогда не было. Это банальный default charset для создаваемых строковых объектов DDL, если у них чарсет не указан. Я понятно выражаюсь?
Поэтому "трансляция" возникает только тогда, когда чарсет объекта или данных НЕ совпадает с чарсетом коннекта (кроме none), и существует таблица трансляции.
Кроме этого - я могу быть неправ, но еще вопрос в том, в каком виде сохраняется строка execute statement. Мне кажется, что у Вас возникает ошибка, когда Вы склеиваете в процедуре строку текста с неизвестным мне чарсетом с куском текста известного чарсета.
Например, строка_в_юникоде + строка_в_win1251.
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 15:04
mustafa
говоря о чарсете базы, я и имел ввиду DEFAULT CHARACTER SET задаваемый при создании базы.
нет у меня никаких других чарсетов кроме дефолтного(т.е. без явного указания) для параметров и переменных процедур/триггеров/udf
и его-же, но явно указанного с коллейтом PXW_CYRL в доменах для полей таблиц.
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 15:19
hvlad
Попробуй что-то вроде
Код: Выделить всё
create procedure TEST (NAME varchar(10))
returns (ID integer)
as
declare variable LSQL varchar(100);
begin
LSQL =
_utf8 'select rdb$relation_id from rdb$database where rdb$character_set_name = '''
|| CAST(:NAME as varchar(10) character set UTF8) || _utf8 '''';
for execute statement :LSQL into :ID
do
suspend;
end
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 15:53
mustafa
тоже самое
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 17:13
hvlad
А вот так ?
Код: Выделить всё
create or alter procedure TEST (NAME varchar(10))
returns (ID integer)
as
declare variable LSQL varchar(100) character set win1251;
begin
LSQL = 'select id from t_test where name = _win1251''' ||
CAST (:NAME as varchar(32) character set WIN1251) || '''';
for execute statement :LSQL into :ID
do
suspend;
end
Re: execute statement и чарсет подключения
Добавлено: 18 фев 2009, 20:43
mustafa
дело-то не в смешении чарсетов.
вообще убрал входной параметр:
Код: Выделить всё
create procedure TEST
returns (ID integer)
as
declare variable LSQL varchar(500);
begin
LSQL = 'select rdb$relation_id from rdb$database where rdb$character_set_name = ''проверка''';
for execute statement :LSQL into :ID
do
suspend;
end
и даже вообще без переменной:
Код: Выделить всё
create procedure TEST
returns (ID integer)
as
begin
for execute statement 'select rdb$relation_id from rdb$database where rdb$character_set_name = ''проверка''' into :ID
do
suspend;
end
результат тот же самый.
