Хранимая процедура

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
santilaas
Сообщения: 51
Зарегистрирован: 27 авг 2005, 21:05

Хранимая процедура

Сообщение santilaas » 09 апр 2007, 17:24

Хранимая процедура:
Firebird 1.5.3, FibPlus 5.2
Привет всем!!!
Вопрос такой:
есть хранимая процедура:

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

CREATE PROCEDURE GRANT_ROLE (
    CMD VARCHAR(6),
    ROLENAME VARCHAR(31),
    USR VARCHAR(31))
AS
DECLARE VARIABLE EXESTUB VARCHAR(1024) = '';
begin
   if (rolename = '') then rolename = null;
   if (usr = '') then usr = null;
   if ((rolename is null) or (usr is null)) then exit;
   else
      begin
         if (cmd starting with 'g') then
            exestub = 'grant ';
         else
            exestub = 'revoke ';

         if (exestub = 'grant ') then
            exestub = exestub || rolename || ' to ' || usr;
         else
            exestub = exestub || rolename || ' from ' || usr;
         execute statement exestub;
      end
   end
- как Вы правильно поняли - она назначает или отбирает роль у пользователя.
Сама она работает (в том же IBExpert-е проверял), но проблема в другом:
- на форме есть 2 ДБГрида, связанные с датасетами (DataSetRole - мастер и DataSetUser - деталь) - так вот, при добавлении
пользователя, он у меня должен записаться в БД безопасности и в таблицу моей БД и здесь же должно выполниться назначение
роли (мастера) данному юзеру (детали). вызываю процедуру так (с помощью компонента pFIBStoredProc):

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

DM.StoredProc.SQL.Clear;
//1-ый способ:
//DM.StoredProc.SQL.Add('EXECUTE PROCEDURE GRANT_ROLE(''grant'',''' + DM.DSRoleNAME.AsString + ''', ''' + Edit.Text) + ''')');
//DM.StoredProc.ExecProc; 
//или так:
// 2-ой способ:
DM.StoredProc.ExecProcedure('SPRole',['grant', DM.DSRoleNAME.AsString, Edit.Text)]);
- притом она все правильно срабатывает, но "гасит" (делает неактивными мои датасеты (см. выше)) - почему так происходит - может кто подскажет?
Заранее благодарен!

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

Сообщение kdv » 09 апр 2007, 21:40

как Вы правильно поняли - она назначает или отбирает роль у пользователя.
вернее, включает пользователя в роль или исключает оттуда.
неясно только, зачем это мутить на сервере.

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

притом она все правильно срабатывает, но "гасит" 
такие запросы надо в отдельной транзакции пускать. старт, ддл, коммит.

santilaas
Сообщения: 51
Зарегистрирован: 27 авг 2005, 21:05

Сообщение santilaas » 10 апр 2007, 18:21

неясно только, зачем это мутить на сервере.
- а что в плохого в том, что я из своего приложения могу раздавать права, ВКЛЮЧАТЬ (ИСКЛЮЧАТЬ) пользователя в роль?! Единственное может я это немного коряво делаю - вот поэтому и прошу помощи

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

Сообщение kdv » 10 апр 2007, 23:20

что я из своего приложения
ты не понял. так или иначе это делается из приложения.
другое дело, почему тебе не нравится просто оператор grant, и ты решил городить для этого процедуру с execute statement.
Единственное может я это немного коряво делаю
про ddl в отдельных транзакциях я уже сказал.

santilaas
Сообщения: 51
Зарегистрирован: 27 авг 2005, 21:05

Сообщение santilaas » 11 апр 2007, 18:26

Помимо двух моих транзакций (на чтение из запись) завел еще одну:
попробовал написать так:

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

