powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Embedded SQL & MFC HOWTO
38 сообщений из 38, показаны все 2 страниц
Embedded SQL & MFC HOWTO
    #32506869
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
РАЗРАБОТКА МНОГОПОТОЧНЫХ КЛИЕНТСКИХ ПРИЛОЖЕНИЙ
ДЛЯ IBM DB2 V8.1 C ИСПОЛЬЗОВАНИЕМ MS Visual C++ V6.0

Очень часто программисты которые впервые сталкиваются с DB2
стараются пременить опыт, который они имели при работе с другими
базами (Oracle,Sybase,MS SQL). Я же полагаю что переносить такой опыт
нежелательно, ибо что для одного сервера баз данных работает хорошо,
то для другого может быть совсем не так.

Здесь, в этой статье я покажу, как легко и просто можно создавать
высокоэффективные программы на Visual С++ для DB2.

Скажу сразу, что приложение реализовано с помощью Embedded SQL.
Почему не ODBC,CLI? По многим причинам:

1) Производительность. Что делают программисты в других базах данных
для повышения производительности? Они делают хранимые процедуры.
Почему приработе хранимых процедур скорость выше? Потому, что они
уже откомпилированы и план запросы уже готов. Осталось только
передать нужные параметры.
А что такое Embedded SQL? В сущности это то же самое. Разработка
программы состоит из написания исходиника *.sqx, обработки его
препроцессором (компилятором SQL) и получения 2-х файлов -
*.bnd и *.cxx. Файлы с расширением *.bnd содержат SQL в
откомпилированном, понятном DB2 виде. А файл *.cxx - содержит
всего лишь вызов этого SQL. Причем файл *.bnd должен быть
связан с базой данных припомощи команды bind. В процессе связывания
строится план запроса.
Как нужно работать с базой данных, чтобы не было никаких задержек?
Понятно, что запросы должны быть как можно короче и выполняться
как можно быстрее. Как вы думаете, сколько хранимых процедур
нужно реализовать, чтобы получить нормальный контекстный поиск?
Для создания нужной интерактивности и производительности
потребуется не один десяток процедур. Причем это не процедуры,
которые реализуют какую-то сложную бизнес-логику. Они реализуют
всего-лишь пользовательский интерфейс. Отсюда вытекает следующий
тезис:
2) Простота и скорость разработки. Отсутствие ошибок.
Гораздо проще иметь все под рукой. В одном файле и SQL,
который будет выполняться, и собственно код приложения.
Более того, в процессе компиляции будут проверены типы данных,
корректность SQL, и если вы написали что-то не так - программа
просто не откомпилится. Более того - нет необходимости
согласовывать код SQL на сервере и код приложения.
Кроме того у embedded sql имеется поддержка версионности.
Поэтому всегда будут работать как старые, так и новые приложения.

3) Удобство. В чем оно заключается? Во-первых больше возможностей
по отладке приложений. После каждого оператора SQL вы можете
вывести сообщение, и решить как поступать - выполнить COMMIT
или ROLLBACK или продолжить дальше выполнение программы.
Попробуйте сделать такое в хранимой процедуре? Кроме того
вам достуно выполнение любых операторов SQL.

4) Переносимость. Это самый больной вопрос. Все программисты
кричат о переносимости. И, как правило говорят что все что можно
запихнуть на сервер базы данных - надо запихнуть. В результате
на сервере в конце концов появляются хранимые процедуры длинной
в несколько листов и которые выполняются не 1-2 секунды,
а по нескольку минут, или даже нескольку дисятков минут.
Причем в этот момент невозможно точно отследить что делает
такая процедура. Может она зависла?
Я полагаю что все обращения к базе данных должны отрабатываться
мгновенно, за исключением разве что отчетов в которых количество
строк перекачиваемых на рабочуюю станцию достаточно велико
(несколько тысяч). В этом случае простительна некоторая задержка.
Перенос основной массы кода не сервер базы данных врядли
значительно сократит трудозатраты переноса с платформы на платформу,
но вот увеличит неоправданную нагрузку на сервер базы данных - это
точно. В любом случае перенос с С++ на Java или с Windows на Linux
потребует некоторых затрат.

4) Безопасность. В случае использования embedded sql радикально
улучшается положение с защищенностью.
a) Защищенность от ошибки программиста
б) У позьзователей работающих с приложениями реализованными на
embedded sql отсутствует реальный доступ к объектам в базе данных.
У них имеется только право выполнять ваше приложение.
в) Разработка приложений и их инсталяция может быть разделена
между несколькими людьми. Одни имеют право компиляции, другие -
связывания, третьи - выполнения.
г) В приложении содержится только код вызываемого SQL, таким образом
полностью отсутствует возможность увидеть реальную структуру данных
или узнать ее на основе информации идущей по сети.

5) Полная поддержка C++ и как следствие ООП.
Поддержка всех фичей C++ (указатели, ссылки, шаблоны, классы)
делает С++ самым выгодным инструментом для разработки приложений.

А теперь о некоторых неудобствах:

Насколько я понял, embedded sql пока что не позволяет обрабатывать
recordsets которые возвращаются из сохраненных процедур. Но без
этого можно запросто обойтись. Например записать recordset во
временную таблицу.

