Я экспортировал базу данных из Informix 11.50 и хочу импортировать ее в Informix 14.10.
dbexport -ss -c -q iscala
Экспортированный сценарий SQL начинается со следующего:
{ DATABASE iscala delimiter | }
EXECUTE PROCEDURE ifx_allow_newline ('t');
grant dba to "informix";
grant dba to "waspop";
grant connect to "jzl";
create distinct type 'informix'.vestnik as decimal(4,0);
grant usage on type 'informix'.vestnik to 'public' as 'informix';
drop cast (decimal(4,0) as vestnik);
create explicit cast (decimal(4,0) as vestnik with 'informix'.date_vestnik);
CREATE FUNCTION "informix".date_vestnik(vestnik DATE) RETURNING vestnik WITH(NOT VARIANT);
RETURN ((CASE WHEN MONTH(vestnik)=12 AND DAY(vestnik)>12 THEN DAY(vestnik) ELSE MONTH(vestnik) END)
*100+MOD(YEAR(vestnik),100))::NUMERIC(4,0)::vestnik;
END FUNCTION;
create explicit cast (vestnik as integer with 'informix'.vestnik_int);
CREATE FUNCTION "informix".vestnik_int(vestnik vestnik) RETURNING INT WITH(NOT VARIANT);
RETURN vestnik::NUMERIC(4,0)::INT;
END FUNCTION;
create explicit cast (integer as vestnik with 'informix'.int_vestnik);
CREATE FUNCTION "informix".int_vestnik(vestnik INT) RETURNING vestnik WITH(NOT VARIANT);
RETURN vestnik::NUMERIC(4,0)::vestnik;
END FUNCTION;
create explicit cast (vestnik as decimal(4,0) with 'informix'.vestnik_date);
CREATE FUNCTION "informix".vestnik_date(vestnik vestnik) RETURNING DATE WITH(NOT VARIANT);
DEFINE y, m, d INT;
LET y = MOD(vestnik::NUMERIC(4,0),100);
LET m = TRUNC(vestnik::NUMERIC(4,0)/100);
LET d = 1;
IF m<1 THEN RETURN NULL;
ELIF m>20 THEN RETURN NULL;
ELIF m>12 THEN LET m,d = 12,m;
END IF
IF y<0 THEN RETURN NULL;
ELIF y<50 THEN LET y = 2000+y;
ELSE LET y = 1900+y;
END IF
RETURN MDY(m,d,y);
END FUNCTION;
{ TABLE "informix".pbcattbl row size = 369 number of columns = 25 index size = 31 }
{ unload file name = pbcat00100.unl number of rows = 0 }
...
...
Когда я запускаю импорт с помощью этого сценария SQL, я получаю следующую ошибку
[informix@srvbib ~]$ dbimport -c -d datadbs -i /home/informix/ iscala
{ DATABASE iscala delimiter | }
grant dba to "informix";
grant dba to "waspop";
grant connect to "jzl";
create distinct type 'informix'.vestnik as decimal(4,0);
grant usage on type 'informix'.vestnik to 'public' as 'informix';
drop cast (decimal(4,0) as vestnik);
create explicit cast (decimal(4,0) as vestnik with 'informix'.date_vestnik);
CREATE FUNCTION "informix".date_vestnik(vestnik DATE) RETURNING vestnik WITH(NOT VARIANT);
RETURN ((CASE WHEN MONTH(vestnik)=12 AND DAY(vestnik)>12 THEN DAY(vestnik) ELSE MONTH(vestnik) END)
*100+MOD(YEAR(vestnik),100))::NUMERIC(4,0)::vestnik;
END FUNCTION;
create explicit cast (vestnik as integer with 'informix'.vestnik_int);
CREATE FUNCTION "informix".vestnik_int(vestnik vestnik) RETURNING INT WITH(NOT VARIANT);
RETURN vestnik::NUMERIC(4,0)::INT;
END FUNCTION;
create explicit cast (integer as vestnik with 'informix'.int_vestnik);
CREATE FUNCTION "informix".int_vestnik(vestnik INT) RETURNING vestnik WITH(NOT VARIANT);
RETURN vestnik::NUMERIC(4,0)::vestnik;
END FUNCTION;
create explicit cast (vestnik as decimal(4,0) with 'informix'.vestnik_date);
*** prepare sqlobj
201 - A syntax error has occurred.
*** execute sqlobj
201 - A syntax error has occurred.
Когда я удаляю процедуру, она работает нормально. Если я попытаюсь создать функцию с помощью dbaccess
, я смогу создать ее без проблем.
Вы знаете или не могли бы вы дать совет или подсказку о том, как решить эту проблему? Спасибо.
Хм… похоже, это ошибка. Сообщение об ошибке вводит в заблуждение — оператор, который не может быть подготовлен, является оператором DROP CAST, который создает DB-Import. В тексте оператора отсутствует закрывающая скобка, потому что он не ожидает DECIMAL(4, 0)
— он думает, что закрывающая скобка в имени этого типа означает, что его не нужно добавлять, тогда как на самом деле его нужно добавить. Некоторый ленивый синтаксический анализ должен стать неленивым. Вам нужно будет связаться с вашим каналом технической поддержки Informix.
Я создал ошибку CQ idsdb00111253. Вы можете использовать это в разговорах со своей службой поддержки.
Привет, @JonathanLeffler. Спасибо за расследование. Что касается вашего наблюдения, я ожидаю, что если я удалю drop case
, ошибка исчезнет, но ошибка все еще существует, даже если drop cast
был удален. Не могли бы вы поделиться со мной, как вы отлаживаете это поведение? Спасибо.
По причинам, которые мне не вполне ясны, DB-Import берет оператор CREATE EXPLICIT CAST и создает из него оператор DROP CAST, но делает при этом ошибку. В какой-то момент я проверю, является ли это новым дефектом, но я чувствую, что он будет присутствовать и в более старых версиях. Вы можете отладить это, установив переменную среды SQLIDEBUG при запуске DB-Import, а затем используя sqliprint
, чтобы показать, какие сообщения отправляются на сервер и с сервера.
Что касается обходных путей, самым простым было бы удалить оскорбительные операторы CREATE CAST из файла импорта (iscala.exp/iscala.sql
) и завершить импорт без них. Затем используйте DB-Access для выполнения пропущенных операторов. Это, несомненно, неприятно, но должно позволить вам завершить импорт.
Converting comments into an answer.
Это похоже на ошибку. Вам нужно будет связаться с вашим каналом технической поддержки Informix. Я создал ошибку CQ idsdb00111253. Вы можете использовать это в разговорах со своей службой поддержки.
Сообщение об ошибке не очень полезно — оператор, который не может быть подготовлен, является оператором DROP CAST
, который DB-Import создает после анализа CREATE CAST
. В тексте сгенерированного оператора отсутствует закрывающая скобка, потому что он не ожидает DECIMAL(4, 0)
— он думает, что закрывающая скобка в имени этого типа означает, что ему не нужно добавлять ее, тогда как на самом деле ее нужно добавить. Некоторый ленивый синтаксический анализ должен стать менее ленивым.
Согласно синтаксическим диаграммам существует два варианта оператора CREATE CAST:
CREATE [{ IMPLICIT | EXPLICIT }] CAST (<type1> AS <type2>)
CREATE [{ IMPLICIT | EXPLICIT }] CAST (<type1> AS <type2> WITH <function>)
Проблема возникает из-за того, что ваш <type2>
— это DECIMAL(4,0)
, а код обнаруживает скобку )
и предполагает (ошибочно), что )
относится к первому варианту, а не ко второму:
create explicit cast (vestnik as decimal(4,0) with 'informix'.vestnik_date);
Спасибо за ваше расследование. Что касается вашего наблюдения, я ожидаю, что если я уберу футляр, ошибка исчезнет, но ошибка все еще существует, даже если бросок был удален. Не могли бы вы поделиться со мной, как вы отлаживаете это поведение?
По причинам, которые мне не вполне ясны, DB-Import берет оператор CREATE EXPLICIT CAST и создает из него оператор DROP CAST, но делает при этом ошибку. В какой-то момент я проверю, является ли это новым дефектом, но я чувствую, что он будет присутствовать и в более старых версиях.
Вы можете отладить это, установив переменную среды SQLIDEBUG
при запуске DB-Import, а затем используя sqliprint
, чтобы показать, какие сообщения отправляются на сервер и с сервера. Я могу найти ссылки на SQLIDEBUG
только в контексте JDBC, но они более общие.
export SQLIDEBUG=2:${TMPDIR:-/tmp}/sqdbg
Когда вы подключаетесь к серверу с этим набором, клиентский код создаст файл, например /tmp/sqdbg_a3715
. Затем вы можете запустить sqliprint /tmp/sqdbg_a3715
.
Что касается обходных путей, самым простым было бы удалить оскорбительные операторы CREATE CAST из файла импорта (iscala.exp/iscala.sql
) и завершить импорт без них. Затем используйте DB-Access для выполнения пропущенных операторов. Это, несомненно, неприятно, но должно позволить вам завершить импорт.
Правильно ли я понимаю, что вы имеете в виду «когда я запускаю импорт», а не «когда я запускаю экспорт»? Какую именно команду (импорта) вы выполняете?