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

Практическое
занятие
9
Знакомство
с
CALL-
интерфейсом
Практика
2
часа
(
Лекции
7,8)
На
данном
занятии
мы
освоим
основы
использования
CALL-
интерфейса
СУБД
ЛИНТЕР
,
на
примере
открытия
соединения
,
выполнения
SELECT-
запросов
,
обработки
ответов
и
закрытия
соединения
.
На
этом
примере
мы
получим
общие
навыки
подключения
CALL-
интерфейса
и
использования
функции
inter.
9.1.
Сборка
программы
с
CALL-
интерфейсом
Для
сборки
программы
с
CALL-
интерфейсом
необходимо
:
•
определить
символ
_VER_MAX=<
версия
ЛИНТЕР
>
где
<
версия
ЛИНТЕР
> -
это
число
,
полученное
<
как
первый
номер
версии
>*100 +
<
второй
номер
версии
>*10;
например
,
для
5.7
это
будет
570,
а
для
5.9 – 590;
•
прописать
пути
для
директивы
#include
в
директорию
intlib
дистрибутива
ЛИНТЕР
;
•
для
Windows
надо
определить
еще
символ
препроцессора
INTER_MSWINDOWS;
•
включить
в
сборку
библиотеку
intlib:
•
в
среде
Windows
это
может
быть
статическая
библиотека
inter325.lib,
расположенная
в
одной
из
поддиректорий
директории
intlib (
в
зависимости
от
компилятора
),
либо
динамически
подключаемая
библиотека
inter325.dll,
соответствующая
библиотека
импорта
inter325.lib
находится
в
директории
intlib/
lib;
•
в
среде
Unix
просто
используется
объектный
файл
intlib.o,
расположенный
в
поддиректории
intlib
дистрибутива
;
•
либо
вместо
подключения
библиотеки
можно
подключить
непосредственно
исходный
текст
CALL-
интерфейса
intlib/intlib.c.
В
среде
Windows
в
дистрибутиве
ЛИНТЕР
имеется
файл
Definition,
который
конфигурируется
при
установке
системы
.
Он
включает
все
необходимые
определения
,
и
может
быть
просто
включен
в
make-
файл
.
Примеры
использования
CALL-
интерфейса
и
соответствующие
make-
файлы
имеются
в
директориях
samples/call
и
samples/c
дистрибутива
ЛИНТЕР
.
Задание
:
Собрать
примеры
простейшего
использования
CALL-
интерфейса
,
поставляемые
вместе
с
ЛИНТЕР
.
Указания
:
Перейдите
в
поддиректорию
samples/c
дистрибутива
ЛИНТЕР
.
Изучите
исходный
текст
примера
step/step.c.
Он
содержит
вызовы
команд
CALL-
интерфейса
“OPEN”, “SLCT”, “GETN”
и
“CLOSE”,
печатая
простую
выборку
,
сделанную
оператором
SELECT.
Изучите
содержимое
make-
файла
(
он
содержит
команды
для
сборки
всех
примеров
,
расположенных
в
поддиректории
samples/c).
Соберите
примеры
:
•
для
Unix,
подайте
команду
make;
•
для
Windows,
подайте
команду
nmake /f makefile.vc (
предполагается
использование
Microsoft Visual C++).