Многие испытывают дискомфорт из-за за того, что требуется двойная
предкомпиляция при обработке макросов. Например такой код придется
обрабатывать препроцессором дважды:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    ////////////////////
    //test.sqx

    #define  LEN  12 
    EXEC SQL BEGIN DECLARE SECTION;
	    char name[LEN];
    EXEC SQL END DECLARE SECTION;
    

препроцессор DB2 не понимает выражения #define. Поэтому первым этапом
нужно выполнить оброботку препроцессором C++, затем препроцессором DB2,
а затем только откомпилировать результат. Все осложняется тем, что
компилятор от MS Visual С++ v.6.0 не понимает расширения .sqx.
в результате команда:

prep test.sqx bindfile isolation ur preprocessor "cl /P"

не может быть выполненна корректно,в той части, где при помощи
cl /P должет был бы быть получен файл test.i , в котором все макросы
#define и дерективы #include уже выполнены. Поэтому мой вам совет:
по возможности не испотзуйте макросы в секциях EXEC SQL.
Можно конечно пойти таким путем:

cl /Р test.cpp #препроцессор C++
copy test.i test.sqx #
db2 prep test.sqx bindfile isolation ur #препроцессор DB2
cl test.cxx db2api.lib #собственно компиляция

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

следующим неудобством является то, что заставить IDE от MS Visual Studio
относиться к файлам с расширением .sqx как к файлам .cpp довольно таки
трудно. Более того, каждый файл .sqx должен быть обработан препроцессором,
т.е. должно быть выполнено custom build. К счатьстью эту проблему можно
обойти. Я, например не испрользую в своих проектах .sqx файлы, а все
файлы исходников компилю следующим нехитрым .bat файлом:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
    rem =============================================
    rem Файл для компиляции исходников с embedded sql
    rem prep.bat
    rem =============================================
	@if exist % 1 .sqx @del % 1 .sqx > nul
	@if exist % 1 .obj @del % 1 .obj > nul
	@if exist % 1 .log @del % 1 .log > nul
	@if exist % 1 .cxx @del % 1 .cxx > nul
	@copy % 1 .cpp % 1 .sqx > nul
	@echo connect to SAMPLE user 'DB2ADMIN' using 'PASSSWWWDD' > % 1 .db2
	@echo prep % 1 .sqx bindfile using % 1 .bnd isolation ur >> % 1 .db2
	@echo bind % 1 .bnd blocking all queryopt  0  isolation ur grant public >> % 1 .db2
	@d:\sqllib\bin\db2clpex db2 -z % 1 .log -vf % 1 .db2
	@if not exist % 1 .bnd ( type % 1 .log; exit  1  )
	@type % 1 .log
	sqx2cpp % 1  > nul
	cl /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Fo"Debug/" /Fd"Debug/" /FD /GZ  /c % 1 .cxx
    


Рассмотрим подробнее что тут написано. первые четыре строки после
комментрариев удаляют мусор который мог бы остаться после предыдущих
компиляций. Затем создается файл с расширением sqx, и файл с расширением
.db2, который содержит скрипт обработки исходника препроцессором db2
и связывания sql с базой данных SAMPLE. Причем пакет будет создан от лица
пользователя DB2ADMIN использующего пароль PASSSWWWDD.
Комнда @d:\sqllib\bin\db2clpex db2 -z %1.log -vf %1.db2 запускает
скрипт на выполнение, а результат выполнения скрипта будет содержаться
в файле .log. Далее , если в процессе выполнения скрипта был получен
файл с расширением .bnd, то процесс связывания прошел успешо,
в противном случае возвращаем ошибку, предварительно распечатов .log
Еще одна маленькая хитрость заключена в командочке sqx2cpp.
Дело в том, что после компиляции .sqx в дерективах #line файла .cxx
будет содержаться ссылка на файл .sqx. Но первоисточником у нас-то
является .cpp. Поэтому файл sqx2cpp просто напросто патчит исходник
заменяя .sqx на .cpp. В результате, если в процессе компиляции случится
ошибка, то двойным кликом по ошибке в окне вывода вы будете перенесены
именно в то место исходного файла которое нужно.
Это текст sqx2cpp, вам нужно его просто откомприлить:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
    /////////////////////////////////////
    // sqx2cpp.cpp
    // to compile:   cl sqx2cpp.cpp
    /////////////////////////////////////

	#include <stdlib.h>
	#include <stdio.h>
	#include <windows.h>
	#include <string.h>
	#include <iostream>

	using namespace std;

	class UIException {
	public:
		UIException(char *msg) {
			cout << msg << endl;
    	}
	};

	class UIMemFile {
    	long   len;
	    HANDLE mh;
    	char*  pData;
	public:
		UIMemFile(char* fname) {
    		cout << "File:" << fname << endl;
			HANDLE hf;
  			hf=CreateFile(
        		fname,
            	GENERIC_READ|GENERIC_WRITE,
	            FILE_SHARE_READ|FILE_SHARE_WRITE,
    	        NULL,
        	    OPEN_EXISTING,
	            FILE_FLAG_SEQUENTIAL_SCAN,
    	        NULL
        	);
	        if (INVALID_HANDLE_VALUE==hf)
    	       	throw UIException("INVALID_HANDLE_VALUE");
        	
	        len=GetFileSize(hf,NULL);

    	    cout << "File size:" << len <<endl;

			mh=CreateFileMapping(hf,NULL,PAGE_READWRITE, 0 , 0 ,NULL);

	        if (NULL==mh)
    	    	throw UIException("CreateFileMapping");

	        CloseHandle(hf);
    	    pData=(char*)MapViewOfFile(mh,FILE_MAP_ALL_ACCESS, 0 , 0 , 0 );
        	if (NULL==pData)
        		throw UIException("MapViewOfFile");
	    }

    	~UIMemFile() {
    		CloseHandle(mh);
	        cout << "Closed." << endl;
    	}
	    long getlen() { return len; }
	    char& operator[] (long offset) {
    		if (offset>=len) throw UIException("Out of range");
        	return pData[offset];
	    }
    	char* operator () (long offset) {
    		if (offset>=len) throw UIException("Out of range");
	        return &pData[offset];
    	}
	};

	bool strcmpz(char* a,char *p) {
    	for (long i= 0 ;p!= 0 ;i++) {
        	if (p[i]!=a[i]) return false;
	    }
    	return true;
	} 

	char *patch;
	char *fname;
	char *pattern;

	void main(int argc,char *argv[]) {
    	if(argc!= 2 ) {
    		cout << "Usage: sqx2cpp {filename}" << endl;
	        exit( 0 );
    	}

	    patch=new char[strlen(argv[ 1 ])+ 5 ];
    	fname=new char[strlen(argv[ 1 ])+ 5 ];
	    pattern=new char[strlen(argv[ 1 ])+ 5 ];

    	sprintf(patch,"%s.cpp",argv[ 1 ]);
	    sprintf(pattern,"%s.sqx",argv[ 1 ]);
    	sprintf(fname,"%s.cxx",argv[ 1 ]);

		UIMemFile eecxxdll(fname);
    	long i;
	    long patternlen=strlen(pattern);

    	for(i= 0 ; i+patternlen<eecxxdll.getlen(); i++) {
			if (strcmpz(eecxxdll(i),pattern)) {
        		cout << "Patched at offset:" << i << endl;
	            for(long j= 0 ;patch[j]!= 0 ;j++) {
    	            eecxxdll[i+j]=patch[j];
        	    }
	        }
	    }

	    delete patch;
    	delete pattern;
	    delete fname;
	}
    


