Переход с FB 1.5.3 на FB 2.0 (возникновение read-only поля)

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Ответить
cav
Сообщения: 21
Зарегистрирован: 18 май 2006, 13:25

Переход с FB 1.5.3 на FB 2.0 (возникновение read-only поля)

Сообщение cav » 25 янв 2007, 05:21

Возможно сейчас в меня полетять табуретки но всеже:
Решил перевести базу с FB 1.5.3 (ods 10.1) на FB 2 (ods 11). По опыту предидущих апдейтов и переходов, решил что бекапа/рестора будет достаточно. База рестор прошла БЕЗ ошибок. Но при попытке записи (UPDATE) в одну из таблиц стала писаль следующее:

Код: Выделить всё

This column cannot be updated because it is derived from an SQL function or expression.
attempted update of read-only column.
.

Где может быть косяк и как его примерно можно исправить ? Есть подозрение на права
текст таблицы : (пересоздавать не пробовал). FB2 2.0.0.12745

Код: Выделить всё

SET SQL DIALECT 3;

SET NAMES WIN1251;



/******************************************************************************/
/***                                 Tables                                 ***/
/******************************************************************************/



CREATE TABLE S$_DATE_OP (
    MODEID    SMALLINT,
    MODEDATE  DATE
);




/******************************************************************************/
/***                                Triggers                                ***/
/******************************************************************************/


SET TERM ^ ;


/******************************************************************************/
/***                          Triggers for tables                           ***/
/******************************************************************************/



/* Trigger: S$_DATE_OP_AU0 */
CREATE TRIGGER S$_DATE_OP_AU0 FOR S$_DATE_OP
ACTIVE AFTER UPDATE POSITION 0
AS
declare M date;
begin
  /* Trigger text */
  if (new.modeid=2) then begin
   if (new.modedate<old.modedate) then begin
    delete from close_date 
    where cdate=old.modedate;
    m=incdate(old.modedate,0,-1,0);
    m=lastdaymonth(:m);
    update naclhead set naclhead.LOCK_DH='F'
    where naclhead.docdate>:M and naclhead.docdate<=old.modedate;
   end -- if modedate<old.modedate
  end
end
^


/* Trigger: S$_DATE_OP_AU1 */
CREATE TRIGGER S$_DATE_OP_AU1 FOR S$_DATE_OP
ACTIVE AFTER UPDATE POSITION 1
AS
begin
  /* Trigger text */
  if ((new.modedate<>old.modedate) and (old.modeid=2)) then
   insert into modedate_log(old_date,new_date)
   values (old.modedate,new.modedate);
end
^


SET TERM ; ^



/******************************************************************************/
/***                              Descriptions                              ***/
/******************************************************************************/

COMMENT ON TABLE S$_DATE_OP IS 
'Даты проверок и етс.';



/* Fields descriptions */

COMMENT ON COLUMN S$_DATE_OP.MODEID IS 
'1 - проверка остатков
2 - закрытий период (залоченые документы)';



/******************************************************************************/
/***                               Privileges                               ***/
/******************************************************************************/


/* Privileges of triggers */
GRANT UPDATE, REFERENCES ON S$_DATE_OP TO TRIGGER S$_DATE_OP_AU0;
GRANT UPDATE, REFERENCES ON S$_DATE_OP TO TRIGGER S$_DATE_OP_AU1;

/* Privileges of procedures */
GRANT SELECT, INSERT, UPDATE ON S$_DATE_OP TO PROCEDURE CHECK_MINUSOSTATOK;
GRANT SELECT, INSERT, UPDATE ON S$_DATE_OP TO PROCEDURE CLOSE_SOFT_PERIOD;
GRANT SELECT ON S$_DATE_OP TO PROCEDURE GET_AVG_CARD_ONE;
GRANT SELECT ON S$_DATE_OP TO PROCEDURE SET_MVIT_FIFO;
Ругается только на апдейт подя MODEDATE

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 25 янв 2007, 08:05

Есть подозрение на неправильный текст ошибки. firebird.msg должен быть один и соответствовать версии fbclient.dll.

Попробуй также создать эту базу из скрипта (у тебя ведь есть образцовый скрипт, не так ли?). Возможно, там есть кривой SQL, который двойка уже не переваривает. Скажем, присвоение чего-нибудь old.* в триггере.