Tr_StoredProc.Active:=True;
Tr_StoredProc.StartTransaction;
DM.StoredProc.SQL.Clear;
DM.StoredProc.SQL.Add('EXECUTE PROCEDURE GRANT_ROLE('''',''' + DM.DSRoleNAME.AsString + ''', ''' + trim(Edit.Text) + ''')');
   try
      DM.StoredProc.ExecProc;
      if Tr_StoredProc.InTransaction then Tr_StoredProc.CommitRetaining;
   except
      Tr_StoredProc.RollbackRetaining;
   end;
но толку мало,
только после DM.DS_A_Role.FullRefresh; - все встает на свои места

почему я не сделал все это через транзакцию на запись - а потому что в рамках неё выполняются другие изменения БД,
а транзакция (которая для ХП) вызывается внутри этой транзакции - кстати вопрос:
- а если транзакция, скажем Tr_main, запущена и в рамках неё выполняется другая транзакция Tr_child, которая подтверждается как CommitRetaining, - то что будет с этой внутренней транзакцией после Rollback- а транзакции Tr_main ???

и еще вопрос: как мне отследить для моей процедуры - включила она пользователя в роль или нет, - чтобы сделать Rollback при необходимости: мне надо в самой процедуре это писать или как-то сделать это иначе?
почему тебе не нравится просто оператор grant
- почему же не нравится - я бы рад сделать, проще, если бы знал как -
kdv, может, если не трудно подскажешь как это сделать?! через Query или еще как?

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

Сообщение kdv » 12 апр 2007, 02:14

Tr_StoredProc.Active:=True;
сколько раз говорить можно - свойство Active - ДЛЯ ТЫКАНЬЯ МЫШЬЮ В OBJECT INSPECTOR. Только. www.ibase.ru/devinfo/ibx.htm

в результате имеем бред вида

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

Tr_StoredProc.Active:=True;
Tr_StoredProc.StartTransaction;
почему я не сделал все это через транзакцию на запись - а потому что в рамках неё выполняются другие изменения БД,
а транзакция (которая для ХП) вызывается внутри этой транзакции - кстати вопрос:
еще раз повторяю - изменения, выполненные операторами DDL, вступают в действие только по commit. И мешать их в транзации с DML КАТЕГОРИЧЕСКИ НЕЛЬЗЯ.
подтверждается как CommitRetaining
хочешь хреновые приложения - используй CommitRetaining дальше. я не знаю, сколько еще раз можно советовать одно и то же.
то что будет с этой внутренней транзакцией
нет никаких "вложенных" транзакций. В принципе. Транзакции всегда выполняются только "параллельно", т.е. независимо друг от друга, так, как они бы выполнялись из разных приложений с разных компьютеров.
включила она пользователя в роль или нет, - чтобы сделать Rollback при необходимости
не всем операторам ddl можно сделать rollback.
я бы рад сделать, проще, если бы знал как
ну так учись же. что ж ты советы игнорируешь? Если ты и дальше будешь писать так как тебе надо, а не так как тебе советуют, какой мне смысл дальше отвечать на твои вопросы???

santilaas
Сообщения: 51
Зарегистрирован: 27 авг 2005, 21:05

Сообщение santilaas » 15 апр 2007, 19:26

процитирую сам себя:
притом она все правильно срабатывает, но "гасит" (делает неактивными мои датасеты (см. выше)) - почему так происходит - может кто подскажет?
- потому что надо было у StoredProc поставить options-qoAutoCommit в False и указать для неё в качестве транзакции мою транзакцию на запись и тогда не надо было бы писать всю эту чепуху (т.е. мой предыдущий ответ)
почему тебе не нравится просто оператор grant, и ты решил городить для этого процедуру с execute statement.
- здесь я полностью согласен - сделал через Query (options-qoAutoCommit, Transaction = Tr_Write):

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

DM.Query_Grant.Close;
  DM.Query_Grant.SQL.Clear;
  DM.Query_Grant.SQL.Add('Grant ' + DM.DataSetRoleName.AsString + ' to ' + DM.DataSetUsersLOGIN.AsString);
  DM.Query_Grant.ExecQuery;
- тут сразу вопрос- обязательно ли делать Close для Query в данном случае?
в результате имеем бред вида ...
- что я могу сказать - снова согласен
что ж ты советы игнорируешь?
- я исправляюсь по мере своих сил

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 16 апр 2007, 02:01

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

DM.Query_Grant.Close;
  DM.Query_Grant.SQL.Clear;
  DM.Query_Grant.SQL.Add('Grant ' + DM.DataSetRoleName.AsString + ' to ' + DM.DataSetUsersLOGIN.AsString);
  DM.Query_Grant.ExecQuery;
Наборы должны закрываться сразу же после использования (естественно, могут быть исключения). В итоге получается:

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

  DM.Query_Grant.SQL.Clear;
  DM.Query_Grant.SQL.Add('Grant ' + DM.DataSetRoleName.AsString + ' to ' + DM.DataSetUsersLOGIN.AsString);
  DM.Query_Grant.ExecQuery;
  DM.Query_Grant.Close;
Таким образом, твой вопрос сам собой отпадает.

santilaas
Сообщения: 51
Зарегистрирован: 27 авг 2005, 21:05

Сообщение santilaas » 17 апр 2007, 18:01

Все, теперь (по этому вопросу) мне все ясно - спасибо Вам, kdv и CyberMax, огромное

Ответить