Ну вот, а теперь давайте разработкой простейшей многопоточной
программки, которая только и будет делать, что вставлять записи в
таблицу test сразу в несколько потоков. Причем по ходу дела
потоки можно будет создавать, приостанавливать и запускать снова.

Надеюсь что у вас установлена DB2 версии 8.1.

Создайте при помощи AppWizard новое приложение, я назвал его XX5.
При создании укажите что представление будет основано на классе
CFormView, и будет линковаться с использованием динамических
библиотек (Shared DLL). После создания приложения зайдите
Project->Project Settings->Category->Precompiled Headers и откажитесь от
использования предварительной компиляции заголовков. Оно и понятно,
заголовки должны быть сначала обработаны препроцессором db2.
Убедитесь что у вас правильно прописаны пути к каталогам
с файлами INCLUDE, LIB. На всякий случай проверте что в
Tools->Options->Directories->Include Files имеются
каталоги D:\SQLLIB\INCLUDE и D:\SQLLIB\TEMPLATES\INCLUDE
(у меня DB2 проинсталирована на D:\SQLLIB, у вас может быть по-другому)
а также Tools->Options->Directories-Library Files D:\SQLLIB\LIB

на закладке Project->Project Settings->Link в поле Object/Library
modules впишите имя библиотеки: db2api.lib
Теперь нужно сделать чтобы все файлы входящие в наш проект
обрабатывались препроцессором DB2. Для этого нужно зайти в установки
проекта (меню Project->Settings (Alt-F7)) для каждого файла *.cpp
на закладке General устнановить галочку в чекбоксе Always use custom
build step, после чего появится закладка Custom Build, и там в поле
Commands нужно ввести команду: prep <имя файла без расширения>
а в поле Outputs необходимо ввести путь и имя объектного файла.
В нашем случае это каталог Debug\<имяфайла>.obj. Теперь можно попытаться
откомпилить файл.