!
52
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
8
П
ри
ме
р
со
зд
ан
ия
за
щ
и
щ
ен
но
й
ба
зы
да
нн
ы
х
!
!
E-
mai
l:
ma
rke
t@
rele
x.r
u
Убедитесь
в
том
,
что
запущена
СУБД
ЛИНТЕР
на
демонстрационной
БД
,
содержащей
таблицу
PERSON.
Запустите
исполняемый
файл
примера
step
и
просмотрите
результаты
.
9.2.
Разработка
собственного
примера
Задание
:
Используя
демонстрационный
пример
из
состава
СУБД
ЛИНТЕР
,
необходимо
разработать
и
отладить
собственную
программу
,
использующую
CALL-
интерфейс
для
выборки
данных
.
Все
задачи
связаны
с
таблицами
PERSON, AUTO
или
FINANCE
демонстрационной
БД
ЛИНТЕР
.
Задача
1
.
Разработать
программу
,
которая
запрашивает
начальные
буквы
имени
человека
(
поле
PERSON.NAME),
и
выводит
данные
обо
всех
людях
,
имя
которых
начинается
с
этих
букв
и
о
марке
(MAKE),
модели
(MODEL)
и
серийном
номере
(SERIALNO)
автомобилей
(
таблица
AUTO),
принадлежащих
каждому
человеку
(
таблицы
PERSON
и
AUTO
связаны
по
полю
PERSONID).
При
этом
данные
о
человеке
должны
выводиться
одной
строкой
,
затем
несколько
строк
о
его
автомобилях
,
затем
данные
о
следующем
человеке
и
т
.
д
.
Задача
2
.
Разработать
программу
,
которая
запрашивает
начальные
буквы
марки
автомобиля
(AUTO.MAKE)
и
выполняет
запрос
на
выборку
данных
,
соответствующих
этим
маркам
,
после
чего
печатает
количество
ответов
и
запрашивает
номер
строки
,
которую
надо
отобразить
.
После
ввода
номера
строки
,
программа
должна
отобразить
данные
этой
строки
,
и
снова
запросить
новый
номер
(
до
тех
пор
,
пока
пользователь
не
введет
недопустимое
значение
номера
).
Задача
3
.
Разработать
программу
,
которая
запрашивает
название
кредитной
карты
(
первые
несколько
букв
поля
CRDITCRD
таблицы
FINANCE)
и
выводит
имена
всех
людей
(PERSON.NAME),
владеющих
картой
данного
типа
(
таблицы
PERSON
и
FINANCE
связаны
по
полю
PERSONID).
При
этом
программа
должна
запрашивать
порядок
сортировки
имен
при
печати
:
по
возрастанию
или
по
убыванию
.
Напечатав
список
имен
,
программа
снова
должна
запросить
порядок
вывода
имен
,
после
чего
выводит
их
(
возможно
,
уже
в
другом
порядке
)
и
так
далее
,
пока
пользователь
не
введет
команду
выхода
.
Задача
4
.
Разработать
программу
,
которая
запрашивает
уникальный
идентификатор
человека
(PERSON.PERSONID).
После
ввода
идентификатора
программа
выводит
имя
человека
(PERSON.NAME)
и
выдает
список
всех
автомобилей
,
которыми
владеет
данный
человек
(
произвольный
набор
колонок
из
таблицы
AUTO
по
желанию
разработчика
,
таблицы
AUTO
и
PERSON
связаны
по
полю
PERSONID).
Далее
программа
запрашивает
новый
идентификатор
и
т
.
д
.,
пока
пользователь
не
введет
–1.
Задача
5
.
Разработать
программу
,
которая
запрашивает
величину
жалованья
человека
(
поле
SALARY
таблицы
PERSON).
После
этого
программа
должна
выдать
информацию
(
идентификатор
(PERSONID),
имя
(NAME),
должность
(JOB)
и
жалованье
)
о
десяти
людях
,
жалование
которых
наиболее
близко
к
введенному
значению
.

