Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Линтер методичка

.pdf
Скачиваний:
78
Добавлен:
21.05.2015
Размер:
1.38 Mб
Скачать

 

printf("%d records selected\n", recCount);

П

 

ра

if (lRet = LINTER_BindAnswer(nCurs, 0, 3, &nKurs, 0, 0,

кт

tInt, sizeof(nKurs), 0, 0, &realLen))

ич

ес

processing_error(lRet, 0, nCurs, 0,"Error

ко

BindAnswer");

е

 

за

 

ня

for (i = 0; i < recCount; i++)

ти

е{

11.

/* Fetch after BindAnswer gives data in nKurs*/

Ос

но

if (lRet = LINTER_Fetch(nCurs, toAbsNumber, i + 1, 1,

вн

0, 0, 0))

ые

пр

processing_error(lRet, 0, nCurs, 0,"Error Fetch");

ие

if (nKurs > 0 && nKurs <= MAXKURSNUM)

м

ы

statistic[nKurs]++;

ис

printf("Kurs = %d\n", nKurs);

по

ль

}

зо

ва

} else

ни

printf("No records found");

я

Li

 

n

//create table

A

PI

if (lRet = LINTER_ExecuteDirect(nCurs, "drop table

 

71!

PRAC12_STAT;", 0, NULL,NULL))

 

{

 

if (lRet == SQLUNKTAB)

 

printf("Table PRAC12_STAT not exists -- create it

 

\n");

 

else

 

processing_error(lRet, 0, nCurs, 0,"Error

 

ExecuteDirect");

E-

} else

mai

printf("Table PRAC12_STAT deleted\n");

l:

ma

 

rke

 

t@

 

rele

 

x.r

 

u

 

72!

П

ра

кт

ич

ес

ко

е

за

ня

ти

е

11.

Ос

но

вн

ые

пр

ие

м

ы

ис

по

ль

зо

ва

ни

я

Li n A PI

if (lRet = LINTER_ExecuteDirect(nCurs, "create table PRAC12_STAT (skurs int not null, scount int);", 0, NULL,NULL))

processing_error(lRet, 0, nCurs, 0,"Error ExecuteDirect");

else printf("Table PRAC12_STAT created\n");

for (i = 0; i < MAXKURSNUM; i++)

{

sprintf(szSQL, "insert into PRAC12_STAT values (%d, %d);\n", i + 1, statistic[i]);

printf(szSQL);

if (lRet = LINTER_ExecuteDirect(nCurs, szSQL, 0, NULL,NULL))

processing_error(lRet, 0, nCurs, 0,"Error ExecuteDirect");

}

printf("Cursor closing\n");

if (lRet = LINTER_CloseCursor(nCurs))

processing_error(lRet, 0, nCurs, 0,"Error CloseCursor");

printf("Connection closing\n");

if (lRet = LINTER_CloseConnect(nConn))

processing_error(lRet, nConn, 0, 0, "ERROR CloseConnect");

E- mai l: ma rke t@ rele x.r u

printf("LINTER_CloseAPI\n");

LINTER_CloseAPI();

/* Free library resource */

printf("Done.\n");

return 0;

/* End */

П}

ра

кт

Скомпилируем этот файл:

 

ич

gcc prac12_e3.c -I /export/home/lindesk/linter5923/linter/

ес

ко

intlib/ -llinapi -lsocket -lm -L /export/home/lindesk/

е

linter5923/linter/intlib/ -o prac12_e3

 

за

 

 

ня

Задача 5. (Студенты выполняют самостоятельно)

Модифицировать данный

ти

пример: в таблицу статистики добавляется столбец SGROUPS

(количество групп на курсе)

иформируется, как наибольшие номер группы у встретившихся студентов данного курса.

11.11.5. Фиксация и откат изменений

Ос

Рассмотрим задачу: пусть требуется перевести всех студентов на следующий курс, а

но

 

 

 

тех, кто закончил 6 курс удалить из таблицы.

 

вн

Тогда, алгоритм работы приложения будет таким:

 

ые

соединяемся с базой данных в пессимистичном режиме;

пр

создаем курсор;

 

ие

выполняем обновление всех студентов – увеличение курса;

м

удаляем студентов с курсом, большим шести;

 

ы

спрашиваем у пользователя подтверждение на фиксацию изменений;

ис

фиксируем или откатываем изменения;

 

по

закрываем курсор и соединение, освобождаем ресурсы библиотеки.

ль

 

 

 

зо

Ниже представлен листинг программы из файла prac12_e4.c.

ва

#include <stdio.h>

 

ни

 

я

#include <stdlib.h>

 

Li

 

 

 

n

 

 

 

A

#include "linapi.h"

 

PI

 

 

 

 

!73

#if defined(VXWORKS)

/* 05.03.02 */

 

 

#include "vxstart.h"

 

 

#endif

 

 

#ifdef _BCPP_

 

 

extern unsigned _stklen = 16383;

 

 

#endif

 

E-

 

 

 

mai

/* function for error processing for LinAPI */

l:

ma rke t@ rele x.r

u

74!

П

ра

кт

ич

ес

ко

е

за

ня

ти

е

11.

Ос

но

вн

ые

пр

ие

м

void processing_error(LONG ret_cod, WORD con_id,

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

 

ва

 

ни

{

 

я

 

Li

printf("ApiErr = %ld, LinErr = %ld, SysErr = %ld\n%s

 

n

 

\n",

 

A

 

PI

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));

E- mai l: ma rke t@ rele x.r u

}

}

LINTER_CloseAPI(); /* Free library resource */ exit(1);

}

Пelse

ра

printf("Return code = %ld\n",ret_cod);

кт

 

ич }

 