Займемся конкретным делом, а именно добавим для нашего приложения
возможность регистрации в базе данных. Создадим ресурс диалога
IDD_LOGIN, у которого будут три окна Edit для ввода имени базы данных,
имени пользователя и пароля (IDC_DATABASE,IDC_LOGIN,IDC_PASSWORD).
В класс приложения CXX5App добавим переменные для регистрации,
и собственно процедуру регистрации - connect()

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	class CXX5App : public CWinApp
	{
	public:
		bool connect();
		char dbpassword[ 12 ];
		char dbuser[ 12 ];
		char dbname[ 12 ];
		CXX5App();
		.
	    .
    	.
    

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
	bool CXX5App::connect()
	{
		EXEC SQL BEGIN DECLARE SECTION;
		char (*pDb)[ 12 ];
		char (*pUser)[ 12 ];
		char (*pPwd)[ 12 ];
		EXEC SQL END DECLARE SECTION;
		pDb=(char(*)[ 12 ])this->dbname;
		pUser=(char(*)[ 12 ])this->dbuser;
		pPwd=(char(*)[ 12 ])this->dbpassword;
		EXEC SQL CONNECT TO :pDb USER :pUser USING :pPwd;
		if (SQLCODE) return false;
		return true;
	}
    
На обработчик кнопки [ОК] навесим такую функцию:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    void CLogin::OnOK() 
	{
		// TODO: Add extra validation here
		CXX5App* pApp=(CXX5App*) ::AfxGetApp();

		GetDlgItem(IDC_DATABASE)->GetWindowText(pApp->dbname,sizeof(pApp->dbname));
		GetDlgItem(IDC_LOGIN)->GetWindowText(pApp->dbuser,sizeof(pApp->dbuser));
		GetDlgItem(IDC_PASSWORD)->GetWindowText(pApp->dbpassword,sizeof(pApp->dbpassword));
		if (pApp->connect()) {
			CDialog::OnOK();
		}
	}
    
Код приведенный выше можно упростить, например таким образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
	class CXX5App : public CWinApp
	{
	public:
		bool connect();
        EXEC SQL BEGIN DECLARE SECTION;
			char dbpassword[ 12 ];
			char dbuser[ 12 ];
			char dbname[ 12 ];
		EXEC SQL END DECLARE SECTION;
		CXX5App();
		.
	    .
    	.
    

И сообтестственно файл реализации

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    EXEC SQL INCLUDE SQLCA;
	bool CXX5App::connect()
	{
		EXEC SQL CONNECT TO :dbname USER :dbuser USING :dbpassword;
		if (SQLCODE) return false;
		return true;
	}
    

Но в связи с тем, что препроцессором должны быть обработаны и *.h файлы
нужно правильно включить их в файл реализации. Я делаю это таким образом:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
    EXEC SQL INCLUDE 'stdafx.h';
    #include "stdafx.h"

    EXEC SQL INCLUDE 'TT.h';
	#include "TT.h"

    EXEC SQL INCLUDE 'XX5.h';
	#include "XX5.h"

    EXEC SQL INCLUDE 'XX5Doc.h';
	#include "XX5Doc.h"

    EXEC SQL INCLUDE 'XX5View.h';
	#include "XX5View.h"
    

Почему я так делаю? Строки вида EXEC SQL INCLUDE 'stdafx.h'; - собственно
выражение, которое будет обработано препроцессором DB2. А вторая
строчка #include "stdafx.h" нужна исключительно для IDE, чтобы
визуальная среда "видела" содержание и структуру заголовочного файла,
т.к. выражения вида EXEC SQL INCLUDE не распознаются IDE. А так как
внутренности заголовочных файлов защищены директивами #ifdef #define #endif
компиляция всегда бедет проходить без ошибок.
Аналогичным образом, пусть мы получили структуру таблицы из нашей базы
данных при помощи команды db2dclgn.exe (кстати - очень удобная штучка,
рекомендую к использованию) резельтатом выполнения которой является
заголовочный файл, содержащий структуру требуемой таблицы в формате C++

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
    //file:account.h
	struct
	{
	  sqlint32 stuff;
	  sqlint32 account;
	  char closed[ 11 ];
	  char type[ 2 ];
	  double overdraft;
	  double active;
	  double passive;
	  double debet;
	  double credit;
	  sqlint32 dcnt;
	  sqlint32 ccnt;
	} account;
    

В другом заголовочном файле мы можем сделать следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
    class CMyClass {
    public:
    	EXEC SQL BEGIN DECLARE SECTION;
        EXEC SQL INCLUDE 'account.h';   //Для препроцессора DB2
        #include "account.h"			//Для среды IDE
        EXEC SQL END DECLARE SECTION;
    .
    .
    .
    

Да, и еще одна деталь. Как правило во всех файлах использующих
embedded sql необходимо использование структуры sqlca, поэтому
я можифицирую файл stdafx.h добавив в него всего две строчки:

Код: plaintext
1.
2.
	#include <Afxmt.h>		//Реализация многопоточности
	#include <sqlenv.h>		//декларация sqlca и пр.
	


Что будет делать наше многопоточное приложение?
Пусть добавляет в таблицу test записи. структура таблицы test
будет очень простой, причем для генирации значений исполизуем
SEQUENCE. Вот скрипт, который создаст необходимые объекты
в базе данных:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
     [i]---------------------------------------------------------------
 
     --ttt.sql
 
	 --Cкрип выполняется командой:
 
	 --d:\SQLLIB\BIN\db2clpex.exe db2 -z ttt.log -v -td@ -f ttt.sql
 
     ---------------------------------------------------------------
 
	CONNECT TO SAMPLE USER db2admin USING 'ibmdb2'@
    CREATE TABLE TEST (
    	ID INTEGER NOT NULL,
        NAME CHAR( 35 ),
        CONSTRAINT AtID_PK PRIMARY KEY (ID)
    )@
	CREATE SEQUENCE S_TEST
		AS INTEGER
		START WITH  0 
    	INCREMENT BY  1 
	    NOMINVALUE
    	NOMAXVALUE
	    NO CYCLE
		CACHE  1000 
	@
	

Отредактикуем представление IDD_XX5_FORM, добавим поле Edit (IDC_CNT),
и четыре кнопки - Start Thread,Suspend,Resume,Terminate (IDC_START,
IDC_SUSPEND_THREAD,IDC_RESUME,IDC_TERMINATE) Причем кнопки
Suspend,Resume,Terminate по умалчанию сделаем disabled.
Каждое запущенное окно будет соответствовать одному потоку.
В процессе выполнения поток будет обновлять текст элемета
управления IDC_CNT, показывающего количство записей, добавленнх
текущим потоком. Собственно поток реализуется на базе класса
CWinThread:
class CTT: public CWinThread {...}, и полный его текст приведен
в конце статьи

А пока назначим действия на кнопки:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
	void CXX5View::OnStart() 
	{
		// TODO: Add your control notification handler code here
		pTT=new CTT(this);
		pTT->CreateThread();
		GetDlgItem(IDC_START)->EnableWindow(FALSE);
		GetDlgItem(IDC_SUSPEND)->EnableWindow(TRUE);
		GetDlgItem(IDC_RESUME)->EnableWindow(FALSE);
		GetDlgItem(IDC_TERMINATE)->EnableWindow(TRUE);
	}
    ...
	void CXX5View::OnSuspend()
	{
		// TODO: Add your control notification handler code here
		if (pTT!=NULL) {
			(pTT->pSection)->Lock();
			pTT->SuspendThread();
			GetDlgItem(IDC_SUSPEND)->EnableWindow(FALSE);
			GetDlgItem(IDC_RESUME)->EnableWindow(TRUE);
			GetDlgItem(IDC_TERMINATE)->EnableWindow(TRUE);
			(pTT->pSection)->Unlock();
		}
	}
    ...
	void CXX5View::OnResume()
	{
		// TODO: Add your control notification handler code here
		pTT->ResumeThread();
		GetDlgItem(IDC_SUSPEND)->EnableWindow(TRUE);
		GetDlgItem(IDC_RESUME)->EnableWindow(FALSE);
		GetDlgItem(IDC_TERMINATE)->EnableWindow(TRUE);
	}

	BOOL CXX5View::DestroyWindow() 
	{
		MessageBox("Terminate thread on Destroy");
		// TODO: Add your specialized code here and/or call the base class
		if (pTT!=NULL) {
			while (!(pTT->pSection)->Lock()) {}
			pTT->SuspendThread();
			TerminateThread(pTT->m_hThread, 0 );
			(pTT->pSection)->Unlock();
			delete pTT;
			pTT=NULL;
		}
		return CFormView::DestroyWindow();
	}
    ...
	void CXX5View::OnTerminate()
	{
		// TODO: Add your control notification handler code here
		if (pTT==NULL) return;
		while (!(pTT->pSection)->Lock()){};
		::TerminateThread(pTT->m_hThread, 0 );	
		GetDlgItem(IDC_START)->EnableWindow(TRUE);
		GetDlgItem(IDC_SUSPEND)->EnableWindow(FALSE);
		GetDlgItem(IDC_RESUME)->EnableWindow(FALSE);
		GetDlgItem(IDC_TERMINATE)->EnableWindow(FALSE);
		(pTT->pSection)->Unlock();
		delete pTT;
		pTT=NULL;
	}
    ...


    

Класс, реализующий поток:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
	#if !defined(AFX_TT_H__BC791288_2AD1_48C5_AFE3_39CDB95AB411__INCLUDED_)
	#define AFX_TT_H__BC791288_2AD1_48C5_AFE3_39CDB95AB411__INCLUDED_

	#if _MSC_VER >  1000 
	#pragma once
	#endif // _MSC_VER >  1000 
	// TT.h : header file
	//



	/////////////////////////////////////////////////////////////////////////////
	// CTT thread

	class CTT : public CWinThread
	{
		DECLARE_DYNCREATE(CTT)
	protected:
		CTT();           // protected constructor used by dynamic creation
	// Attributes
	public:
		CTT(CFormView *pV){
			pView=pV;
			pSection=new CCriticalSection;
		}
		CFormView *pView;
		CCriticalSection *pSection;
		void **ppCtx;
		struct sqlca sqlca;
	// Operations
		public:

	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CTT)
	public:
		virtual BOOL InitInstance();
		virtual int ExitInstance();
		virtual int Run();
	//}}AFX_VIRTUAL

	// Implementation
	protected:
	public:
		virtual ~CTT();

		// Generated message map functions
		//{{AFX_CTT
			// NOTE - the ClassWizard will add and remove member functions here.
		//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
	};

	/////////////////////////////////////////////////////////////////////////////

	//{{AFX_INSERT_LOCATION}}
	// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

	#endif // !defined(AFX_TT_H__BC791288_2AD1_48C5_AFE3_39CDB95AB411__INCLUDED_)
    

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
	// TT.cpp : implementation file
	//

	#include "stdafx.h"
	#include "TT.h"
	#include "XX5.h"

	#include "XX5Doc.h"
	#include "XX5View.h"

	#ifdef _DEBUG
	#define new DEBUG_NEW
	#undef THIS_FILE
	static char THIS_FILE[] = __FILE__;
	#endif

	/////////////////////////////////////////////////////////////////////////////
	// CTT

	IMPLEMENT_DYNCREATE(CTT, CWinThread)

	CTT::CTT()
	{
		ppCtx=(void**)new char[ 2048 ];
	}

	CTT::~CTT()
	{
		delete pSection;
	}

	BOOL CTT::InitInstance()
	{
		// TODO:  perform and per-thread initialization here
		return TRUE;
	}

	int CTT::ExitInstance()
	{
		// TODO:  perform any per-thread cleanup here
		return CWinThread::ExitInstance();
	}

	BEGIN_MESSAGE_MAP(CTT, CWinThread)
		//{{AFX_MSG_MAP(CTT)
			// NOTE - the ClassWizard will add and remove mapping macros here.
		//}}AFX_MSG_MAP
	END_MESSAGE_MAP()

	/////////////////////////////////////////////////////////////////////////////
	// CTT message handlers

	int CTT::Run() 
	{
		// TODO: Add your specialized code here and/or call the base class
        // -----------------------------------------------------------
 
        //Установим минимальный приоритет потока, в противном случае
        //от сожрет все ресурсы системы так, что мы даже на экране
        //ничего не увидим
        // -----------------------------------------------------------
 
		this->SetThreadPriority(THREAD_PRIORITY_IDLE);
		// -----------------------------------------------------------
 
        //Здесь будет выделена память под контекст
        //потока команд DB2. Почему-то что и сколько выделять 
        //не описано в документации. Я выделил наобум. Прокатило
        //Запускал одновременно до  50  потоков. Все работает.
        // -----------------------------------------------------------
 
		ppCtx=(void **) new char[ 1024 ]; //Буфер под контекст
		char buf[ 15 ];					//Бувер для форматирования
		long i= 0 ;						//Кол-во добавленных записей

		// --------------------------------------------------------------
 
        //Получаем контекст, сразу же присоединив его к текущему потоку
        // --------------------------------------------------------------
 
		i=sqleBeginCtx(ppCtx,SQL_CTX_BEGIN_ALL,NULL,&sqlca);
		sprintf(buf,"%d",i);
		(((CXX5View*)pView)->GetDlgItem(IDC_CNT))->SetWindowText(buf);

		// ----------------------------
 
    	//Собственно выполнение потока
        // ----------------------------	
 
		while (true) {
			i++;
			sprintf(buf,"%d",i);
            // -------------------------------------------------
 
            //Вывод информации о количестве добавленных записей
            // -------------------------------------------------
 
			(((CXX5View*)pView)->GetDlgItem(IDC_CNT))->SetWindowText(buf);

            // --------------------------------
 
            //Добавление записи в таблицу test
            // --------------------------------
 
			EXEC SQL INSERT INTO TEST (id,Name)
            	VALUES (NEXTVAL FOR S_TEST,CURRENT TIMESTAMP);

            // ---------------------------------------
 
            //В случае ошибки прерываем работу цикла
            // ---------------------------------------
 
			if (SQLCODE) {
				EXEC SQL ROLLBACK WORK;
				break;
			} else {
				EXEC SQL COMMIT WORK;
			}
            // ------------------------------------------
 
            //Каждая нить будет генерировать  1000  значений
            //Если у вас есть желание, то можете задавать кол-во
            //в поле IDC_CNT
            // ------------------------------------------
 
			if (i> 1000 ) break;
		}
        // ---------------------------------------------
 
		//После того, как нить отработала отсоединяем 
        //контекст от базы данных и убиваем его
        // ---------------------------------------------
 
		EXEC SQL CONNECT RESET;
		i=sqleEndCtx(ppCtx,SQL_CTX_END_ALL,NULL,&sqlca);
		sprintf(buf,"%d",i);
		(((CXX5View*)pView)->GetDlgItem(IDC_CNT))->SetWindowText(buf);
		while(!pSection->Lock()){};
		(((CXX5View*)pView)->pTT)=NULL;
		pSection->Unlock();
		::ExitThread( 0 );
		return CWinThread::Run();
	}

    

Вообще я не являюсь большим специалистом по написанию многопоточных
соединений, и показанный здесь пример уж очень простой. К сожалению
в тех задачах, которые решаю я, многопоточность не нужна.
Однако главная идея, как это все использовать понятна. Более того,
реализуется эта техника очень просто. Если кто захочет получить
приведенный здесь в качестве примера проект в исходниках, обращайтесь
ко мне по адресу g a r d e n m a n @ y a n d e x . r u
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33005777
Lepsik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по просьбе Gardenman присоединил файлик
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33005779
Lepsik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
еще одна попытка, после превью файл не присоединяется
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33007472
Фотография Ggg_old
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот буквально пару дней назад хотел поднять топик про EmbedSQL, про то , кто и в каких случаях его использует, и в каких случаях нужно применять его, а не ООП библиотеки.
Прочитав этот топик, становится абсолютно непонятно, зачем так страдать,
когда можно написать:
TDatabase...
TQuery...
TResultSet...

Тем не менее, я думаю, что отдельный топик по EmbedSQL стоит завести. Вот только в какой ветке ворума? Может в "Сравнение СУБД"?.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33007582
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтож, в сравнениях можно поднять. Можно глянуть у кого код проще получается. Хотя это уже поднималось.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33007652
Фотография Ggg_old
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2gardenman:
Договорились. Кто будет создавать? Я вопросом EmbedSQL не владею на практике. Вам, я думаю сормулировать тему получится лучше. Ну и ссылка на этот топик, что бы была.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33009271
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman
можно добавить только ссылку на db2mag, где поясняеться как и почему появились пакеты, и почему еще используються.
Ну и ежели MQ добавить для стягивания "длинных" репортов посредством, например, publish/subscribe, да еще и QP навесить, то получим архитектуру приближенную к идеалу :)

PS
Понятия "контекста" в ESQL появилось недавно, а до этого приходилось писать multithreaded на CLI, но позже я все мигрировал на ESQL.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33009347
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 ggv
Тут прикол еще вот в чем. Понятие контекста по ходу дела менялось. Даже в 8 версии. Когда я писал этот пример - при порождении контекста создавалась новая сессия. И следовательно, транзакция в этом новом контексте контексте была независимой. (Делая list applications я видел несколько сооединений) А теперь понятие контекста (как я полагаю) существенно изменилось. Я экспериментировал с этим недавно. У меня получилось так, что транзакция на все контексты - одна. Т.е. в транзакции можно распараллелить несколько операций:
Типа
Порождаем нить 1, породжаем контекс для нити 1, выполняем SQL
Порождаем нить 2, породжаем контекс для нити 2, выполняем SQL
...
Порождаем нить N, породжаем контекс для нити N, выполняем SQL
Ждем завершения всех нитей - проверяем что все выполнилось ОК
делаем один COMMIT или ROLLBACK сразу для всех нитей.
Т.е. получили многопоточную транзакцию.

С использованием CLI у нас каждый поток - у нас несколько независимых соединений, а следовательно и несколько независимых транзакций. Хотя порождать в этом случае отдельные потоки не нужно. А просто смешивая CLI и ESQL можно просто переключаться между соединениями и таким образом "эмулировать" автономные транзакции.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33009371
Lepsik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для MSSQL предупреждение :

Код: plaintext
1.
While the ESQL/C API is still supported in Microsoft SQL Server  2000 , no future versions of SQL Server will include the files needed to do programming work on applications that use this API. Connections from existing applications written using ESQL/C will still be supported in the next version of SQL Server, but this support will also be dropped in a future release. When writing new applications, avoid using ESQL/C. When modifying existing applications, you are strongly encouraged to remove dependencies on ESQL/C. Instead of ESQL/C, you can use Microsoft ActiveX® Data Objects (ADO), OLE DB, or ODBC to access data in SQL Server.

А как у DB2 c этим будет обстоять ?
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33009887
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Lepsik
Мда... серьезные у MS намерения...
Я думаю что IBM вряд-ли когда-либо поступит так же. Больно уж серьезно это все встроено в ядро.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010067
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman - вот этого я не видел, щас буду пробовать.
Когда я с многопоточным приложением возился, контекст был полноценным независимым коннектом.
Тогда 8.2 еще небыло.

Я сильно разочаруюсь в IBM, если убъют ESQL.....
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010085
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 ggv Щас я тебе примерчики выложу, на которых я экспериментировал..
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010106
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот, смотри приложенный архив, может я в чем-то ошибся, но не думаю...
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010169
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman - не обещаю что прям щас, но постараюсь в течении дня-двух разобраться.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010176
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
о как, это в добавок ко всему еще и С++ :)
Я уж как-нибудь по старинке, на С-ях :)
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33010202
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне интересно как будет многопоточное приложение работать с временной таблицей. Т.е. возможно ли для каждой нити создать свою GTT - оказалось - нет. Типа получилось что коннект один. Ну и - вобщем получилась параллельная (многопоточная) транзакция
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33024376
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman -
ну на сегодня я многого не достиг (не очень много времени, какие-то непонятки с DB2 DWE for linux, также с WebSphere App Serv & DB2 Alphablox и всё под linux)
но вот сейчас глянул доку
раздел
http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0006107.htm
особенно подраздел recomendations
http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/ad/c0006108.htm
ну и также
http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/admin/r0001917.htm