Практическое
занятие
10
Углубленное
изучение
CALL-
интерфейса
Практика
6
часов
(
Лекция
9)
На
занятии
будут
приведены
примеры
,
иллюстрирующие
работу
с
СУБД
ЛИНТЕР
через
прикладной
интерфейс
низкого
уровня
Intlib (CALL-
интерфейс
).
Будут
рассмотрены
следующие
вопросы
:
•
обработка
ошибок
с
использованием
GETE;
•
использование
DML/DDL
запросов
;
•
работа
с
BLOB-
столбцами
;
•
работа
с
подчиненными
курсорами
;
•
обработка
транзакций
;
•
получение
структуры
ответа
;
•
асинхронное
выполнение
запроса
.
10.1.
Использование
DML/DDL
запросов
,
обработка
ошибок
Алгоритм
работы
примера
prac10_e1.c
таков
:
1.
Открывается
канал
.
2.
Удаляется
таблица
AUTO,
и
при
ошибке
выводится
текст
с
помощью
команды
GETE.
3.
Создается
таблица
AUTO,
и
при
ошибке
выводится
текст
с
помощью
команды
GETE.
4.
Закрывается
канал
.
Следует
обратить
внимание
на
то
,
что
запросы
DML/DDL (
все
,
кроме
SELECT),
подаются
с
четырьмя
пробелами
в
поле
Command:
memcpy(Cbl.Command," ",4); /* Non SELECT command */
inter(&Cbl,NULL,"drop table auto;",NULL,NULL);
Для
получения
информации
о
произошедшей
ошибке
во
время
компиляции
или
выполнения
запроса
,
предназначена
команда
GETE.
В
примере
рассматривается
применение
данной
команды
для
получения
текстового
сообщения
от
ядра
о
произошедшей
ошибке
(
функция
PrintError).
memcpy(pCBL->Command,"GETE",4); /* Get error text */
pCBL->RowId = pCBL->CodErr;
pCBL->LnBufRow = MAXSTRLEN;
inter(pCBL,NULL,NULL,NULL,szErrorText);
if (pCBL->CodErr != NORMAL)
printf("
Ошибка
обработки
GETE
: %ld\n", pCBL->CodErr);
else
{

!
54
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
10.
Уг
лу
бл
ен
но
е
из
уч
ен
ие
C
A
L
L-
ин
те
рф
ей
са
!
!
E-
mai
l:
ma
rke
t@
rele
x.r
u
realLen = (pCBL->LnBufRow < realLen - 1) ? pCBL->LnBufRow
: realLen;
printf("
Сообщение
: %s\n", szErrorText);
}
Для
получения
текстового
сообщения
заполняется
поле
RowId
номером
ошибки
ЛИНТЕР
, LnBufRow
длиной
буфера
под
сообщение
.
Адрес
буфера
передается
как
последний
параметр
функции
inter.
При
успешном
завершении
функции
в
буфере
находится
текстовое
сообщение
об
ошибке
,
которое
в
примере
выводится
на
экран
.
Для
демонстрации
примера
необходимо
,
чтобы
существовала
таблица
ERRORS
с
описаниями
ошибок
.
Если
данная
таблица
отсутствует
,
то
сообщение
об
ошибках
будет
выглядеть
так
:
Linter return code: 2202
.
10.2.
Работа
с
BLOB-
столбцами
Алгоритм
работы
примера
prac10_e2.c
таков
:
1.
Открывается
канал
.
2.
Делается
попытка
создания
таблицы
TFILE.
3.
Предлагается
меню
,
в
котором
:
•
в
таблицу
добавляется
запись
,
в
BLOB-
поле
которой
загружается
указанный
пользователем
файл
;
•
делается
выборка
из
таблицы
,
и
выгружаются
данные
BLOB-
поля
в
файл
из
строки
,
указанной
пользователем
.
18.
Закрывается
канал
.
Следует
обратить
внимание
,
на
то
,
что
при
занесении
BLOB-
данных
можно
указать
тип
(
целое
число
),
передаваемое
в
параметре
RowId.
memcpy(pCbl->Command,"AOBJ",4);
pCbl->RowId = 0;
pCbl->LnBufRow = realLen;
inter(pCbl,NULL,NULL,NULL,buf);
При
получении
BLOB-
данных
следует
иметь
в
виду
,
что
передаваемая
в
параметре
RowId
позиция
начинается
с
единицы
.
long beginPos = 1;
…
memcpy(pCbl->Command,"GOBJ",4);
pCbl->RowId = beginPos;
pCbl->LnBufRow = blobPortion;
inter(pCbl,NULL,NULL,NULL,buf);
…
beginPos += realLen;
Работы
с
данными
из
BLOB-
столбца
с
минимальным
номером
используются
команды
AOBJ, COBJ
и
GOBJ.
Для
работы
с
другими
BLOB-
столбцами
(
с
указанием
номера
)
следует
использовать
команды
ABLB, CBLB
и
GBLB.
Обучаемым
необходимо
самостоятельно
решить
одну
из
следующих
задач
.

!
!
П
ра
кт
ич
ес
ко
е
за
ня
ти
е
10.
Уг
лу
бл
ен
но
е
из
уч
ен
ие
C
A
L
L-
ин
те
рф
ей
са
!
55
E-
mai
l:
ma
rke
t@
rele
x.r
u
Задача
1.
Модифицировать
данный
пример
,
добавив
возможность
очистки
всей
таблицы
и
удаления
указанных
записей
.
Задача
2.
Модифицировать
данный
пример
,
добавив
возможность
очистки
содержимого
BLOB-
ячейки
и
добавления
данных
в
конец
существующей
BLOB-
ячейки
.
Задача
3.
Модифицировать
данный
пример
,
добавив
в
таблицу
поле
FSOURCE,
в
котором
будет
располагаться
исходный
текст
данного
исполняемого
файла
(
если
он
существует
в
директории
данного
файла
).
Например
,
пользователь
указывает
имя
файла
/
home/linter/prac10/prac10_e2,
тогда
добавляется
новая
запись
;
в
столбец
FCONTENT
загружается
этот
файл
,
а
в
столбец
FSOURCE
добавляется
файл
/home/linter/prac10/
prac10_e2.c.
Задача
4.
Модифицировать
данный
пример
,
следующим
образом
:
если
для
указанного
имени
файла
существует
файл
*.c (
с
расширением
‘c’),
то
он
добавляется
следующей
строкой
и
ему
присваивается
тип
1.
Если
существует
файл
*.h,
то
он
также
добавляется
новой
строкой
и
ему
присваивается
тип
2.
10.3.
Работа
с
подчиненными
курсорами
,
обработка
транзакций
Как
уже
известно
,
клиентское
приложение
для
работы
с
БД
должно
открыть
канал
связи
(
соединение
).
При
открытии
канала
приложение
должно
указать
имя
ЛИНТЕР
-
сервера
,
с
которым
должно
быть
установлено
соединение
,
а
также
регистрационные
данные
для
проверки
санкционированного
доступа
(
имя
пользователя
и
пароль
,
под
которыми
приложение
будет
зарегистрировано
как
пользователь
БД
).
Через
соединение
могут
быть
открыты
подчиненные
каналы
,
называемые
курсорами
.
Для
открытия
курсора
приложению
уже
не
нужно
указывать
регистрационные
данные
–
курсоры
наследуют
эту
информацию
от
соединения
,
которому
они
подчинены
.
Это
удобно
использовать
,
когда
приложение
должно
обрабатывать
различные
запросы
,
направляемые
к
одной
и
той
же
БД
:
можно
не
открывать
несколько
соединений
,
а
использовать
несколько
курсоров
.
Механизм
соединений
и
курсоров
используется
СУБД
ЛИНТЕР
для
управления
транзакциями
.
Изменения
данных
в
БД
,
прошедшие
по
некоторому
курсору
,
могут
фиксироваться
(
откатываться
)
независимо
от
работы
по
другим
курсорам
соединения
,
однако
фиксация
/
откат
по
соединению
вызовет
фиксацию
/
откат
по
всем
подчиненным
курсорам
.
Пример
prac10_e3.c
иллюстрирует
работу
канала
и
двух
подчиненных
курсоров
.
Алгоритм
его
работы
таков
:
1.
Открывается
канал
.
2.
Делается
попытка
создания
таблицы
PRAC12_T1.
3.
Открываются
два
курсора
(
в
оптимистичном
режиме
обработки
транзакций
).
4.
Предлагается
меню
,
в
котором
:
•
в
таблицу
добавляется
запись
по
любому
из
курсоров
;
•
из
таблицы
удаляются
все
записи
по
любому
из
курсоров
;
•
делается
выборка
из
таблицы
по
любому
из
курсоров
;
•
фиксируются
изменения
по
любому
из
курсоров
;
•
откатываются
изменения
по
любому
из
курсоров
;
19.
Закрывается
канал
.
Студенты
должны
попробовать
выполнять
разные
действия
по
разным
курсорам
и
посмотреть
,
как
работает
механизм
подчиненных
курсоров
.
Следует
обратить
внимание
на
то
,
что
номер
родительского
канала
устанавливается
в
CBL
дочернего
Следующим
образом
:
Cursor[i].NumChan = Cbl.NumChan;
Cursor[i].PrzExe = M_OPTIMISTIC;
memcpy(Cursor[i].Command,"OCUR",4); /* Open cursor */