ес

 

ко

 

е#define MAXSTRLEN 100

за

#define MAXKURSNUM 6

 

 

ня

 

 

ти

 

 

 

 

е

 

 

 

 

11.

#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 */

 

ни

 

я

 

 

 

 

Li

LONG realLen = 0;

 

 

n

 

 

A

LONG recCount = 0;

 

 

PI

 

 

char szMask[MAXSTRLEN] = {0};

!75

printf("\nConnect\n");

if (lRet = LINTER_Connect("SYSTEM", 0, "MANAGER", 0, NULL, mExclusive, &nConn))

processing_error(lRet, nConn, 0, 0, "ERROR Linter_Connect");

E-

printf("Open cursor\n");

mai

 

l:

 

ma

 

rke

 

t@

 

rele

 

x.r

 

u

 

76!

П

ра

кт

ич

ес

ко

е

за

ня

ти

е

if (lRet = LINTER_OpenCursor(nConn, &nCurs, NULL, 0, mExclusive))

processing_error(lRet, nConn, 0, 0, "Error open cursor");

printf("Students updating...");

if (lRet = LINTER_ExecuteDirect(nCurs, "update PRAC12_STUDENT set SKURS = SKURS + 1;", 0, NULL,NULL))

11.processing_error(lRet, 0, nCurs, 0,"Error

Ос

но

вн

ые

пр

ие

м

ы

ис

по

ль

зо

ва

ни

ExecuteDirect");

realLen = sizeof(recCount);

if (lRet = LINTER_GetCursorOption(nCurs, cRowCount, 0, &recCount, &realLen))

processing_error(lRet, 0, nCurs, 0,"Error GetCursorOption");

printf(" Done. %d records updated.\n", recCount);

printf("Students deleting...");

яif (lRet = LINTER_ExecuteDirect(nCurs, "delete from

Li

PRAC12_STUDENT where SKURS > 6;", 0, NULL,NULL))

n

processing_error(lRet, 0, nCurs, 0,"Error

A

PI

ExecuteDirect");

realLen = sizeof(recCount);

if (lRet = LINTER_GetCursorOption(nCurs, cRowCount, 0, &recCount, &realLen))

processing_error(lRet, 0, nCurs, 0,"Error GetCursorOption");

printf(" Done. %d records deleted.\n", recCount);

printf("Do you want to commit changes? (Y/N)\n"); gets(szMask);

E- mai l: ma rke t@ rele x.r u

if (!strcmp(szMask, "Y") || !strcmp(szMask, "y"))

{

Пprintf("Commit...");

ра

if (lRet = LINTER_ExecuteDirect(nCurs, "commit;", 0,

кт

NULL,NULL))

ич

ес

processing_error(lRet, 0, nCurs, 0,"Error

ко

ExecuteDirect");

е

printf("Done\n");

за

ня

} else

ти

е{

11.

printf("Rollback...");

Ос

но

if (lRet = LINTER_ExecuteDirect(nCurs, "rollback;", 0,

вн

NULL,NULL))

 

ые

 

пр

processing_error(lRet, 0, nCurs, 0,"Error

ие

ExecuteDirect");

 

м

 

printf("Done\n");

 

ы

 

ис

}

 

по

 

ль

 

 

зо

printf("Cursor closing\n");

ва

ни

if (lRet = LINTER_CloseCursor(nCurs))

я

processing_error(lRet, 0, nCurs, 0,"Error CloseCursor");

Li

n

printf("Connection closing\n");

A

PI

if (lRet = LINTER_CloseConnect(nConn))

77!

processing_error(lRet, nConn, 0, 0, "ERROR

 

CloseConnect");

 

 

 

 

printf("LINTER_CloseAPI\n");

 

LINTER_CloseAPI();

/* Free library resource */

E- mai l: ma rke t@ rele x.r u

printf("Done.\n"); return 0;

/* End */

}

78!

ПСкомпилируем этот файл:

ра

gcc prac12_e4.c -I /export/home/lindesk/linter5923/linter/

кт

ич

intlib/ -llinapi -lsocket -lm -L /export/home/lindesk/

ес

linter5923/linter/intlib/ -o prac12_e4

 

ко

Задача 6. (Студенты выполняют самостоятельно)

Модифицировать данный

е

пример: в таблицу студентов добавляется столбец SFORM (форма обучения – бакалавр,

за

 

 

 

специалист или магистр). Модифицировать процесс удаления студентов из таблицы по

окончаниюня

вуза, учитывая, что время обучения бакалавра – 4 года, специалиста – 5 лет и

магистра – 6.

 

ти

Выпускников заносить в таблицу PRAC12_VYPUSK

( ФИО , номер группы ,

е

выпуска, квалификация).

11.

Ос

но

вн

ые

пр

ие

м

ы

ис

по

ль

зо

ва

ни

я

Li n A PI

E- mai l: ma rke t@ rele x.r u

Практическое занятие 12

Пример разработки приложения для ЛИНТЕР с использованием Qt

Практика 8 часов

Целью данной практики является освоение техники построения графического приложения, работающего с базой данных ЛИНТЕР в среде Unix, при использовании графической библиотеки Qt версии 1.4.x или выше (необходимы общие знания по Qt).

Вданном практике рассматривается синхронная и асинхронная работа с ЛИНТЕР и прием сообщений от ЛИНТЕР через асинхронный запрос. Работа с ЛИНТЕР осуществляется через Call-интерфейс (необходимы знания из предыдущих занятий по Callинтерфейсу). Используются вызовы Call-интерфейса, уже изученные нами, и никакой особой специфики здесь нет. Аналогичным образом можно было бы использовать и LinAPI. Специфичность нашей практики заключается в использовании классов C++, обеспечивающих работу с ЛИНТЕР, в частности, при построении приложений с графическим интерфейсом пользователя на основе библиотеки Qt.

Впримере используется таблица AUTO со следующей структурой:

create table auto(

 

MAKE

char(20),

MODEL

char(20),

BODYTYPE

char(15),

CYLNDERS

integer,

HORSEPWR

integer,

DSPLCMNT

integer,

WEIGHT

integer,

COLOR

char(10),

YEAR

integer,

SERIALNO

char(16),

CHKDATE

integer,

CHKMILE

integer,

PERSONID

integer primary key);

Эта таблица входит в демонстрационную БД СУБД ЛИНТЕР и ее всегда можно создать и загрузить из файлов, входящих в дистрибутив ЛИНТЕР. Для работы примеров в базе данных, после ее старта, должно быть создано событие AUTO_CHANGE:

create event auto_change as delete, update, insert on auto;

Приложение визуально построено так, что данные из запроса отображаются в многострочном элементе (это либо список, либо таблица) и для текущей строки в 4 однострочных элементах (однострочный редактор).

!80

Практическая работа разделена на три этапа , на каждом из которых создается готовоеП графическое приложение.

ра Сборка приложения осуществляется с помощью команды 'make' в результате выполнениякт которой создается исполняемый файл 'main'. Перед сборкой должны быть

изменены значения переменных LINTER и QTDIR на те, которые соответствуют

ич

реальности. Исходные файлы и сценарии сборки для каждого из примеров находятся в

ес

подкаталогах step1, step2, step3.

ко На первом этапе - демонстрируется синхронная работа с ЛИНТЕР. В приложении

используется многострочный элемент - список для вывода результата выборки и 4

однострочных редактора, для вывода значений полей каждой записи

за

После запуска программы список будет заполнен значениями поля AUTO.SERIALNO,

ня

а в однострочных редакторах значениями полей MAKE, MODEL,YEAR, SERIALNO текущей

ти

 

 

записи выборки.

е

На втором этапе добавляется возможность асинхронного приема сообщения от

12

 

 

Линтера и его синхронная обработка в программе. Если во время работы программы при

помощиП

любой клиентской программы изменить содержимое таблицы AUTO, то ранее

запущенная программа сама перечитает данные.

ри

На третьем этапе к функциональности реализованной на первых этапах добавляется

ме

возможность асинхронного выполнения select-запроса. Программа не ожидает ответа на

р

запрос, а продолжает работать, и только после наступления события о готовности

ра

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

результатоваб выборки. Для того чтобы была видна работа программы, при изменении

состояния источника данных выводятся информационные окна. SQL-запрос к Линтеру

от

 

 

 

написан специально с перемножением таблиц, чтобы была видна пауза между началом

ки

 

 

 

выполнения запроса и его концом.

пр

Далее опишем более подробно устройство классов и принципы по которым были

написаныил

приложения на каждом из этапов.

ож

12.1. Первый этап

ен

В прикладных системах часто одни и те же данные одновременно отображаются в

ия

 

 

 

разных визуальных элементах. Поэтому введем отдельный объект для работы с данными -

источникдл

данных. Для представления данных в программе разработаем два класса:

я

CDataSource - интерфейсный класс источник данных реляционного типа. Его

основные особенности:

Л

 

он осуществляет технологию работы с курсором через методы getCurRow ,

И

 

Н

 

 

setCurRow, rowCount;

 

он может находиться в двух состояниях: активен и неактивен; метод state может

Т

 

 

 

возвратить Empty/Ready;

Е

 

 

 

источник данных активизируется методом retrieve, а деактивизируется методом

Р

 

 

 

destroy или при возникновении ошибки;

с

 

 

 

табличные значение можно получить вызовом методов

ис

 

 

 

getNull,

по

 

 

 

 

getField,

ль

 

 

 

 

getFieldAsChar (всегда конвертирует значение в строку);

зо

 

 

 

источник данных имеет 3 сообщения:

ва

onError - генерируется при возникновении ошибки,

ни

onFullChange - генерируется при изменении текущего состояния,

ем

onCurRowChange - генерируется при изменении текущей строки курсора

Qt

 

В принципе, класс источника данных должен быть абстрактным (можно разработать различные источники данных - например источник данных в памяти), но мы сразу будем

делать реализацию настроенную на работу с SQL-запросами, используя класс CSqlDS.

E-

mai CSqlDS – класс, который делегирует свою функциональность по работе с выборкой

по SQL-запросу. Класс имеет одно сообщение 'onError' (в принципе можно обойтись и без l:

него, если построить контроль ошибок через возвращаемый результат или исключения). В ma

rke t@ rele x.r u