мне показалось, что в концепции контекста ничего не изменилось....
Ежели я только внимательно читал.
сегодня постараюсь скомпилить и проверить
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33024633
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
почитал, однако как объяснить то, что я получаю? Может я где-то ошибся в коде? Конечно код, который я привел - сделан слегка тяп-ляп, но я не думаю что я там слишком сисльно напортачил.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33030296
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
http://publib.boulder.ibm.com/infocenter/db2help/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0005841.htm

gardenman, продолжать, или это оно и есть?

У меня, правда, уже материал на статью получился, что-то типа "HOWTO DB2 Multithread Programmin with ESQL and Context."
Можно и закончить ее, у можно и забить.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33030310
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman -- oops, у тебя это используеться.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33031068
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Написать статью - это хорошо... правда не знаю будет ли она востребована...
А то вот я смотрю кроме меня нихто DB2 не любит
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33031621
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman - а я??????
на выходных вот закончу с context (если ничем не загрузят дома), а затем можно в виде howto оформить.
Правда, восстребованость будет минимальная - J2EE наш рулевой на обозримую перспективу.
Так что надо почитать будет про SQLJ :)
Может, сравнение какое оформиться.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33032969
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman - ну всё работает как и документировано.
Если я правильно понимаю, чего я натворил, и суть вопроса.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33033028
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стоп!