cav
Сообщения: 21
Зарегистрирован: 18 май 2006, 13:25

Сообщение cav » 25 янв 2007, 08:47

Создал базу из скрипта ругнулся в 2 других местах :(
Ничего не понимаю :(

Код: Выделить всё

/*******************************************************************************
The next statement causes the following error: 

Column does not belong to referenced table.
Dynamic SQL Error.
SQL error code = -206.
Column NACLSPEC.SUMMARUB cannot be repeated in INSERT statement.
At line 29, column 110.
*******************************************************************************/
ALTER PROCEDURE SET_NACLSPEC(PUSERID INTEGER,
PID VARCHAR(20),
PINOUT SMALLINT)
 AS
DECLARE VARIABLE LGUID INTEGER;
DECLARE VARIABLE LQUANTITY DOUBLE PRECISION;
DECLARE VARIABLE LPRICENONDS NUMERIC(15,3);
DECLARE VARIABLE LPRICERUB NUMERIC(15,3);
DECLARE VARIABLE LTAX DOUBLE PRECISION;
DECLARE VARIABLE LMES VARCHAR(30);
DECLARE VARIABLE LMODECARD CHAR(1);
DECLARE VARIABLE LSUMNDS NUMERIC(15,3);
DECLARE VARIABLE LMESSIZE DOUBLE PRECISION;
DECLARE VARIABLE LTOTALRUB NUMERIC(15,3);
DECLARE VARIABLE LQUANTITYALL DOUBLE PRECISION;
DECLARE VARIABLE LBASETOTALRUB NUMERIC(15,3);
DECLARE VARIABLE LNLINE INTEGER;
DECLARE VARIABLE LPROCLOSS NUMERIC(9,3);
begin
  /* Procedure Text */
  delete from naclspec
  where id=:pid and inout=:pinout;
  lnline=1;
  for
   select ns.guid,ns.quantity,ns.pricenonds,ns.pricerub,ns.tax,ns.modecard,ns.mes,ns.sumnds,ns.messize,ns.totalrub,ns.quantityall,ns.basetotalrub,ns.procloss from naclspec_wrk ns
   where userid=:puserid
   into :lguid,:lquantity,:lpricenonds,:lpricerub,:ltax,:lmodecard,:lmes,:lsumnds,:lmessize,:ltotalrub,:LQUANTITYALL,:LBASETOTALRUB,:LPROCLOSS
  do begin
   insert into naclspec (id,inout,guid,quantity,pricerub,summarub,pricenonds,tax,modecard,sumnds,mes,messize,summarub,quantityall,basetotalrub,nline,procloss)
   values (:pid,:pinout,:lguid,:lquantity,:lpricerub,0,:lpricenonds,:ltax,:lmodecard,:lsumnds,:lmes,:lmessize,:ltotalrub,:LQUANTITYALL,:LBASETOTALRUB,:LNLINE,:LPROCLOSS);
   lnline=:lnline+1;
  end

  select sum(ns.totalrub),sum(ns.sumnds) from naclspec_wrk ns
  where userid=:puserid
  into :ltotalrub,:lsumnds;

  if (:ltotalrub is null) then ltotalrub=0;

  update naclhead nh set nh.totalrub=:ltotalrub,moduser=:puserid,nh.sumnds=softround(:lsumnds,2)
  where id=:pid and inout=:pinout;

  exit;
end
;

/*******************************************************************************
The next statement causes the following error: 

This column cannot be updated because it is derived from an SQL function or expression.
attempted update of read-only column.
*******************************************************************************/
CREATE TRIGGER NACLHEAD_AU1 FOR NACLHEAD
ACTIVE AFTER UPDATE POSITION 1 
AS
declare variable UNAME varchar(60);
declare variable UOP varchar(40);
begin
  /* Trigger text */
  select name from users us
  where us.id=new.moduser
  into :uname;

  if (:uname is null) then uname='no user';

  if ((new.clientindex<>old.clientindex) or (new.docdate<>old.docdate) or (new.operation<>old.operation) or (new.client2index<>old.client2index)) then begin
   insert into naclhead_log (flg,id,inout,docdate,clientindex,client2index,operation,username,modedoc,modetime,rectype,totalrub)
   values ('UPD',new.id,new.inout,new.docdate,new.clientindex,new.client2index,new.operation,:uname,current_date,current_time,'Изменен',new.totalrub);
  end

  if (new.totalrub<>old.totalrub) then
   insert into naclhead_log (flg,id,inout,docdate,clientindex,client2index,operation,username,modedoc,modetime,rectype,totalrub)
   values ('UPD',new.id,new.inout,new.docdate,new.clientindex,new.client2index,new.operation,:uname,current_date,current_time,'Изменена спецификация',new.totalrub);

  if (new.used<>old.used) then begin
    if (new.used='T') then
     uop='Оприходован';
    else
     uop='Разоприходован';
   insert into naclhead_log (flg,id,inout,docdate,clientindex,client2index,operation,username,modedoc,modetime,rectype,totalrub)
   values ('UPD',new.id,new.inout,new.docdate,new.clientindex,new.client2index,new.operation,:uname,current_date,current_time,:uop,new.totalrub);

   new.poststatus=2;
  end
end
;

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Re: Переход с FB 1.5.3 на FB 2.0 (возникновение read-only по

Сообщение avenger » 25 янв 2007, 09:03

cav писал(а):Ругается только на апдейт подя MODEDATE
У меня тоже была такая ситуация. Оказалось, что в AFTER Insert/Update/Delete триггерах нельзя изменять поля NEW.### и OLD.###. A в BEFORE Insert/Update/Delete триггерах можно.

Свою ситуацию решил разбитием триггера на два. Один After, другой Before.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 25 янв 2007, 09:04

В первом случае summarub упомянута дважды в insert, это теперь запрещено, о чем и говорится в тексте ошибки.
Во втором - нельзя присваивать new переменным в after триггерах.

cav
Сообщения: 21
Зарегистрирован: 18 май 2006, 13:25

Сообщение cav » 25 янв 2007, 09:42

Спасибо всем ответившим..... Блин вот что значит невнимательно сообщения о ошибках читать и релизнотес :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 25 янв 2007, 09:44

Во втором - нельзя присваивать new переменным в after триггерах.
причем нельзя потому что смысла нет это делать.

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 25 янв 2007, 10:51

kdv писал(а):причем нельзя потому что смысла нет это делать
скорее потому, что это не работает так, как некоторыми ожидается :-)
На что рассчитывает человек с таким вот кодом:
new.poststatus=2;
в after-триггере? Это же очевидный баг у него, статус никогда не установится в 2.

cav
Сообщения: 21
Зарегистрирован: 18 май 2006, 13:25

Сообщение cav » 25 янв 2007, 11:21

kdv писал(а):
причем нельзя потому что смысла нет это делать

скорее потому, что это не работает так, как некоторыми ожидается :-)
На что рассчитывает человек с таким вот кодом:
new.poststatus=2;
в after-триггере? Это же очевидный баг у него, статус никогда не установится в 2.
Самое интересное что эта строчка в FB 1.5 работает :) .

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 25 янв 2007, 11:41

cav писал(а):Самое интересное что эта строчка в FB 1.5 работает
как no-op. Запись не меняется.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 25 янв 2007, 15:38

Самое интересное что эта строчка в FB 1.5 работает
нихрена она не работает.
как вообще в голову может прийти в after-триггере менять столбцы записи - непонятно.

avenger
Сообщения: 141
Зарегистрирован: 25 окт 2005, 11:53

Сообщение avenger » 25 янв 2007, 23:28

kdv писал(а):нихрена она не работает.
как вообще в голову может прийти в after-триггере менять столбцы записи - непонятно.
Значение она не меняет это точно. А вот использовать NEW.* можно было как переменную. Т.е. не надо было создавать промежуточную переменную внутри триггера.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 26 янв 2007, 10:50

avenger писал(а):А вот использовать NEW.* можно было как переменную.
Per Anus Ad Astrum (C).
Сейчас с делами разберусь, надо будет нафотошопить медальку с соответствующей надписью. Для вручения, так сказать.

cav
Сообщения: 21
Зарегистрирован: 18 май 2006, 13:25

Сообщение cav » 26 янв 2007, 11:06

Per Anus Ad Astrum (C).
Сейчас с делами разберусь, надо будет нафотошопить медальку с соответствующей надписью. Для вручения, так сказать.
А можно мне одну :)
KDV

нихрена она не работает.
как вообще в голову может прийти в after-триггере менять столбцы записи - непонятно.
посыпаю голову пеплом.... прогнал сильно.....

Ответить