Страница 1 из 1

Триггер

Добавлено: 18 июн 2009, 13:54
Ruh
Я решила поработать с триггерами взяла стандартный пример из хэлпа. Заменила только имя таблицы. Причем триггер должен обращаться к Vip интерфейсу. Все компилится без ошибок, но когда запускаю, галактика вылетает, и причем вставляет в указанную таблицу кучу записей, только с одним заполненным полем waywps.num_work, если же я не ставлю функцию ClearBuffer(#waywps), то запись вставляет, но поле waywps.num_work остается нулевым, хотя сообщения выдаются. Помогите, пожалуйста, с этим разобраться.


//объявление объектного интерфейса
objInterface objTrig;
function DoInsert(cRec : comp) : word;
end;
//объявление Vip-интерфейса
#include ObjTrig.vih
vipInterface vipTrig implements objTrig;

//===================
//реализация Vip-интерфейса
interface vipTrig;

//логическая таблица для связанной таблицы
create view as select * from waywps;

function DoInsert(cRec : comp) : word;
{
ClearBuffer(#waywps);
waywps.num_work := 9999;
message('вошла');
result := insert current waywps;
}

//------------------------------------------------------
HandleEvent
cmOnVipUnload: message('dddd');
end;
end.
//===========================================
var GlobVipTrig : vipTrig new;

handler with replace Trig_After on trigger waywps after insert
action
{
var buf : record as table waywps;
GetTableBuffer(buf); // считываем старый буфер
GlobVipTrig.doInsert(buf.NRec);
result := true;
}
Версия Atlantis 5.4.14, галактика 8.01.

Добавлено: 18 июн 2009, 14:15
edward_K
ну кто же в after insert делает вставку в туже таблу - вы просто циклите весь процесс пока переполнение стека не произошло.
если надо чего то изменить перед вставкой то уж лучше before и SetTableBuffer а не insert.

Добавлено: 18 июн 2009, 14:16
edward_K
да и replace тоже не есть хорошо - разработчик тоже могет сие использовать.

Добавлено: 18 июн 2009, 14:42
Ruh
Почему же когда я не чищу буфер она не циклит, вставляет запись, но поле не меняет?
Также если делать update current она вставляет, но поле это не обновляет!
И тогда получается , что в хелпе по vip, допущена ошибка в примере!!!

Добавлено: 18 июн 2009, 14:51
edward_K
без ClearBuffer у вас просто ощибка по уникальному ключу.
а что табла везде была одинаковая в примере? Почитайте хелп к SetTableBuffer - мож поймете в чем фишка. Где то в доке было написано что именно так делать, как вы, нельзя.

Добавлено: 18 июн 2009, 14:55
Ruh
вот пример:
Пример 2.

Данный триггер вызывается при добавлении записи в таблицу HozOper. В триггере производится изменение текущей записи таблицы HozOper и добавление новой записи в таблицу HozForm.

//======================================================
//объявление объектного интерфейса
objInterface objTrig;
function DoInsert(cRec : comp) : word;
end;
//объявление Vip-интерфейса
vipInterface vipTrig implements objTrig;
//======================================================
//реализация Vip-интерфейса
interface vipTrig;
//------------------------------------------------------
//логическая таблица для связанной таблицы
create view as select * from HozForm;

//------------------------------------------------------
//функция добавления записи в связанную таблицу
function DoInsert(cRec : comp) : word;
{
ClearBuffer(#HozForm);
HozForm.cNRec := cRec; // связка с родительской таблицей (HozOper)
HozForm.Formula := 'Новая формула';
result := insert current HozForm;
}
//------------------------------------------------------
handleEvent
cmOnVipUnload: message('dddd');
end;
end.
//======================================================
// Для модификации текущей записи лучше сделать trigger before insert.
// Он выполняется перед добавлением записи в таблицу HozOper.
// Установка значений выполняется с использованием GetTableBufferP и SetTableBuffer.
handler with replace Trig_Before on trigger HozOper before insert
action
{
//переменная буфера с позицией
var buf : record as table HozOper with x$position;
GetTableBufferP(buf); // Считываем буфер
buf.Name2 := 'Новое значение'; // Изменяем значение поля
SetTableBuffer(buf); // Сохраняем буфер
result := true;
}
//======================================================
// Для вставки новых записей лучше сделать trigger after insert.
// Триггер выполняется после добавления записи в родительскую таблицу(HozOper).
// К моменту вызова триггера HozOper.NRec уже определен.
// Переменную объекта лучше сделать на уровне приложения, чтобы
// при каждом срабатывании триггера объект каждый раз не создавался.
// При первом обращении к VIP-объекту произойдет автоматическая
// инициализация. Освобождение произойдет при выходе из приложения
var GlobVipTrig : vipTrig new;
handler with replace Trig_After on trigger HozOper after insert
action
{
var buf : record as table HozOper;
GetTableBuffer(buf); // считываем старый буфер
GlobVipTrig.doInsert(buf.NRec); // добавляем запись в таблицу НozForm
result := true;
}

а к SetTableBuffer- написано что, если меняю ключевое, а поле которое я хочу изменить не являеться ключевым!

Добавлено: 18 июн 2009, 14:56
Ruh
А что за ошибка по уникальному ключу? Ошибок не каких не выдает.Или я что-то не правильно поняла?

Добавлено: 18 июн 2009, 17:01
edward_K
таблы таки разнык 8) Hozoper не Hozform

Добавлено: 18 июн 2009, 22:41
Ruh
:-? Ой, сама не заметила! Большое спасибо! Буду внимательнее.Я же в первый раз :oops:

Добавлено: 19 июн 2009, 00:19
Ged
Я же в первый раз
Радует фраза конечно :) Не в обиду, но .. это Вы маме это скажите.
На счет рекурсии - есть функ. RecursionLevel , с помощью которой можно отследить вложенность. Например в случае необходимости создания подчиненных записей в таблице при создании родительской записи. В принципе на что вы и напоролись.

Добавлено: 06 июл 2009, 18:32
savov
Вопрос к уважаемой Ruh. Какой у вас сервер и где брали мануал по триггерам?

Добавлено: 24 июл 2009, 13:18
Ruh
платформа btrive, мануал по триггерам в мануале по описанию языка Vip :smile: