ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.04.2021
Просмотров: 1871
Скачиваний: 3

!
56
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
10.
Уг
лу
бл
ен
но
е
из
уч
ен
ие
C
A
L
L-
ин
те
рф
ей
са
!
!
E-
mai
l:
ma
rke
t@
rele
x.r
u
inter(Cursor + i,NULL,NULL,NULL,NULL);
Необходимо
иметь
в
виду
,
что
управляющий
блок
Cursor[I]
перед
этим
должен
быть
очищен
,
чтобы
другие
поля
не
содержали
неправильной
информации
(
например
,
если
в
поле
Node
окажется
«
мусор
»,
то
результатом
операции
будет
1001).
Другой
вариант
–
просто
скопировать
содержимое
управляющего
блока
основного
соединения
в
управляющий
блок
курсора
перед
установкой
специфических
полей
.
Для
самостоятельного
решения
предлагается
одна
из
задач
:
Задача
5.
Модифицировать
данный
пример
,
добавив
возможность
ввода
пользователем
режимов
обработки
транзакций
.
Внимательно
посмотреть
отличия
в
работе
примера
в
оптимистичном
и
пессимистичном
режимах
.
Задача
6.
Модифицировать
данный
пример
,
добавив
возможность
отката
и
фиксации
изменений
по
главному
каналу
.
Выяснить
,
что
происходит
с
незавершенными
дочерними
транзакциями
при
фиксации
или
откате
родительской
.
10.4.
Получение
структуры
ответа
В
случае
,
когда
структура
ответа
неизвестна
(
например
,
идет
выполнение
запроса
,
заданного
пользователем
),
необходимо
выяснить
структуру
ответа
.
Для
этого
предназначена
команда
GETA.
Пример
prac10_e4
иллюстрирует
работу
данной
команды
.
Алгоритм
его
работы
таков
:
1.
Открывается
канал
.
2.
Пользователь
вводит
SELECT-
запрос
.
3.
Запрос
исполняется
.
4.
Выбирается
количество
столбцов
в
ответе
.
5.
Выбирается
описание
столбцов
.
6.
Закрывается
канал
.
Сборка
примера
должна
осуществляться
с
указанием
используемой
версии
СУБД
ЛИНТЕР
:
gcc prac10_e4.c -I /export/home/lindesk/linter5923/linter/
intlib/ /export/home/lindesk/linter5923/linter/intlib/
intlib.o -o prac10_e4 -lsocket -D_VER_MAX=590
В
данном
примере
описание
столбцов
выбирается
по
одному
,
хотя
более
эффективно
было
бы
выбирать
группами
по
N
элементов
. N = <
максимальный
размер
ответа
> / <
размер
дескриптора
столбца
,
или
sizeof(GETA_OUT).
Максимальный
размер
ответа
равен
4
Кб
.
Задача
7.
Модифицировать
данный
пример
,
чтобы
выборка
дескрипторов
столбцов
осуществлялась
блоками
.
10.5.
Асинхронное
выполнение
запроса
В
случае
,
когда
выполнение
запроса
может
занять
достаточно
много
времени
,
имеет
смысл
использовать
асинхронные
запросы
.
Для
этого
с
запросом
передается
адрес
функции
,
которая
будет
вызвана
по
окончанию
запроса
.
Алгоритм
работы
примера
prac10_e5
таков
:
1.
Открывается
канал
и
подчиненный
курсор
.
2.
Делается
попытка
создать
таблицу
PRAC10_T1.
3.
Создается
событие
на
добавление
строки
в
таблицу
.
4.
По
курсору
выполняется
команда
ожидания
события
,
которая
будет
обрабатываться
асинхронно
.
5.
Пользователь
в
любой
момент
может
подать
запрос
на
вставку
данных
в
таблицу
.
6.
Происходит
событие
,
завершается
обработка
запроса
по
курсору
,
и
управление
передается
в
процедуру
асинхронной
обработки
.

!
!
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
10.
Уг
лу
бл
ен
но
е
из
уч
ен
ие
C
A
L
L-
ин
те
рф
ей
са
!
57
E-
mai
l:
ma
rke
t@
rele
x.r
u
7.
Поскольку
из
асинхронного
обработчика
можно
вызывать
функцию
inter
только
асинхронно
,
то
очистка
события
также
происходит
в
асинхронном
режиме
.
8.
Закрывается
соединение
,
и
освобождаются
ресурсы
библиотеки
.
Асинхронный
обработчик
,
как
видно
из
вывода
примера
,
срабатывает
до
окончания
синхронной
операции
вставки
данных
в
таблицу
.
Вставка
по
каналу
4... –
синхронная
команда
на
вставку
стартовала
Вставка
выполнена
–
сработал
асинхронный
обработчик
ожидания
события
Очистка
события
...
готово
–
произошла
очистка
события
(
удаление
из
очереди
)
Вставка
выполнена
. –
завершилась
синхронная
команда
вставки
записи
.
Заметим
,
что
событие
инициируется
в
момент
любой
вставки
,
и
остается
актуально
до
тех
пор
,
пока
его
не
очистить
.
Поэтому
если
сначала
выполнить
вставку
,
а
затем
включить
режим
ожидания
,
то
ожидание
события
сразу
же
получит
ответ
(
т
.
к
.
событие
было
выставлено
предыдущей
вставкой
).
В
коде
примера
следует
обратить
внимание
на
то
,
как
передается
адрес
процедуры
и
указывается
флаг
асинхронности
:
memcpy(Cbl->Command," ",4);
Cbl->LnBufRow = 0;
Cbl->PrzExe = Cbl->PrzExe | Q_ASYNC;
inter(Cbl,NULL,"clear event INS_T1;", onEventCleared,
NULL);
Задача
8.
Модифицировать
данный
пример
,
чтобы
при
удалении
данных
в
специальную
таблицу
вставлялись
данные
о
количестве
удаленных
строк
и
времени
удаления
(
реализовать
это
,
используя
CALL-
интерфейс
и
асинхронную
обработку
событий
(
без
триггеров
)).