Все же скажи такую конкретную вещь (предлагаю 2 варианта)

1) Каждый контекст работает в своей транзакции (и, как следствие, откат в любой нити - независим от других нитей, т.е. все контексты - независимы)
2) Все контексты работают в одной транзакции, и => откат в одной нити откатывает все изменения в других нитях.

Если тебе не трудно, выложи исходники, я глянуть хочу...
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33033088
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
ну поскольку я так и не выяснил, на каких таких правах я могу публиковать код, и поскольку мне тут же посоветовали провести "событие" для бизнес партнеров, проще сказали будет послать код персонально на мыло. Что я и сделаю.
Щас вот только еще одну фигню проверю (самому интересно) и пошлю.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33041228
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
gardenman - Ну? Что?
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33041308
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
еще не смотрел, наверное на выходных займусь...
мне дома на линукса DB2 установить надо, чтоб все посмотреть...
так что - ток после праздников...
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33041336
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
да ладно, не растраивайся так :)
Если бы меня от С++ не воротило, я бы в твоих файлах разобрался...
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627660
Фотография Apex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кхе-кхе, простите, уважаемый gardenman, я так понимаю, что все описанное вами относится исключительно к DB2? Если нет, то я бы поспорил с некоторыми пунктами...
Но сейчас не об этом, вот это фраза меня очень удивила:
авторВ результате
на сервере в конце концов появляются хранимые процедуры длинной
в несколько листов и которые выполняются не 1-2 секунды,
а по нескольку минут, или даже нескольку дисятков минут.
Причем в этот момент невозможно точно отследить что делает
такая процедура. Может она зависла?
А снять трейс? Или у DB2 нет такой возможности?
Тоже самое касается отладки, отдалчика (debuger) у нее тоже?
-------------------------------------------------------
Автор благодарит алфавит за любезно предоставленные ему буквы.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627685
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ApexКхе-кхе, простите, уважаемый gardenman, я так понимаю, что все описанное вами относится исключительно к DB2? Если нет, то я бы поспорил с некоторыми пунктами...
Но сейчас не об этом, вот это фраза меня очень удивила:
авторВ результате
на сервере в конце концов появляются хранимые процедуры длинной
в несколько листов и которые выполняются не 1-2 секунды,
а по нескольку минут, или даже нескольку дисятков минут.
Причем в этот момент невозможно точно отследить что делает
такая процедура. Может она зависла?
А снять трейс? Или у DB2 нет такой возможности?
Тоже самое касается отладки, отдалчика (debuger) у нее тоже?
-------------------------------------------------------
Автор благодарит алфавит за любезно предоставленные ему буквы.

