Откатить изменения

Назначение
 

Команда RBAC предназначена для отмены (отката) всех изменений, выполненных текущей транзакцией.

Примечание

Команда RBAC эквивалентна SQL-запросу ROLLBACK; (см. документ «СУБД ЛИНТЕР. Справочник по SQL», пункт «Отмена изменений»).

Параметры вызова

inter(CBL, {VarBuf | NULL}, NULL, [CondBuf], NULL);

Входные данные

Входными данными являются:

  • контрольный блок CBL;

  • буфер параметров VarBuf (для транзакции с контрольными точками). В противном случае значение параметра должно быть NULL.

В контрольном блоке должны быть заполнены поля:

Имя поля Значение
NumChan Номер канала
Command "RBAC"
Node Имя ЛИНТЕР-сервера

Буфер параметров VarBuf используется при обработке команды RBAC для транзакции с контрольными точками и должен содержать информацию о месте в транзакции, c которого необходимо выполнить откат транзакции (см. структуру SAVE_POINT в описании команды COMT).

Выходные данные

Выходными данными является контрольный блок CBL.

В нем будут возвращены:

Имя поля Значение
CodErr Код завершения запроса к СУБД ЛИНТЕР
SysErr Код состояния ОС
Описание

После выполнения команды RBAC текущая транзакция завершается без сохранения изменений.

Если клиентское приложение имеет главный и подчиненные каналы и команда RBAC подается по главному каналу, то RBAC автоматически выполняется и для всех транзакций в подчиненных каналах.

Если перед аварийным закрытием канала (KILL) в нем имеется незавершенная транзакция, то по умолчанию она завершается командой RBAC.

Если в транзакции были установлены контрольные точки (SAVEPOINT) (см. документ «СУБД ЛИНТЕР. Справочник по SQL», пункт «Создание точки сохранения»), и фиксация изменений в них не производилась, то по команде RBAC выполняется откат всей транзакции.

Если в транзакции были установлены контрольные точки (например, SP1, SP2, SP3), и в некоторых из них выполнялась фиксация изменений (т.е. устанавливалось новое начало текущей транзакции, например, SP3), то команда RBAC выполняется в соответствии с алгоритмом, приведенным в таблице 13.

После выполнения команды RBAC до некоторой контрольной точки автоматически удаляются все более поздние контрольные точки.

При наличии в канале выборки данных и подачи команды RBAC по этому каналу выборка данных будет закрыта только в случае запуска ядра СУБД в режиме /COMPATIBILITY=STANDARD.

Пример
      «действия 1»
…
SET SAVEPOINT SP1
      «действия 2»
RBAC (SP1)

«действия 2» были отменены в БД (и уже не могут быть восстановлены),

«действия 1» пока не зафиксированы в БД, но если подать команду COMT

– будут зафиксированы в БД и транзакцию можно продолжать.

Таблица 13. Алгоритм отката изменений при наличии контрольных точек
Значение поляРезультат
SavePointNamedName
0не важноне важноОткат до точки SP3
10не важноОткат до точки SP3
11SP3Откат до точки SP3
11''Ошибка
11SP2Ошибки нет, но ROLLBACK не выполняется

Коды завершения
Код Описание
NORMAL Нормальное завершение (выполнен откат изменений)
ERRMODE Использование команды в недопустимом режиме. RBAC можно использовать в любом режиме, кроме AUTOCOMMIT
Пример формирования команды
#include < string.h >
#include < stdlib.h >
#include "inter.h"
L_LONG LinterRBAC(TCBL *pCBL)
   {
   memcpy(pCBL- >Command, "RBAC", 4);
   pCBL- >PrzExe &= ~Q_ASYNC;
   inter(pCBL, NULL, NULL, NULL, NULL);
   return pCBL- >CodErr;
   }
Пример использования команды

В примере показано использование:

  • команд обработки непоисковых запросов;

  • команд управления транзакциями;

  • команд управления доступом к данным.

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include "inter.h"
#include "exlib.h"

#ifndef WINCE
int    main()
#else
int    exnosel()
#endif
   {
   TCBL  CBLconnect;
   L_CHAR  Name_Pass[]="SYSTEM/MANAGER8";
   L_CHAR  Node[]="    ";
   L_WORD  Priority=0;
   L_LONG PrzExe=M_EXCLUSIVE | Q_ENCODE | M_BINARY;
   L_LONG Err;

   memset(&CBLconnect,0,sizeof(TCBL));
   Err=LinterOPEN(&CBLconnect, Name_Pass, Node, Priority, PrzExe);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("Connect to RDBMS Linter\n");

   Err=LinterNotSelect(&CBLconnect,
        "insert into PERSON(PERSONID)
   values(10000) ;");
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("insert into PERSON\n");

   Err=LinterRBAC(&CBLconnect);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("RollBack\n");

   Err=LinterNotSelect(&CBLconnect,
        "insert into PERSON(PERSONID)
   values(10000) ;");
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("insert into PERSON\n");

   Err=LinterNotSelect(&CBLconnect,
        "delete from PERSON where
   PERSONID=10000 ;");
   if (Err != NORMAL)
   PrintError(&CBLconnect);
   printf("delete from PERSON\n");

   Err=LinterCOMT(&CBLconnect);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("Commit\n");

   Err=LinterLREL(&CBLconnect, "SYSTEM", "PERSON");
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("LREL\n");

   Err=LinterUREL(&CBLconnect);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("UREL\n");

   Err=LinterLROW(&CBLconnect);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("LROW\n");

   Err=LinterUROW(&CBLconnect);
   if (Err != NORMAL)
     PrintError(&CBLconnect);
   printf("UROW\n");

   printf("End Example\n");

   return 0;
   }