!
!
!
58
E-mail: market@relex.ru
ЗАО
НПП
«
РЕЛЭКС
»
http://www.relex.ru
Практическое
занятие
11
Основные
приемы
использования
LinAPI
Практика
2
часа
(
Лекция
10)
На
занятии
будут
приведены
примеры
,
иллюстрирующие
работу
с
СУБД
ЛИНТЕР
через
прикладной
интерфейс
LinAPI.
11.1.
Настройки
компилятора
Для
компиляции
файлов
с
примерами
необходимо
указывать
компилятору
путь
к
файлам
“linapi.h”, “decimals.h”, “tick.h”,
а
компоновщику
к
библиотекам
“linapi”, “decimals”,
“tick”.
Эти
файлы
и
библиотеки
поставляются
в
директории
linter/intlib.
К
примеру
,
в
UNIX-
системах
,
команда
на
компиляцию
файла
примера
ins_linapi.c
может
выглядеть
так
:
gcc -I /export/home/lindesk/linter5923/linter/intlib/
ins_linapi.c -llinapi -ldecimals -ltick -L /export/home/
lindesk/linter5923/linter/intlib/ -lsocket –lm –o
ins_linapi
11.2.
Открытие
соединения
,
курсора
и
выполнение
запроса
Ниже
представлен
пример
(prac12_e2.c),
в
котором
консольное
приложение
делает
попытку
создать
соединение
,
открыть
курсор
,
и
подать
по
нему
команду
по
удалению
и
созданию
таблицы
,
выполнить
несколько
операций
по
вставке
данных
.
#include <stdio.h>
#include <stdlib.h>
#include "linapi.h"
#if defined(VXWORKS) /* 05.03.02 */
#include "vxstart.h"
#endif
#ifdef _BCPP_
extern unsigned _stklen = 16383;
#endif
/* function for error processing for LinAPI */
void processing_error(LONG ret_cod,
WORD con_id,

!
!
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
11.
Ос
но
вн
ые
пр
ие
м
ы
ис
по
ль
зо
ва
ни
я
Li
n
A
PI
!
59
E-
mai
l:
ma
rke
t@
rele
x.r
u
WORD cur_id,
WORD stmt_id,
char * message)
{
LONG lRet;
LONG apierr = 0, error = 0, syserr = 0;
if ( ret_cod == LINAPI_ERROR )
{
/* getting error codes for required object */
if (lRet = LINTER_Error(con_id, cur_id, stmt_id,
&apierr, &error, &syserr, NULL, NULL))
printf("diagnostic error %ld\n",lRet);
else
{
printf("ApiErr = %ld, LinErr = %ld, SysErr = %ld\n%s
\n",
apierr, error, syserr, message);
if ( (apierr == eLinterError) && error > 2000 && error
< 3000)
{
/* getting string and position if syntax error is */
printf("Syntax error : line %d, position %d\n",
(short)syserr, *(short*)((char*)&syserr +2));
}
}
LINTER_CloseAPI(); /* Free library resource */
exit(1);
}
else
printf("Return code = %ld\n",ret_cod);

!
60
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
11.
Ос
но
вн
ые
пр
ие
м
ы
ис
по
ль
зо
ва
ни
я
Li
n
A
PI
!
!
E-
mai
l:
ma
rke
t@
rele
x.r
u
}
#if defined(VXWORKS) /* 05.03.02 */
MainStart(apidata, 32*1024, UninitLinterClient)
#else
int main(void)
#endif
{
WORD nConn; /* connection identifier */
WORD nCurs; /* cursor identifier */
LONG lRet; /* return code */
/* Establish connection */
printf("\nConnect\n");
if (lRet = LINTER_Connect("SYSTEM", 0, "MANAGER", 0,
NULL, mAutocommit, &nConn))
processing_error(lRet, nConn, 0, 0, "ERROR
Linter_Connect");
/* cursor opening for query processing */
printf("Open cursor\n");
if (lRet = LINTER_OpenCursor(nConn, &nCurs, NULL, 0,
mAutocommit))
processing_error(lRet, nConn, 0, 0, "Error open
cursor");
LINTER_ExecuteDirect(nCurs, "drop table PRAC12_STUDENT;",
0, NULL,NULL);
if (lRet = LINTER_ExecuteDirect(nCurs, "create table
PRAC12_STUDENT(num int not null primary key, fio char(250)
not null, skurs int default 1, sgroup int default 1 );", 0,
NULL,NULL))