Вышесказанное относилось к Sybase ASE - самой отвратительной базе данных и ее близкому родственнику MS SQL Server
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627751
Фотография Apex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenman
Вышесказанное относилось к Sybase ASE - самой отвратительной базе данных и ее близкому родственнику MS SQL Server
Вы не поняли, я про этот пост :)
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627801
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это - да. Но многое уже изменилось. Сейчас никого не затащишь в MFC программить. теперь популярен .Net. Принципе можно поюзать managed С++.
А к чему вообще вопрос-то?
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627875
Фотография Apex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanЭто - да. Но многое уже изменилось. Сейчас никого не затащишь в MFC программить. теперь популярен .Net. Принципе можно поюзать managed С++.
А к чему вообще вопрос-то?
Да мне на этот .Net честно говоря, с высокой горки:))
Вопрос-то собственно к этому:
дубль два
gardenman

В результате
на сервере в конце концов появляются хранимые процедуры длинной
в несколько листов и которые выполняются не 1-2 секунды,
а по нескольку минут, или даже нескольку дисятков минут.
Причем в этот момент невозможно точно отследить что делает
такая процедура. Может она зависла?


А снять трейс? Или у DB2 нет такой возможности?
Тоже самое касается отладки, отдалчика (debuger) у нее тоже?

Трейсить серверные процессы можно или нет?
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627894
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть отладчик хранимых процедур. (имеются в виду только SQL процедуры и написанные на Java) Я Java не занимался и нет желания. А также смотрите Event и Snapshot мониторы.
Отладчик доступен из СС.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #33627995
Фотография Apex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenmanЕсть отладчик хранимых процедур. (имеются в виду только SQL процедуры и написанные на Java) Я Java не занимался и нет желания. А также смотрите Event и Snapshot мониторы.
Отладчик доступен из СС.
OK. Thanks
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #34123956
fedotxxl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторНасколько я понял, embedded sql пока что не позволяет обрабатывать
recordsets которые возвращаются из сохраненных процедур. Но без
этого можно запросто обойтись. Например записать recordset во
временную таблицу.
Можно пример такого кода? Который бы записывал во временную таблицу?
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #34124072
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
смотрите

CREATE GLOBAL TEMPORARY TABLE SESSION.TTT ...
INSERT INTO SESSION.TTT SELECT ....

или

INSERT INTO SESSION.TTT
WITH .....
SELECT ....

Можно одним селектом заполнить сразу кучу таблиц сделать кучу апдейтов и делетов.
...
Рейтинг: 0 / 0
Embedded SQL & MFC HOWTO
    #34124080
Фотография NewYear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
позволяет.
recordsets я понял cursor with return?
...
Рейтинг: 0 / 0
38 сообщений из 38, показаны все 2 страниц
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Embedded SQL & MFC HOWTO
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]