1 // vi: noexpandtab:tabstop=4
2 /*
3 	Author: Sergey Sikorskiy (www.sikorskiy.net)
4 	License: BSD
5 */
6 
7 #include "fb.h"
8 
9 #ifdef PLATFORM_WIN32
10 	#define DLLFILENAME "fbclient.dll"
11 	#define DLLCALL     __stdcall
12 #else
13 	#define DLLFILENAME "libfbclient.so"
14 #endif
15 #define DLIMODULE   FB
16 #define DLIHEADER   <Firebird/Firebird.dli>
17 #include <Core/dli_source.h>
18 
19 // Development-time comments ...
20 
21 
22 // Conversions ...
23 // void        ISC_EXPORT isc_decode_date (ISC_QUAD ISC_FAR *,
24 //                     void ISC_FAR *);
25 //
26 // void        ISC_EXPORT isc_decode_sql_date (ISC_DATE ISC_FAR *,
27 //                     void ISC_FAR *);
28 //
29 // void        ISC_EXPORT isc_decode_sql_time (ISC_TIME ISC_FAR *,
30 //                     void ISC_FAR *);
31 //
32 // void        ISC_EXPORT isc_decode_timestamp (ISC_TIMESTAMP ISC_FAR *,
33 //                     void ISC_FAR *);
34 //
35 // void        ISC_EXPORT isc_encode_date (void ISC_FAR *,
36 //                     ISC_QUAD ISC_FAR *);
37 //
38 // void        ISC_EXPORT isc_encode_sql_date (void ISC_FAR *,
39 //                     ISC_DATE ISC_FAR *);
40 //
41 // void        ISC_EXPORT isc_encode_sql_time (void ISC_FAR *,
42 //                     ISC_TIME ISC_FAR *);
43 //
44 // void        ISC_EXPORT isc_encode_timestamp (void ISC_FAR *,
45 //                     ISC_TIMESTAMP ISC_FAR *);
46 //
47 // ISC_STATUS  ISC_EXPORT isc_dsql_finish (isc_db_handle ISC_FAR *);
48 //
49 // ISC_STATUS  ISC_EXPORT isc_dsql_insert (ISC_STATUS ISC_FAR *,
50 //                        isc_stmt_handle ISC_FAR *,
51 //                        unsigned short,
52 //                        XSQLDA ISC_FAR *);
53 //
54 
55 
56 // Print ...
57 // void        ISC_EXPORT isc_print_sqlerror (short,
58 //                        ISC_STATUS ISC_FAR *);
59 //
60 // ISC_STATUS  ISC_EXPORT isc_print_status (ISC_STATUS ISC_FAR *);
61 //
62 
63 
64 
65 // Not supported ...
66 
67 
68 // The isc_create_database ( ) method is not currently supported
69 // from user applications. is for internal use only.
70 // ISC_STATUS  ISC_EXPORT isc_create_database (ISC_STATUS ISC_FAR *,
71 //                         short,
72 //                         char ISC_FAR *,
73 //                         isc_db_handle ISC_FAR *,
74 //                         short,
75 //                         char ISC_FAR *,
76 //                         short);
77 
78 
79 // Not documented ...
80 
81 // void        ISC_EXPORT isc_sql_interprete (short,
82 //                        char ISC_FAR *,
83 //                        short);
84 //
85 // ISC_LONG    ISC_EXPORT isc_vax_integer (char ISC_FAR *,
86 //                     short);
87 //
88 // ISC_INT64   ISC_EXPORT isc_portable_integer  (unsigned char ISC_FAR *,
89 //                                               short);
90 // ISC_STATUS  ISC_EXPORT isc_compile_request (ISC_STATUS ISC_FAR *,
91 //                         isc_db_handle ISC_FAR *,
92 //                         isc_req_handle ISC_FAR *,
93 //                         short,
94 //                         char ISC_FAR *);
95 //
96 // ISC_STATUS  ISC_EXPORT isc_compile_request2 (ISC_STATUS ISC_FAR *,
97 //                          isc_db_handle ISC_FAR *,
98 //                          isc_req_handle ISC_FAR *,
99 //                          short,
100 //                          char ISC_FAR *);
101 //
102 // ISC_STATUS  ISC_EXPORT isc_ddl (ISC_STATUS ISC_FAR *,
103 //                     isc_db_handle ISC_FAR *,
104 //                     isc_tr_handle ISC_FAR *,
105 //                     short,
106 //                     char ISC_FAR *);
107 //
108 // ISC_STATUS  ISC_EXPORT isc_receive (ISC_STATUS ISC_FAR *,
109 //                     isc_req_handle ISC_FAR *,
110 //                     short,
111 //                     short,
112 //                     void ISC_FAR *,
113 //                     short);
114 //
115 // ISC_STATUS  ISC_EXPORT isc_release_request (ISC_STATUS ISC_FAR *,
116 //                         isc_req_handle ISC_FAR *);
117 //
118 // ISC_STATUS  ISC_EXPORT isc_request_info (ISC_STATUS ISC_FAR *,
119 //                      isc_req_handle ISC_FAR *,
120 //                      short,
121 //                      short,
122 //                      char ISC_FAR *,
123 //                      short,
124 //                      char ISC_FAR *);
125 //
126 // ISC_STATUS  ISC_EXPORT isc_send (ISC_STATUS ISC_FAR *,
127 //                  isc_req_handle ISC_FAR *,
128 //                  short,
129 //                  short,
130 //                  void ISC_FAR *,
131 //                  short);
132 //
133 // ISC_STATUS  ISC_EXPORT isc_start_and_send (ISC_STATUS ISC_FAR *,
134 //                        isc_req_handle ISC_FAR *,
135 //                        isc_tr_handle ISC_FAR *,
136 //                        short,
137 //                        short,
138 //                        void ISC_FAR *,
139 //                        short);
140 //
141 // ISC_STATUS  ISC_EXPORT isc_start_request (ISC_STATUS ISC_FAR *,
142 //                       isc_req_handle ISC_FAR *,
143 //                       isc_tr_handle ISC_FAR *,
144 //                       short);
145 //
146 // ISC_STATUS  ISC_EXPORT isc_unwind_request (ISC_STATUS ISC_FAR *,
147 //                        isc_tr_handle ISC_FAR *,
148 //                        short);
149 //
150 // ISC_STATUS  ISC_EXPORT isc_close (ISC_STATUS ISC_FAR *,
151 //                   char ISC_FAR *);
152 //
153 // ISC_STATUS  ISC_EXPORT isc_declare (ISC_STATUS ISC_FAR *,
154 //                     char ISC_FAR *,
155 //                     char ISC_FAR *);
156 //
157 // ISC_STATUS  ISC_EXPORT isc_describe (ISC_STATUS ISC_FAR *,
158 //                     char ISC_FAR *,
159 //                     XSQLDA ISC_FAR *);
160 //
161 // ISC_STATUS  ISC_EXPORT isc_describe_bind (ISC_STATUS ISC_FAR *,
162 //                       char ISC_FAR *,
163 //                       XSQLDA ISC_FAR *);
164 //
165 // ISC_STATUS  ISC_EXPORT isc_open (ISC_STATUS ISC_FAR *,
166 //                  isc_tr_handle ISC_FAR *,
167 //                  char ISC_FAR *,
168 //                  XSQLDA ISC_FAR *);
169 //
170 // ISC_STATUS  ISC_EXPORT isc_dsql_release (ISC_STATUS ISC_FAR *,
171 //                      char ISC_FAR *);
172 //
173 // ISC_LONG    ISC_EXPORT isc_ftof (char ISC_FAR *,
174 //                  unsigned short,
175 //                  char ISC_FAR *,
176 //                  unsigned short);
177 //
178 // ISC_STATUS  ISC_EXPORT isc_print_blr (char ISC_FAR *,
179 //                       isc_callback,
180 //                       void ISC_FAR *,
181 //                       short);
182 //
183 // void        ISC_EXPORT isc_set_debug (int);
184 //
185 // void        ISC_EXPORT isc_qtoq (ISC_QUAD ISC_FAR *,
186 //                  ISC_QUAD ISC_FAR *);
187 //
188 // void        ISC_EXPORT isc_vtof (char ISC_FAR *,
189 //                  char ISC_FAR *,
190 //                  unsigned short);
191 //
192 // void        ISC_EXPORT isc_vtov (char ISC_FAR *,
193 //                  char ISC_FAR *,
194 //                  short);
195 //
196 // ISC_LONG    ISC_EXPORT isc_reset_fpe (unsigned short);
197 
198 
199 
200 
201 
202 
203 
204 
205 namespace ibpp
206 {
207 	///////////////////////////////////////////////////////////////////////////
208 	///////////////////////////////////////////////////////////////////////////
209 	long
getSQLCode()210 	Error::getSQLCode()
211 	{
212 		sqlCode_ = dll.isc_sqlcode(status_vector_);
213 		if (sqlCode_ == 999)
214 		{
215 			sqlCode_ = 0;
216 		}
217 		return sqlCode_;
218 	}
219 
220 	String
getErrorText()221 	Error::getErrorText()
222 	{
223 		// isc_sql_interprete(sqlCode_, msg_, sizeof(msg_));
224 		// return msg_;
225 
226 		String errStr;
227 
228 #if 0
229 		ISC_STATUS* pVector = status_vector_;
230 		dll.isc_interprete(msg_, &pVector);
231 		errStr += msg_;
232 		while (dll.isc_interprete(msg_, &pVector))
233 		{
234 			errStr += "; ";
235 			errStr += msg_;
236 		}
237 #else
238 		const ISC_STATUS* pVector = status_vector_;
239 		dll.fb_interpret(msg_, sizeof(msg_), &pVector);
240 		errStr += msg_;
241 		while (dll.fb_interpret(msg_, sizeof(msg_), &pVector))
242 		{
243 			errStr += "; ";
244 			errStr += msg_;
245 		}
246 #endif
247 
248 		return errStr;
249 	}
250 
251 	void
check()252 	Error::check()
253 	{
254 		// static char already_exists[] = "already exists";
255 		// static char duplicate_value[] = "duplicate value";
256 
257 		if (status_vector_[0] == 1 && status_vector_[1])
258 		{
259 			String err_str = getErrorText();
260 
261 			// if (!info_str.empty())
262 			// {
263 			//     err_str += " ";
264 			//     err_str += info_str;
265 			// }
266 
267 			long error_code = getSQLCode();
268 
269 			throw DbExc(err_str, error_code);
270 		}
271 	}
272 
273 	///////////////////////////////////////////////////////////////////////////
dpb()274 	dpb::dpb() :
275 			pos_(0)
276 	{
277 		memset(buff_, 0, sizeof(buff_));
278 	}
279 
280 	void
addParam(char value)281 	dpb::addParam(char value)
282 	{
283 		ASSERT(sizeof(pos_) < sizeof(buff_));
284 		buff_[pos_++] = value;
285 	}
286 
287 	void
addCluster(char type,const char * value)288 	dpb::addCluster(char type, const char* value)
289 	{
290 		short len = value ? (short)strlen(value) : 0;
291 
292 		ASSERT(sizeof(pos_ + 2 + len - 1) < sizeof(buff_));
293 		buff_[pos_++] = type;
294 		buff_[pos_++] = char(len);
295 //         strncpy(&buff_[pos_], value, len);
296 		memcpy(&buff_[pos_], value, len);
297 		pos_ += len;
298 	}
299 
300 	void
addCluster(char type,short value)301 	dpb::addCluster(char type, short value)
302 	{
303 		ASSERT(sizeof(pos_ + 4 - 1) < sizeof(buff_));
304 		buff_[pos_++] = type;
305 		buff_[pos_++] = char(2);
306 		*(short*)&buff_[pos_] = value;
307 		pos_ += short(2);
308 	}
309 
310 	void
addCluster(char type,bool value)311 	dpb::addCluster(char type, bool value)
312 	{
313 		ASSERT(sizeof(pos_ + 3 - 1) < sizeof(buff_));
314 		buff_[pos_++] = type;
315 		buff_[pos_++] = char(1);
316 		buff_[pos_++] = char(value ? 1 : 0);
317 	}
318 
319 	void
addCluster(char type,char value)320 	dpb::addCluster(char type, char value)
321 	{
322 		ASSERT(sizeof(pos_ + 3 - 1) < sizeof(buff_));
323 		buff_[pos_++] = type;
324 		buff_[pos_++] = char(1);
325 		buff_[pos_++] = value;
326 	}
327 
328 	void
addCluster(char type,unsigned long value)329 	dpb::addCluster(char type, unsigned long value)
330 	{
331 		ASSERT(pos_ + 1 + sizeof(value) - 1 < sizeof(buff_));
332 		buff_[pos_++] = type;
333 		*(unsigned long*)&buff_[pos_] = value;
334 		pos_ += short(sizeof(value));
335 	}
336 
337 	///////////////////////////////////////////////////////////////////////////
DBParamBuff()338 	DBParamBuff::DBParamBuff()
339 	{
340 		addParam(isc_dpb_version1);
341 	}
342 
343 	///////////////////////////////////////////////////////////////////////////
DataBase(T_FB & dll,Error & ib_error)344 	DataBase::DataBase(T_FB& dll, Error& ib_error)
345 	: handle_(NULL)
346 	, dll(dll)
347 	, ib_error(ib_error)
348 	{
349 	}
350 
351 	void
attach(const char * name)352 	DataBase::attach(const char* name)
353 	{
354 		handle_ = NULL;
355 		ib_error.check(dll.isc_attach_database(
356 				  ib_error.getErrorVector(),
357 				  strlen(name),
358 				  const_cast<char*>(name),
359 				  &handle_,
360 				  paramBuff_.getBuffSize(),
361 				  const_cast<char*>(paramBuff_.getBuff())
362 			  ));
363 	}
364 
365 	void
dettach()366 	DataBase::dettach()
367 	{
368 		if (handle_ != 0)
369 		{
370 			ib_error.check(dll.isc_detach_database(
371 					  ib_error.getErrorVector(),
372 					  //const_cast<void**>(&handle_)
373 					  &handle_
374 				  ));
375 		}
376 	}
377 
378 	void
drop()379 	DataBase::drop()
380 	{
381 		ib_error.check(dll.isc_drop_database(
382 				  ib_error.getErrorVector(),
383 				  //const_cast<void**>(&handle_)
384 				  &handle_
385 			  ));
386 		handle_ = NULL;
387 	}
388 
389 	void
execute_immediate(const String & stmt)390 	DataBase::execute_immediate(const String& stmt)
391 	{
392 		ASSERT(handle_ == 0);
393 		isc_tr_handle tr_handle = NULL;
394 
395 		ib_error.check(dll.isc_dsql_execute_immediate(
396 				  ib_error.getErrorVector(),
397 				  &handle_,
398 				  &tr_handle,
399 				  stmt.GetCount(),
400 				  stmt,
401 				  3, // dialect_,
402 				  NULL // inDataArray_.getBuffer()
403 			  ));
404 
405 		ib_error.check(dll.isc_detach_database(
406 				  ib_error.getErrorVector(),
407 				  //static_cast<void**>(&handle_)
408 				  &handle_
409 			  ));
410 	}
411 
412 	void
expand_dpb() const413 	DataBase::expand_dpb() const
414 	{
415 		// isc_expand_dpb() allocates a new block for the DPB. to avoid memory leaks, call
416 		// isc_free() to release that space.
417 
418 		// void        ISC_EXPORT_VARARG isc_expand_dpb (char ISC_FAR * ISC_FAR *,
419 //                           short ISC_FAR *,
420 //                           ...);
421 //
422 
423 // void        ISC_EXPORT isc_print_sqlerror (short,
424 	}
425 
426 	void
modify_dpb() const427 	DataBase::modify_dpb() const
428 	{
429 // int        ISC_EXPORT isc_modify_dpb (char ISC_FAR * ISC_FAR *,
430 //                      short ISC_FAR *, unsigned short,
431 //                      char ISC_FAR *, short );
432 //
433 	}
434 
435 	void
getInfo() const436 	DataBase::getInfo() const
437 	{
438 // ISC_STATUS  ISC_EXPORT isc_database_info (ISC_STATUS ISC_FAR *,
439 //                       isc_db_handle ISC_FAR *,
440 //                       short,
441 //                       char ISC_FAR *,
442 //                       short,
443 //                       char ISC_FAR *);
444 	}
445 
version_callback(void * user_arg,char * data)446 	void version_callback(void* user_arg, char* data)
447 	{
448 		ASSERT(user_arg);
449 		if (user_arg)
450 		{
451 			DataBase* pDataBase = (DataBase*)user_arg;
452 
453 			if (pDataBase->dbVersion_.IsEmpty())
454 			{
455 				pDataBase->dbVersion_ = data;
456 			}
457 			else
458 			{
459 				pDataBase->odsVersion_ = data;
460 			}
461 		}
462 	}
463 
464 	void
retrieveVersion()465 	DataBase::retrieveVersion()
466 	{
467 		dbVersion_.Clear();
468 		odsVersion_.Clear();
469 
470 #if FB_API_VER < 20
471 		typedef isc_callback cb_type;
472 #else
473 		typedef ISC_VERSION_CALLBACK cb_type;
474 #endif
475 
476 		ib_error.check(dll.isc_version(
477 				  &handle_,
478 				  (cb_type)version_callback,
479 				  this
480 			  ));
481 	}
482 
483 	///////////////////////////////////////////////////////////////////////////
Transaction(T_FB & dll,Error & ib_error)484 	Transaction::Transaction(T_FB& dll, Error& ib_error)
485 	: handle_(0L)
486 	, dll(dll)
487 	, ib_error(ib_error)
488 	{
489 	}
490 
491 	void
start(const DataBase & db)492 	Transaction::start(const DataBase& db)
493 	{
494 		handle_ = NULL;
495 
496 		// Note If a TPB is not created for a transaction, a NULL pointer must be passed to
497 		// isc_start_transaction () in its place. A default set of attributes is automatically assigned to
498 		// such transactions.
499 
500 		ib_error.check(dll.isc_start_transaction(
501 				  ib_error.getErrorVector(),
502 				  &handle_,
503 				  1, // Number of database handles passed in this call
504 				  db.getHandleP(),
505 				  paramBuff_.getBuffSize(),
506 				  const_cast<char*>(paramBuff_.getBuff())
507 			  ));
508 	}
509 
510 	void
start_multiple()511 	Transaction::start_multiple()
512 	{
513 // ISC_STATUS  ISC_EXPORT isc_start_multiple (ISC_STATUS ISC_FAR *,
514 //                        isc_tr_handle ISC_FAR *,
515 //                        short,
516 //                        void ISC_FAR *);
517 //
518 	}
519 
520 	void
commit()521 	Transaction::commit()
522 	{
523 		ib_error.check(dll.isc_commit_transaction(
524 				  ib_error.getErrorVector(),
525 				  &handle_
526 			  ));
527 	}
528 
529 	void
commit_retaining()530 	Transaction::commit_retaining()
531 	{
532 		ib_error.check(dll.isc_commit_retaining(
533 				  ib_error.getErrorVector(),
534 				  &handle_
535 			  ));
536 	}
537 
538 	void
rollback()539 	Transaction::rollback()
540 	{
541 		ib_error.check(dll.isc_rollback_transaction(
542 				  ib_error.getErrorVector(),
543 				  &handle_
544 			  ));
545 	}
546 
547 	void
rollback_retaining()548 	Transaction::rollback_retaining()
549 	{
550 		// isc_rollback_retaining () should be used with caution because the error
551 		// that caused the rollback may be in the transactions context. In this case, until the context
552 		// is released the error will continue.
553 		ib_error.check(dll.isc_rollback_retaining(
554 				  ib_error.getErrorVector(),
555 				  &handle_
556 			  ));
557 	}
558 
559 	void
prepare()560 	Transaction::prepare()
561 	{
562 		ib_error.check(dll.isc_prepare_transaction(
563 				  ib_error.getErrorVector(),
564 				  &handle_
565 			  ));
566 	}
567 
568 	void
prepare2()569 	Transaction::prepare2()
570 	{
571 // ISC_STATUS  ISC_EXPORT isc_prepare_transaction2 (ISC_STATUS ISC_FAR *,
572 //                          isc_tr_handle ISC_FAR *,
573 //                          short,
574 //                          char ISC_FAR *);
575 //
576 	}
577 
578 	void
getInfo()579 	Transaction::getInfo()
580 	{
581 // ISC_STATUS  ISC_EXPORT isc_transaction_info (ISC_STATUS ISC_FAR *,
582 //                          isc_tr_handle ISC_FAR *,
583 //                          short,
584 //                          char ISC_FAR *,
585 //                          short,
586 //                          char ISC_FAR *);
587 	}
588 
589 // Not documented ...
590 // ISC_STATUS  ISC_EXPORT isc_transact_request (ISC_STATUS ISC_FAR *,
591 //                          isc_db_handle ISC_FAR *,
592 //                          isc_tr_handle ISC_FAR *,
593 //                          unsigned short,
594 //                          char ISC_FAR *,
595 //                          unsigned short,
596 //                          char ISC_FAR *,
597 //                          unsigned short,
598 //                          char ISC_FAR *);
599 
600 // Not documented ...
601 // ISC_STATUS  ISC_EXPORT isc_reconnect_transaction (ISC_STATUS ISC_FAR *,
602 //                           isc_db_handle ISC_FAR *,
603 //                           isc_tr_handle ISC_FAR *,
604 //                           short,
605 //                           char ISC_FAR *);
606 //
607 
608 	///////////////////////////////////////////////////////////////////////////
SQLDataArray(size_t size)609 	SQLDataArray::SQLDataArray(size_t size) :
610 			pDA_(NULL),
611 			size_(0)
612 	{
613 		setSize(size);
614 	}
615 
SQLDataArray(const SQLDataArray &)616 	SQLDataArray::SQLDataArray(const SQLDataArray& /*theArray*/)
617 	{
618 		ASSERT(false);
619 	}
620 
~SQLDataArray()621 	SQLDataArray::~SQLDataArray()
622 	{
623 		try
624 		{
625 			setSize(0);
626 		}
627 		catch (...)
628 		{
629 			ASSERT(false);
630 		}
631 	}
632 
633 	void
setSize(size_t size)634 	SQLDataArray::setSize(size_t size)
635 	{
636 		if (size != size_)
637 		{
638 			if (pDA_)
639 			{
640 				free(pDA_);
641 				pDA_ = NULL;
642 			}
643 			size_ = size;
644 			if (size_ != 0)
645 			{
646 				size_t len = XSQLDA_LENGTH(size_);
647 				pDA_ = (XSQLDA *)malloc(len);
648 				memset(pDA_, 0, len);
649 				// Initialize it ...
650 				pDA_->version = SQLDA_VERSION1;
651 				pDA_->sqln = size_;
652 				pDA_->sqld = size_; // actual number of fields ...
653 			}
654 		}
655 	}
656 
657 	///////////////////////////////////////////////////////////////////////////
DynamicSQL(const DataBase & db,const Transaction & tr,T_FB & dll,Error & ib_error)658 	DynamicSQL::DynamicSQL(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error)
659 	: dialect_(3)
660 	, pDBHandle_(db.getHandleP())
661 	, pTRHandle_(tr.getHandleP())
662 	, dll(dll)
663 	, ib_error(ib_error)
664 	, handle_(NULL)
665 	, all_data_fetched_(false)
666 	{
667 		allocate_stmt2();
668 	}
669 
~DynamicSQL()670 	DynamicSQL::~DynamicSQL()
671 	{
672 		try
673 		{
674 			drop_statement();
675 		}
676 		catch (...)
677 		{
678 			ASSERT(false);
679 		}
680 	}
681 
682 	void
execute_immediate(const String & stmt)683 	DynamicSQL::execute_immediate(const String& stmt)
684 	{
685 		ib_error.check(dll.isc_dsql_execute_immediate(
686 				  ib_error.getErrorVector(),
687 				  pDBHandle_,
688 				  pTRHandle_,
689 				  stmt.GetCount(),
690 				  stmt,
691 				  dialect_,
692 				  inDataArray_.getBuffer()
693 			  ));
694 		// There is no data to fetch ...
695 		// all_data_fetched_ = false;
696 	}
697 
698 	void
execute_immediate_data(const String & stmt)699 	DynamicSQL::execute_immediate_data(const String& stmt)
700 	{
701 		ib_error.check(dll.isc_dsql_exec_immed2(
702 				  ib_error.getErrorVector(),
703 				  pDBHandle_,
704 				  pTRHandle_,
705 				  stmt.GetCount(),
706 				  stmt,
707 				  dialect_,
708 				  inDataArray_.getBuffer(),
709 				  outDataArray_.getBuffer()
710 			  ));
711 		all_data_fetched_ = false;
712 	}
713 
714 	void
execute_immediate_no_trans(const String & stmt)715 	DynamicSQL::execute_immediate_no_trans(const String& stmt)
716 	{
717 		ASSERT(*pDBHandle_ == 0);
718 		ASSERT(*pTRHandle_ == 0);
719 
720 		ib_error.check(dll.isc_dsql_execute_immediate(
721 				  ib_error.getErrorVector(),
722 				  pDBHandle_,
723 				  pTRHandle_,
724 				  stmt.GetCount(),
725 				  stmt,
726 				  dialect_,
727 				  inDataArray_.getBuffer()
728 			  ));
729 		// There is no data to fetch ...
730 		// all_data_fetched_ = false;
731 	}
732 
733 	void
prepare(const String & stmt,const SQLDataArray & define_da)734 	DynamicSQL::prepare(const String& stmt, const SQLDataArray& define_da)
735 	{
736 		ib_error.check(dll.isc_dsql_prepare(
737 				  ib_error.getErrorVector(),
738 				  pTRHandle_,
739 				  &handle_,
740 				  stmt.GetCount(),
741 				  stmt,
742 				  dialect_,
743 				  define_da.getBuffer()
744 			  ));
745 	}
746 
747 	void
execute()748 	DynamicSQL::execute()
749 	{
750 		ib_error.check(dll.isc_dsql_execute(
751 				  ib_error.getErrorVector(),
752 				  pTRHandle_,
753 				  &handle_,
754 				  // Indicates the version of the extended SQL descriptor area (XSQLDA)
755 				  // ???? ??????? ???? 3-?, ?? SQL_DIALECT_V6, ???? ?????? - SQL_DIALECT_V5
756 				  SQL_DIALECT_V6,
757 				  inDataArray_.getBuffer()
758 			  ));
759 		all_data_fetched_ = false;
760 	}
761 
762 	void
execute2()763 	DynamicSQL::execute2()
764 	{
765 		ib_error.check(dll.isc_dsql_execute2(
766 				  ib_error.getErrorVector(),
767 				  pTRHandle_,
768 				  &handle_,
769 				  // Indicates the version of the extended SQL descriptor area (XSQLDA)
770 				  // ???? ??????? ???? 3-?, ?? SQL_DIALECT_V6, ???? ?????? - SQL_DIALECT_V5
771 				  SQL_DIALECT_V6,
772 				  inDataArray_.getBuffer(),
773 				  outDataArray_.getBuffer()
774 			  ));
775 		// all_data_fetched_ = false;
776 	}
777 
778 	void
describe_bind(const SQLDataArray & da)779 	DynamicSQL::describe_bind(const SQLDataArray& da)
780 	{
781 		ib_error.check(dll.isc_dsql_describe_bind(
782 				  ib_error.getErrorVector(),
783 				  &handle_,
784 				  // Indicates the version of the extended SQL descriptor area (XSQLDA)
785 				  // ???? ??????? ???? 3-?, ?? SQL_DIALECT_V6, ???? ?????? - SQL_DIALECT_V5
786 				  SQL_DIALECT_V6,
787 				  da.getBuffer()
788 			  ));
789 	}
790 
791 	void
describe_define(const SQLDataArray & da)792 	DynamicSQL::describe_define(const SQLDataArray& da)
793 	{
794 		ib_error.check(dll.isc_dsql_describe(
795 				  ib_error.getErrorVector(),
796 				  &handle_,
797 				  // Indicates the version of the extended SQL descriptor area (XSQLDA)
798 				  // ???? ??????? ???? 3-?, ?? SQL_DIALECT_V6, ???? ?????? - SQL_DIALECT_V5
799 				  SQL_DIALECT_V6,
800 				  da.getBuffer()
801 			  ));
802 	}
803 
804 	void
setCursorName(const char * name)805 	DynamicSQL::setCursorName(const char* name)
806 	{
807 		ib_error.check(dll.isc_dsql_set_cursor_name(
808 				  ib_error.getErrorVector(),
809 				  &handle_,
810 				  const_cast<char*>(name),
811 				  0 // Reserved for future use; set to 0
812 			  ));
813 	}
814 
815 	bool
fetch()816 	DynamicSQL::fetch()
817 	{
818 		if (!all_data_fetched_)
819 		{
820 			int fetch_stat = dll.isc_dsql_fetch(
821 								 ib_error.getErrorVector(),
822 								 &handle_,
823 								 // Indicates the version of the extended SQL descriptor area (XSQLDA)
824 								 // ???? ??????? ???? 3-?, ?? SQL_DIALECT_V6, ???? ?????? - SQL_DIALECT_V5
825 								 SQL_DIALECT_V6,
826 								 outDataArray_.getBuffer()
827 							 );
828 
829 			switch (fetch_stat)
830 			{
831 			case 0:
832 				return true;
833 			case 100:
834 				// No more data.
835 				all_data_fetched_ = true;
836 				return false;
837 			default:
838 				ib_error.check();
839 				break;
840 			}
841 		}
842 
843 		return false;
844 	}
845 
846 	int
getStmtType()847 	DynamicSQL::getStmtType()
848 	{
849 		// Get Statement type in our case ...
850 		char type_item[] = {isc_info_sql_stmt_type};
851 		char res_buffer[8];
852 		int  st_type = 0;
853 
854 		ib_error.check(dll.isc_dsql_sql_info(
855 				  ib_error.getErrorVector(),
856 				  &handle_,
857 				  sizeof(type_item),
858 				  type_item,
859 				  sizeof(res_buffer),
860 				  res_buffer
861 			  ));
862 
863 		if (res_buffer[0] == isc_info_sql_stmt_type)
864 		{
865 			short length;
866 			length = static_cast<short>(dll.isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 1), 2));
867 			st_type = static_cast<int>(dll.isc_portable_integer(reinterpret_cast<unsigned char*>(res_buffer + 3), length));
868 		}
869 
870 		return st_type;
871 	}
872 
873 	void
allocate_stmt()874 	DynamicSQL::allocate_stmt()
875 	{
876 		// Note The isc_dsql_allocate_statement2() function is similar to the
877 		// isc_dsql_alloc_statement() function except that statement handles allocated using
878 		// isc_dsql_allocate_statement2() are automatically reset to
879 		// NULL when the database under which they are allocated is detached.
880 
881 		if (handle_ == 0)
882 		{
883 			ib_error.check(dll.isc_dsql_allocate_statement(
884 					  ib_error.getErrorVector(),
885 					  pDBHandle_,
886 					  &handle_
887 				  ));
888 		}
889 		else
890 		{
891 			ASSERT(handle_ == 0);
892 		}
893 	}
894 
895 	void
allocate_stmt2()896 	DynamicSQL::allocate_stmt2()
897 	{
898 		// Note The isc_dsql_allocate_statement2() function is similar to the
899 		// isc_dsql_alloc_statement() function except that statement handles allocated using
900 		// isc_dsql_allocate_statement2() are automatically reset to
901 		// NULL when the database under which they are allocated is detached.
902 
903 		if (handle_ == 0)
904 		{
905 			ib_error.check(dll.isc_dsql_alloc_statement2(
906 					  ib_error.getErrorVector(),
907 					  pDBHandle_,
908 					  &handle_
909 				  ));
910 		}
911 		else
912 		{
913 			ASSERT(handle_ == 0);
914 		}
915 	}
916 
917 	void
close_cursor()918 	DynamicSQL::close_cursor()
919 	{
920 		ib_error.check(dll.isc_dsql_free_statement(
921 				  ib_error.getErrorVector(),
922 				  &handle_,
923 				  DSQL_close
924 			  ));
925 		// !!! Do not set handle_ = NULL here !!!;
926 	}
927 
928 	void
drop_statement()929 	DynamicSQL::drop_statement()
930 	{
931 		ib_error.check(dll.isc_dsql_free_statement(
932 				  ib_error.getErrorVector(),
933 				  &handle_,
934 				  DSQL_drop
935 			  ));
936 		handle_ = NULL;
937 	}
938 
939 // Not documented ...
940 // ISC_STATUS  ISC_EXPORT isc_execute (ISC_STATUS ISC_FAR *,
941 //                     isc_tr_handle ISC_FAR *,
942 //                     char ISC_FAR *,
943 //                     XSQLDA ISC_FAR *);
944 //
945 
946 // Not documented ...
947 // ISC_STATUS  ISC_EXPORT isc_execute_immediate (ISC_STATUS ISC_FAR *,
948 //                           isc_db_handle ISC_FAR *,
949 //                           isc_tr_handle ISC_FAR *,
950 //                           short ISC_FAR *,
951 //                           char ISC_FAR *);
952 //
953 
954 // Not documented ...
955 // ISC_STATUS  ISC_EXPORT isc_fetch (ISC_STATUS ISC_FAR *,
956 //                   char ISC_FAR *,
957 //                   XSQLDA ISC_FAR *);
958 //
959 
960 // Not documented ...
961 // ISC_STATUS  ISC_EXPORT isc_prepare (ISC_STATUS ISC_FAR *,
962 //                     isc_db_handle ISC_FAR *,
963 //                     isc_tr_handle ISC_FAR *,
964 //                     char ISC_FAR *,
965 //                     short ISC_FAR *,
966 //                     char ISC_FAR *,
967 //                     XSQLDA ISC_FAR *);
968 
969 // Not documented ...
970 // ISC_STATUS  ISC_EXPORT isc_dsql_execute_m (ISC_STATUS ISC_FAR *,
971 //                        isc_tr_handle ISC_FAR *,
972 //                        isc_stmt_handle ISC_FAR *,
973 //                        unsigned short,
974 //                        char ISC_FAR *,
975 //                        unsigned short,
976 //                        unsigned short,
977 //                        char ISC_FAR *);
978 //
979 
980 // Not documented ...
981 // ISC_STATUS  ISC_EXPORT isc_dsql_execute2_m (ISC_STATUS ISC_FAR *,
982 //                        isc_tr_handle ISC_FAR *,
983 //                        isc_stmt_handle ISC_FAR *,
984 //                        unsigned short,
985 //                        char ISC_FAR *,
986 //                        unsigned short,
987 //                        unsigned short,
988 //                        char ISC_FAR *,
989 //                        unsigned short,
990 //                        char ISC_FAR *,
991 //                        unsigned short,
992 //                        unsigned short,
993 //                        char ISC_FAR *);
994 
995 
996 // Not documented ...
997 // ISC_STATUS  ISC_EXPORT isc_dsql_execute_immediate_m (ISC_STATUS ISC_FAR *,
998 //                              isc_db_handle ISC_FAR *,
999 //                              isc_tr_handle ISC_FAR *,
1000 //                              unsigned short,
1001 //                              char ISC_FAR *,
1002 //                              unsigned short,
1003 //                              unsigned short,
1004 //                              char ISC_FAR *,
1005 //                              unsigned short,
1006 //                              unsigned short,
1007 //                              char ISC_FAR *);
1008 
1009 // Not documented ...
1010 // ISC_STATUS  ISC_EXPORT isc_dsql_exec_immed3_m (ISC_STATUS ISC_FAR *,
1011 //                            isc_db_handle ISC_FAR *,
1012 //                            isc_tr_handle ISC_FAR *,
1013 //                            unsigned short,
1014 //                            char ISC_FAR *,
1015 //                            unsigned short,
1016 //                            unsigned short,
1017 //                            char ISC_FAR *,
1018 //                            unsigned short,
1019 //                            unsigned short,
1020 //                            char ISC_FAR *,
1021 //                            unsigned short,
1022 //                            char ISC_FAR *,
1023 //                            unsigned short,
1024 //                            unsigned short,
1025 //                            char ISC_FAR *);
1026 
1027 // Not documented ...
1028 // ISC_STATUS  ISC_EXPORT isc_dsql_fetch_m (ISC_STATUS ISC_FAR *,
1029 //                      isc_stmt_handle ISC_FAR *,
1030 //                      unsigned short,
1031 //                      char ISC_FAR *,
1032 //                      unsigned short,
1033 //                      unsigned short,
1034 //                      char ISC_FAR *);
1035 
1036 // Not documented ...
1037 // ISC_STATUS  ISC_EXPORT isc_dsql_insert_m (ISC_STATUS ISC_FAR *,
1038 //                       isc_stmt_handle ISC_FAR *,
1039 //                       unsigned short,
1040 //                       char ISC_FAR *,
1041 //                       unsigned short,
1042 //                       unsigned short,
1043 //                       char ISC_FAR *);
1044 
1045 // Not documented ...
1046 // ISC_STATUS  ISC_EXPORT isc_dsql_prepare_m (ISC_STATUS ISC_FAR *,
1047 //                        isc_tr_handle ISC_FAR *,
1048 //                        isc_stmt_handle ISC_FAR *,
1049 //                        unsigned short,
1050 //                        char ISC_FAR *,
1051 //                        unsigned short,
1052 //                        unsigned short,
1053 //                        char ISC_FAR *,
1054 //                        unsigned short,
1055 //                        char ISC_FAR *);
1056 //
1057 
1058 	///////////////////////////////////////////////////////////////////////////
EmbededSQL()1059 	EmbededSQL::EmbededSQL()
1060 	{
1061 	}
1062 
1063 // Not documented ...
1064 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_close (ISC_STATUS ISC_FAR *,
1065 //                          char ISC_FAR *);
1066 
1067 // Not documented ...
1068 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_declare (ISC_STATUS ISC_FAR *,
1069 //                           char ISC_FAR *,
1070 //                           char ISC_FAR *);
1071 
1072 // Not documented ...
1073 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_describe (ISC_STATUS ISC_FAR *,
1074 //                         char ISC_FAR *,
1075 //                         unsigned short,
1076 //                         XSQLDA ISC_FAR *);
1077 
1078 // Not documented ...
1079 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_describe_bind (ISC_STATUS ISC_FAR *,
1080 //                              char ISC_FAR *,
1081 //                              unsigned short,
1082 //                              XSQLDA ISC_FAR *);
1083 
1084 // Not documented ...
1085 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_execute (ISC_STATUS ISC_FAR *,
1086 //                            isc_tr_handle ISC_FAR *,
1087 //                            char ISC_FAR *,
1088 //                            unsigned short,
1089 //                            XSQLDA ISC_FAR *);
1090 
1091 // Not documented ...
1092 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_execute2 (ISC_STATUS ISC_FAR *,
1093 //                         isc_tr_handle ISC_FAR *,
1094 //                         char ISC_FAR *,
1095 //                         unsigned short,
1096 //                         XSQLDA ISC_FAR *,
1097 //                         XSQLDA ISC_FAR *);
1098 
1099 // Not documented ...
1100 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_execute_immed (ISC_STATUS ISC_FAR *,
1101 //                              isc_db_handle ISC_FAR *,
1102 //                              isc_tr_handle ISC_FAR *,
1103 //                              unsigned short,
1104 //                              char ISC_FAR *,
1105 //                              unsigned short,
1106 //                              XSQLDA ISC_FAR *);
1107 
1108 // Not documented ...
1109 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_fetch (ISC_STATUS ISC_FAR *,
1110 //                          char ISC_FAR *,
1111 //                          unsigned short,
1112 //                          XSQLDA ISC_FAR *);
1113 
1114 // Not documented ...
1115 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_open (ISC_STATUS ISC_FAR *,
1116 //                         isc_tr_handle ISC_FAR *,
1117 //                         char ISC_FAR *,
1118 //                         unsigned short,
1119 //                         XSQLDA ISC_FAR *);
1120 
1121 // Not documented ...
1122 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_open2 (ISC_STATUS ISC_FAR *,
1123 //                          isc_tr_handle ISC_FAR *,
1124 //                          char ISC_FAR *,
1125 //                          unsigned short,
1126 //                          XSQLDA ISC_FAR *,
1127 //                          XSQLDA ISC_FAR *);
1128 
1129 // Not documented ...
1130 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_insert (ISC_STATUS ISC_FAR *,
1131 //                           char ISC_FAR *,
1132 //                           unsigned short,
1133 //                           XSQLDA ISC_FAR *);
1134 
1135 // Not documented ...
1136 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_prepare (ISC_STATUS ISC_FAR *,
1137 //                            isc_db_handle ISC_FAR *,
1138 //                            isc_tr_handle ISC_FAR *,
1139 //                            char ISC_FAR *,
1140 //                            unsigned short,
1141 //                            char ISC_FAR *,
1142 //                            unsigned short,
1143 //                            XSQLDA ISC_FAR *);
1144 
1145 // Not documented ...
1146 // ISC_STATUS  ISC_EXPORT isc_embed_dsql_release (ISC_STATUS ISC_FAR *,
1147 //                            char ISC_FAR *);
1148 
1149 	///////////////////////////////////////////////////////////////////////////
1150 	void
get(SegmentBlob & blob,const String & tbl_name,const String & clm_name)1151 	BlobDescr::get(
1152 		SegmentBlob& blob,
1153 		const String& tbl_name,
1154 		const String& clm_name
1155 	)
1156 	{
1157 		char clm_global_name[256];
1158 
1159 		ib_error.check(dll.isc_blob_lookup_desc(
1160 				  ib_error.getErrorVector(),
1161 				  blob.pDBHandle_,
1162 				  blob.pTRHandle_,
1163 				  (unsigned char ISC_FAR *)~tbl_name,
1164 				  (unsigned char ISC_FAR *)~clm_name,
1165 				  &blobDescr_,
1166 				  (unsigned char ISC_FAR *)clm_global_name
1167 			  ));
1168 	}
1169 
1170 	void
getDefault()1171 	BlobDescr::getDefault()
1172 	{
1173 		// void       ISC_EXPORT isc_blob_default_desc (ISC_BLOB_DESC ISC_FAR *,
1174 		//                                         unsigned char ISC_FAR *,
1175 		//                                         unsigned char ISC_FAR *);
1176 		//
1177 	}
1178 
1179 	void
set()1180 	BlobDescr::set()
1181 	{
1182 		// ISC_STATUS ISC_EXPORT isc_blob_set_desc (ISC_STATUS ISC_FAR *,
1183 		//                      unsigned char ISC_FAR *,
1184 		//                      unsigned char ISC_FAR *,
1185 		//                      short,
1186 		//                      short,
1187 		//                      short,
1188 		//                      ISC_BLOB_DESC ISC_FAR *);
1189 		//
1190 	}
1191 
1192 	// ISC_STATUS ISC_EXPORT isc_blob_gen_bpb (ISC_STATUS ISC_FAR *,
1193 	//                     ISC_BLOB_DESC ISC_FAR *,
1194 	//                     ISC_BLOB_DESC ISC_FAR *,
1195 	//                     unsigned short,
1196 	//                     unsigned char ISC_FAR *,
1197 	//                     unsigned short ISC_FAR *);
1198 	//
1199 
1200 	///////////////////////////////////////////////////////////////////////////
info()1201 	SegmentBlob::info::info() :
1202 			lenght_(0),
1203 			maxSegments_(0),
1204 			numSegments_(0),
1205 			type_segmented(false)
1206 	{
1207 	}
1208 
SegmentBlob(const DataBase & db,const Transaction & tr,T_FB & dll,Error & ib_error)1209 	SegmentBlob::SegmentBlob(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error) :
1210 		pDBHandle_(db.getHandleP()),
1211 		pTRHandle_(tr.getHandleP()),
1212 		dll(dll),
1213 		ib_error(ib_error),
1214 		isOpen_(false),
1215 		hasInfo_(false)
1216 	{
1217 		handle_ = NULL;
1218 
1219 		id_.gds_quad_low = 0;
1220 		id_.gds_quad_high = 0;
1221 
1222 		lastID_.gds_quad_low = 0;
1223 		lastID_.gds_quad_high = 0;
1224 	}
1225 
~SegmentBlob()1226 	SegmentBlob::~SegmentBlob()
1227 	{
1228 		// This is not a right place to close BLOB ...
1229 		// close();
1230 	}
1231 
1232 	void
open_internal()1233 	SegmentBlob::open_internal()
1234 	{
1235 		handle_ = NULL;
1236 
1237 		ib_error.check(dll.isc_open_blob(
1238 				  ib_error.getErrorVector(),
1239 				  pDBHandle_,
1240 				  pTRHandle_,
1241 				  &handle_,   /* set by this function to refer to the SegmentBlob */
1242 				  &id_       /* SegmentBlob ID put into out_sqlda by isc_dsql_fetch() */
1243 			  ));
1244 	}
1245 
1246 	void
open2_internal()1247 	SegmentBlob::open2_internal()
1248 	{
1249 		handle_ = NULL;
1250 
1251 		ib_error.check(dll.isc_open_blob2(
1252 				  ib_error.getErrorVector(),
1253 				  pDBHandle_,
1254 				  pTRHandle_,
1255 				  &handle_,   /* set by this function to refer to the SegmentBlob */
1256 				  &id_,       /* SegmentBlob ID put into out_sqlda by isc_dsql_fetch() */
1257 				  0,          /* BPB length = 0; no filter will be used */
1258 				  NULL        /* NULL BPB, since no filter will be used */
1259 			  ));
1260 	}
1261 
1262 	void
setup_open()1263 	SegmentBlob::setup_open()
1264 	{
1265 		isOpen_ = true;
1266 		lastID_ = id_;
1267 		hasInfo_ = false;
1268 	}
1269 
1270 	void
setup_close()1271 	SegmentBlob::setup_close()
1272 	{
1273 		isOpen_ = false;
1274 		lastID_.gds_quad_low = 0;
1275 		lastID_.gds_quad_high = 0;
1276 		hasInfo_ = false;
1277 	}
1278 
1279 	void
open()1280 	SegmentBlob::open()
1281 	{
1282 		if (!isOpen_)
1283 		{
1284 			open2_internal();
1285 			setup_open();
1286 		}
1287 		else if ((lastID_.gds_quad_high != id_.gds_quad_high) || (lastID_.gds_quad_low != id_.gds_quad_low))
1288 		{
1289 			close();
1290 			open2_internal();
1291 			setup_open();
1292 		}
1293 	}
1294 
1295 	void
create_internal()1296 	SegmentBlob::create_internal()
1297 	{
1298 		handle_ = NULL;
1299 		id_.gds_quad_low = 0;
1300 		id_.gds_quad_high = 0;
1301 
1302 		ib_error.check(dll.isc_create_blob(
1303 				  ib_error.getErrorVector(),
1304 				  pDBHandle_,
1305 				  pTRHandle_,
1306 				  &handle_,   /* set by this function to refer to the SegmentBlob */
1307 				  &id_        /* SegmentBlob ID put into out_sqlda by isc_dsql_fetch() */
1308 			  ));
1309 	}
1310 
1311 	void
create2_internal()1312 	SegmentBlob::create2_internal()
1313 	{
1314 		handle_ = NULL;
1315 		id_.gds_quad_low = 0;
1316 		id_.gds_quad_high = 0;
1317 
1318 		ib_error.check(dll.isc_create_blob2(
1319 				  ib_error.getErrorVector(),
1320 				  pDBHandle_,
1321 				  pTRHandle_,
1322 				  &handle_,   /* set by this function to refer to the SegmentBlob */
1323 				  &id_,       /* SegmentBlob ID put into out_sqlda by isc_dsql_fetch() */
1324 				  0,          /* BPB length = 0; no filter will be used */
1325 				  NULL        /* NULL BPB, since no filter will be used */
1326 			  ));
1327 	}
1328 
1329 	void
create()1330 	SegmentBlob::create()
1331 	{
1332 		close();
1333 		create2_internal();
1334 		setup_open();
1335 	}
1336 
1337 	void
close()1338 	SegmentBlob::close()
1339 	{
1340 		if (isOpen_)
1341 		{
1342 			ASSERT(handle_);
1343 			ib_error.check(dll.isc_close_blob(
1344 					  ib_error.getErrorVector(),
1345 					  &handle_
1346 				  ));
1347 			handle_ = NULL;
1348 			setup_close();
1349 		}
1350 	}
1351 
1352 	bool
getSegment(unsigned short & actualSegLen,unsigned short maxSegLen,char * pSegment)1353 	SegmentBlob::getSegment(
1354 		unsigned short& actualSegLen,
1355 		unsigned short maxSegLen,
1356 		char* pSegment
1357 	)
1358 	{
1359 		bool result = false;
1360 
1361 		if (!isOpen_)
1362 			open();
1363 
1364 		ASSERT(handle_);
1365 		stat_ = dll.isc_get_segment(
1366 					ib_error.getErrorVector(),
1367 					&handle_,
1368 					&actualSegLen,
1369 					maxSegLen,
1370 					pSegment
1371 				);
1372 		if (stat_ == 0 || (stat_ != 0 && ib_error.get_err_code() == isc_segment))
1373 			result = true;
1374 		else if (stat_ == isc_segstr_eof)
1375 			result = false;
1376 		else
1377 			// Exception.
1378 			ib_error.check();
1379 
1380 		return result;
1381 	}
1382 
1383 	void
1384 	// SegmentBlob::addSegment(const String& data)
addSegment(const char * pSegment,unsigned short seg_length)1385 	SegmentBlob::addSegment(const char* pSegment, unsigned short seg_length)
1386 	{
1387 		if (!isOpen_)
1388 			open();
1389 
1390 		ASSERT(handle_);
1391 		ib_error.check(dll.isc_put_segment(
1392 				  ib_error.getErrorVector(),
1393 				  &handle_,
1394 				  seg_length,
1395 				  const_cast<char*>(pSegment)
1396 			  ));
1397 	}
1398 
1399 	void
put_segment(const char * data_ptr,size_t data_len)1400 	SegmentBlob::put_segment(const char* data_ptr, size_t data_len)
1401 	{
1402 		long cur_str_pos = 0;
1403 		unsigned short cur_segment_size = 0;
1404 		long size_left = data_len;
1405 		const unsigned short db_segment_size = 0xFFFF;
1406 
1407 		// !!! Segment size is limited to "unsigned short" ...
1408 		while (size_left > 0)
1409 		{
1410 			cur_segment_size = (size_left > db_segment_size ? db_segment_size : static_cast<unsigned short>(size_left));
1411 
1412 			addSegment(data_ptr + cur_str_pos, cur_segment_size);
1413 
1414 			size_left -= cur_segment_size;
1415 			cur_str_pos += cur_segment_size;
1416 		}
1417 	}
1418 
1419 	void
cancel()1420 	SegmentBlob::cancel()
1421 	{
1422 		ASSERT(handle_);
1423 		ib_error.check(dll.isc_cancel_blob(
1424 				  ib_error.getErrorVector(),
1425 				  &handle_
1426 			  ));
1427 		setup_close();
1428 	}
1429 
1430 	void
retrieve_info()1431 	SegmentBlob::retrieve_info()
1432 	{
1433 		if (!hasInfo_)
1434 		{
1435 			char res_buffer[40];
1436 			char blob_items[] =
1437 			{
1438 				isc_info_blob_total_length,
1439 				isc_info_blob_max_segment,
1440 				isc_info_blob_num_segments,
1441 				isc_info_blob_type
1442 			};
1443 
1444 			if (!isOpen_)
1445 				open();
1446 
1447 			ASSERT(handle_);
1448 			ib_error.check(dll.isc_blob_info(
1449 					  ib_error.getErrorVector(),
1450 					  &handle_,
1451 					  sizeof(blob_items),/* Length of item-list buffer. */
1452 					  blob_items, /* Item-list buffer. */
1453 					  sizeof(res_buffer),/* Length of result buffer. */
1454 					  res_buffer /* Result buffer */
1455 				  ));
1456 
1457 			// Extract values returned in the result buffer
1458 			for (char* p = res_buffer; *p != isc_info_end ;)
1459 			{
1460 
1461 				char item = *p++;
1462 
1463 				short length = (short)dll.isc_vax_integer(p, 2);
1464 
1465 				p += 2;
1466 
1467 				switch (item)
1468 				{
1469 				case isc_info_blob_total_length:
1470 					info_.lenght_ = dll.isc_vax_integer(p, length);
1471 					break;
1472 				case isc_info_blob_max_segment:
1473 					info_.maxSegments_ = dll.isc_vax_integer(p, length);
1474 					break;
1475 				case isc_info_blob_num_segments:
1476 					info_.numSegments_ = dll.isc_vax_integer(p, length);
1477 					break;
1478 				case isc_info_blob_type:
1479 					info_.type_segmented = (dll.isc_vax_integer(p, length) == 0);
1480 					break;
1481 				case isc_info_truncated:
1482 					// handle error
1483 					throw DbExc("BLOB information was truncated.");
1484 					break;
1485 				case isc_info_error:
1486 					// handle error
1487 					throw DbExc("Requested BLOB information is unavailable.");
1488 					break;
1489 				default:
1490 					break;
1491 				}
1492 
1493 				p += length;
1494 			}
1495 
1496 			hasInfo_ = true;
1497 		}
1498 	}
1499 
1500 // Stream Blobs ...
1501 // http://www.ibphoenix.com/a4556.htm
1502 
1503 // Not documented ...
1504 // ISC_STATUS  ISC_EXPORT isc_seek_blob (ISC_STATUS ISC_FAR *,
1505 //                       isc_blob_handle ISC_FAR *,
1506 //                       short,
1507 //                       ISC_LONG,
1508 //                       ISC_LONG ISC_FAR *);
1509 //
1510 
1511 
1512 
1513 
1514 // Not documented ...
1515 // BSTREAM     ISC_FAR * ISC_EXPORT BLOB_open (isc_blob_handle,
1516 //                         char ISC_FAR *,
1517 //                         int);
1518 //
1519 
1520 // Not documented ...
1521 // int         ISC_EXPORT BLOB_put (char,
1522 //                  BSTREAM ISC_FAR *);
1523 //
1524 
1525 // Not documented ...
1526 // int         ISC_EXPORT BLOB_close (BSTREAM ISC_FAR *);
1527 //
1528 
1529 // Not documented ...
1530 // int         ISC_EXPORT BLOB_get (BSTREAM ISC_FAR *);
1531 //
1532 
1533 // Not documented ...
1534 // int         ISC_EXPORT BLOB_display (ISC_QUAD ISC_FAR *,
1535 //                      isc_db_handle,
1536 //                      isc_tr_handle,
1537 //                      char ISC_FAR *);
1538 //
1539 
1540 // Not documented ...
1541 // int         ISC_EXPORT BLOB_dump (ISC_QUAD ISC_FAR *,
1542 //                   isc_db_handle,
1543 //                   isc_tr_handle,
1544 //                   char ISC_FAR *);
1545 //
1546 
1547 // Not documented ...
1548 // int         ISC_EXPORT BLOB_edit (ISC_QUAD ISC_FAR *,
1549 //                   isc_db_handle,
1550 //                   isc_tr_handle,
1551 //                   char ISC_FAR *);
1552 //
1553 
1554 // Not documented ...
1555 // int         ISC_EXPORT BLOB_load (ISC_QUAD ISC_FAR *,
1556 //                   isc_db_handle,
1557 //                   isc_tr_handle,
1558 //                   char ISC_FAR *);
1559 //
1560 
1561 // Not documented ...
1562 // int         ISC_EXPORT BLOB_text_dump (ISC_QUAD ISC_FAR *,
1563 //                   isc_db_handle,
1564 //                   isc_tr_handle,
1565 //                   char ISC_FAR *);
1566 //
1567 
1568 // Not documented ...
1569 // int         ISC_EXPORT BLOB_text_load (ISC_QUAD ISC_FAR *,
1570 //                   isc_db_handle,
1571 //                   isc_tr_handle,
1572 //                   char ISC_FAR *);
1573 //
1574 
1575 // Not documented ...
1576 // BSTREAM     ISC_FAR * ISC_EXPORT Bopen (ISC_QUAD ISC_FAR *,
1577 //                         isc_db_handle,
1578 //                         isc_tr_handle,
1579 //                         char ISC_FAR *);
1580 //
1581 
1582 // Not documented ...
1583 // BSTREAM     ISC_FAR * ISC_EXPORT Bopen2 (ISC_QUAD ISC_FAR *,
1584 //                      isc_db_handle,
1585 //                      isc_tr_handle,
1586 //                      char ISC_FAR *,
1587 //                      unsigned short);
1588 
1589 
1590 
1591 	///////////////////////////////////////////////////////////////////////////
spb(size_t buff_size)1592 	spb::spb(size_t buff_size) :
1593 			buff_size_(buff_size),
1594 			pos_(0)
1595 	{
1596 		buff_ptr_ = new char[buff_size_];
1597 		memset(buff_ptr_, 0, buff_size_);
1598 	}
1599 
~spb()1600 	spb::~spb()
1601 	{
1602 		delete [] buff_ptr_;
1603 	}
1604 
1605 	void
addParam(char value)1606 	spb::addParam(char value)
1607 	{
1608 		ASSERT(pos_ < buff_size_);
1609 		buff_ptr_[pos_++] = value;
1610 	}
1611 
1612 	void
addCluster(char type,const char * value)1613 	spb::addCluster(char type, const char* value)
1614 	{
1615 		unsigned short len = (unsigned short)strlen(value);
1616 
1617 		ASSERT(static_cast<size_t>(pos_ + 1 + 2 + len - 1) < buff_size_);
1618 		buff_ptr_[pos_++] = type;
1619 		char* p = &buff_ptr_[pos_];
1620 		ADD_SPB_LENGTH(p, len); // It is okay to have a warning "conversion from 'unsigned short' to 'char'" here.
1621 		pos_ += sizeof(len);
1622 		memcpy(&buff_ptr_[pos_], value, len);
1623 		pos_ += len;
1624 	}
1625 
1626 	void
addCluster(char type,unsigned long value)1627 	spb::addCluster(char type, unsigned long value)
1628 	{
1629 		ASSERT(pos_ + 1 + sizeof(value) - 1 < buff_size_);
1630 		buff_ptr_[pos_++] = type;
1631 		// *(short*)&buff_ptr_[pos_] = value;
1632 		char* p = &buff_ptr_[pos_];
1633 		ADD_SPB_NUMERIC(p, value);
1634 		pos_ += short(sizeof(value));
1635 	}
1636 
1637 	///////////////////////////////////////////////////////////////////////////
1638 	void
attach(const char * host,const char * user,const char * pswd,network_protocol_t protocol)1639 	Service::attach(
1640 		const char* host,
1641 		const char* user,
1642 		const char* pswd,
1643 		network_protocol_t protocol
1644 	)
1645 	{
1646 		String service_host;
1647 
1648 		service_host = host;
1649 		if (!service_host.IsEmpty())
1650 		{
1651 			switch (protocol)
1652 			{
1653 			case np_TCP_IP:
1654 				service_host += ":service_mgr";
1655 				break;
1656 			case np_NetBEUI:
1657 				service_host = "\\\\" + service_host;
1658 				service_host += "\\service_mgr";
1659 				break;
1660 			case np_IPX_SPX:
1661 				service_host += "@service_mgr";
1662 				break;
1663 			case np_local:
1664 				service_host = "service_mgr";
1665 				break;
1666 			}
1667 		}
1668 		else
1669 		{
1670 			service_host = "service_mgr";
1671 		}
1672 
1673 		dpb paramBuff;
1674 		paramBuff.addParam(isc_spb_version);
1675 		paramBuff.addParam(isc_spb_current_version);
1676 		paramBuff.addCluster(isc_spb_user_name, user);
1677 		paramBuff.addCluster(isc_spb_password, pswd);
1678 
1679 		handle_ = 0L;
1680 		ib_error.check(dll.isc_service_attach(
1681 				  ib_error.getErrorVector(),
1682 				  service_host.GetCount(),
1683 				  service_host,
1684 				  &handle_,
1685 				  paramBuff.getBuffSize(),
1686 				  const_cast<char*>(paramBuff.getBuff())
1687 			  ));
1688 	}
1689 
1690 	void
detach()1691 	Service::detach()
1692 	{
1693 		ib_error.check(dll.isc_service_detach(
1694 				  ib_error.getErrorVector(),
1695 				  &handle_
1696 			  ));
1697 	}
1698 
1699 	void
executeCommand(const spb & pb)1700 	Service::executeCommand(const spb& pb)
1701 	{
1702 		ib_error.check(dll.isc_service_start(
1703 				  ib_error.getErrorVector(),
1704 				  &handle_,
1705 				  NULL,
1706 				  pb.getBuffSize(),
1707 				  const_cast<char*>(pb.getBuff())
1708 			  ));
1709 	}
1710 
1711 	void
query(const spb & request,const spb & result)1712 	Service::query(const spb& request, const spb& result)
1713 	{
1714 		spb flags_buff;
1715 
1716 		flags_buff.addParam(isc_spb_version);
1717 		flags_buff.addParam(isc_spb_current_version);
1718 		flags_buff.addCluster(isc_info_svc_timeout, 60);
1719 
1720 		ib_error.check(dll.isc_service_query(
1721 				  ib_error.getErrorVector(),
1722 				  &handle_,
1723 				  NULL,
1724 				  flags_buff.getBuffSize(), flags_buff.getBuff(),
1725 				  request.getBuffSize(), request.getBuff(),
1726 				  result.getBuffMaxSize(), result.getBuff()
1727 			  ));
1728 
1729 //         char spb_buffer[6], *spb = spb_buffer;
1730 //         char request_buffer[] = {
1731 //             isc_info_svc_version,
1732 //             isc_info_svc_server_version,
1733 //             isc_info_svc_implementation,
1734 //             isc_info_svc_get_env,
1735 //             isc_info_svc_get_env_lock,
1736 //             isc_info_svc_get_env_msg,
1737 //             isc_info_svc_get_licensed_users,
1738 //             isc_info_svc_user_dbpath
1739 //             };
1740 //         char result_buffer[1024], *p = result_buffer;
1741 //         memset(result_buffer, 0, sizeof(result_buffer));
1742 //
1743 //         // *spb++ = isc_info_svc_timeout;
1744 //         // ADD_SPB_NUMERIC(spb, 60); /* 1 minute timeout */
1745 //
1746 //         if (isc_service_query (
1747 //             ib_error.getErrorVector(),
1748 //             &handle_,
1749 //             NULL,
1750 //             spb - spb_buffer, spb_buffer,
1751 //             // sizeof(request_buffer), request_buffer,
1752 //             request.getBuffSize(), request.getBuff(),
1753 //             // sizeof(result_buffer), result_buffer
1754 //             result.getBuffMaxSize(), result.getBuff()
1755 //             )
1756 //         )
1757 //         {
1758 //             isc_print_status(ib_error.getErrorVector());
1759 //             isc_service_detach(ib_error.getErrorVector(), &handle_);
1760 //             return;
1761 //         }
1762 	}
1763 
1764 	///////////////////////////////////////////////////////////////////////////
user_info()1765 	user_info::user_info() :
1766 			user_id(0),
1767 			group_id(0)
1768 	{
1769 	}
1770 
user_info(const user_info & info)1771 	user_info::user_info(const user_info& info)
1772 	{
1773 		copy(info);
1774 	}
1775 
1776 	void
copy(const user_info & info)1777 	user_info::copy(const user_info& info)
1778 	{
1779 		user_id = info.user_id;
1780 		group_id = info.group_id;
1781 		user_name = info.user_name;
1782 		first_name = info.first_name;
1783 		middle_name = info.middle_name;
1784 		last_name = info.last_name;
1785 	}
1786 
1787 	///////////////////////////////////////////////////////////////////////////
server_info()1788 	server_info::server_info() :
1789 			svc_version(0),
1790 			num_licensed_users(0)
1791 	{
1792 	}
1793 
server_info(const server_info & info)1794 	server_info::server_info(const server_info& info)
1795 	{
1796 		copy(info);
1797 	}
1798 
1799 	void
copy(const server_info & info)1800 	server_info::copy(const server_info& info)
1801 	{
1802 		svc_version = info.svc_version;
1803 		num_licensed_users = info.num_licensed_users;
1804 		server_version = info.server_version;
1805 		implementation_str = info.implementation_str;
1806 		env_ib_str = info.env_ib_str;
1807 		env_lock_str = info.env_lock_str;
1808 		env_msg_str = info.env_msg_str;
1809 		user_db_path_str = info.user_db_path_str;
1810 	}
1811 
1812 	///////////////////////////////////////////////////////////////////////////
1813 	namespace svc_cmd
1814 	{
1815 		///////////////////////////////////////////////////////////////////////////
base(Service & svc)1816 		base::base(Service& svc) :
1817 				svc_ptr_(&svc)
1818 		{
1819 		}
1820 
1821 		unsigned long
read_long(char * & p) const1822 		base::read_long(char*& p) const
1823 		{
1824 			unsigned long result;
1825 
1826 			// p += sizeof(unsigned short);
1827 			result = (unsigned long)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(result));
1828 			p += sizeof(unsigned long);
1829 			return result;
1830 		}
1831 
1832 		unsigned short
read_short(char * & p) const1833 		base::read_short(char*& p) const
1834 		{
1835 			unsigned short result;
1836 
1837 			// p += sizeof(unsigned short);
1838 			result = (unsigned short)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(result));
1839 			p += sizeof(unsigned short);
1840 			return result;
1841 		}
1842 
1843 		String
read_string(char * & p) const1844 		base::read_string(char*& p) const
1845 		{
1846 			String result;
1847 			size_t str_length;
1848 
1849 			str_length = (unsigned short)svc_ptr_->get_dll().isc_portable_integer((unsigned char*)p, sizeof(unsigned short));
1850 			p += sizeof(unsigned short);
1851 			result = String(p, str_length);
1852 			p += str_length;
1853 			return result;
1854 		}
1855 
1856 		///////////////////////////////////////////////////////////////////////////
backup(Service & svc)1857 		backup::backup(Service& svc) :
1858 				base(svc)
1859 		{
1860 		}
1861 
1862 		///////////////////////////////////////////////////////////////////////////
restore(Service & svc)1863 		restore::restore(Service& svc) :
1864 				base(svc)
1865 		{
1866 		}
1867 
1868 		///////////////////////////////////////////////////////////////////////////
set_properties(Service & svc)1869 		set_properties::set_properties(Service& svc) :
1870 				base(svc)
1871 		{
1872 		}
1873 
1874 		///////////////////////////////////////////////////////////////////////////
repair(Service & svc)1875 		repair::repair(Service& svc) :
1876 				base(svc)
1877 		{
1878 		}
1879 
1880 		///////////////////////////////////////////////////////////////////////////
get_db_stats(Service & svc)1881 		get_db_stats::get_db_stats(Service& svc) :
1882 				base(svc)
1883 		{
1884 		}
1885 
1886 		///////////////////////////////////////////////////////////////////////////
get_server_info(Service & svc)1887 		get_server_info::get_server_info(Service& svc) :
1888 				base(svc)
1889 		{
1890 		}
1891 
1892 		void
execute()1893 		get_server_info::execute()
1894 		{
1895 			spb request;
1896 			spb result(1024);
1897 
1898 			// Prepare request ...
1899 			request.addParam(isc_info_svc_version);
1900 			request.addParam(isc_info_svc_server_version);
1901 			request.addParam(isc_info_svc_implementation);
1902 			request.addParam(isc_info_svc_get_env);
1903 			request.addParam(isc_info_svc_get_env_lock);
1904 			request.addParam(isc_info_svc_get_env_msg);
1905 			request.addParam(isc_info_svc_get_licensed_users);
1906 			request.addParam(isc_info_svc_user_dbpath);
1907 
1908 			// Execute ...
1909 			svc_ptr_->query(request, result);
1910 
1911 			// Parse results ...
1912 			char* p = const_cast<char*>(result.getBuff());
1913 
1914 			do
1915 			{
1916 				switch (*p++)
1917 				{
1918 				case isc_info_truncated:
1919 					throw DbExc("Server information was truncated.");
1920 					break;
1921 				case isc_info_svc_version:
1922 					info_.svc_version = read_long(p);
1923 					break;
1924 				case isc_info_svc_get_licensed_users:
1925 					info_.num_licensed_users = read_long(p);
1926 					break;
1927 				case isc_info_svc_server_version:
1928 					info_.server_version = read_string(p);
1929 					break;
1930 				case isc_info_svc_implementation:
1931 					info_.implementation_str = read_string(p);
1932 					break;
1933 				case isc_info_svc_get_env:
1934 					info_.env_ib_str = read_string(p);
1935 					break;
1936 				case isc_info_svc_get_env_lock:
1937 					info_.env_lock_str = read_string(p);
1938 					break;
1939 				case isc_info_svc_get_env_msg:
1940 					info_.env_msg_str = read_string(p);
1941 					break;
1942 				case isc_info_svc_user_dbpath:
1943 					info_.user_db_path_str = read_string(p);
1944 					break;
1945 				}
1946 			}
1947 			while (*p);
1948 		}
1949 
1950 		///////////////////////////////////////////////////////////////////////////
get_log(Service & svc)1951 		get_log::get_log(Service& svc) :
1952 				base(svc)
1953 		{
1954 		}
1955 
1956 		///////////////////////////////////////////////////////////////////////////
get_user_info(Service & svc,const String & user_name)1957 		get_user_info::get_user_info(Service& svc, const String& user_name) :
1958 				base(svc),
1959 				user_name_(user_name)
1960 		{
1961 			paramBuff_.addParam(isc_action_svc_display_user);
1962 			paramBuff_.addCluster(isc_spb_sec_username, user_name);
1963 		}
1964 
1965 		void
execute()1966 		get_user_info::execute()
1967 		{
1968 			spb request;
1969 			spb result(1024);
1970 
1971 			unsigned short loop;
1972 
1973 			// Executea task ...
1974 			svc_ptr_->executeCommand(paramBuff_);
1975 
1976 			// Prepare request ...
1977 			request.addParam(isc_info_svc_get_users);
1978 
1979 			// Execute ...
1980 			svc_ptr_->query(request, result);
1981 
1982 			// Parse results ...
1983 			char* p = const_cast<char*>(result.getBuff());
1984 
1985 			do
1986 			{
1987 				switch (*p++)
1988 				{
1989 				case isc_info_truncated:
1990 					throw DbExc("User information was truncated.");
1991 					break;
1992 				case isc_info_svc_get_users:
1993 					loop = read_short(p);
1994 					while (*p != isc_info_end)
1995 					{
1996 						switch (*p++)
1997 						{
1998 						case isc_spb_sec_username:
1999 							info_.user_name = read_string(p);
2000 							loop -= (info_.user_name.GetCount() + sizeof(unsigned short) + 1);
2001 							break;
2002 						case isc_spb_sec_firstname:
2003 							info_.first_name = read_string(p);
2004 							loop -= (info_.first_name.GetCount() + sizeof(unsigned short) + 1);
2005 							break;
2006 						case isc_spb_sec_middlename:
2007 							info_.middle_name = read_string(p);
2008 							loop -= (info_.middle_name.GetCount() + sizeof(unsigned short) + 1);
2009 							break;
2010 						case isc_spb_sec_lastname:
2011 							info_.last_name = read_string(p);
2012 							loop -= (info_.last_name.GetCount() + sizeof(unsigned short) + 1);
2013 							break;
2014 						case isc_spb_sec_groupid:
2015 							info_.group_id = read_long(p);
2016 							loop -= (sizeof(unsigned long) + 1);
2017 							break;
2018 						case isc_spb_sec_userid:
2019 							info_.user_id = read_long(p);
2020 							loop -= (sizeof(unsigned long) + 1);
2021 							break;
2022 						}
2023 					}
2024 					break;
2025 				}
2026 			}
2027 			while (*p);
2028 		}
2029 
2030 		///////////////////////////////////////////////////////////////////////////
get_users(Service & svc)2031 		get_users::get_users(Service& svc) :
2032 				base(svc)
2033 		{
2034 			paramBuff_.addParam(isc_action_svc_display_user);
2035 		}
2036 
2037 		void
execute()2038 		get_users::execute()
2039 		{
2040 			spb request;
2041 			spb result(1024);
2042 
2043 			unsigned short loop;
2044 
2045 			// Executea task ...
2046 			svc_ptr_->executeCommand(paramBuff_);
2047 
2048 			// Prepare request ...
2049 			request.addParam(isc_info_svc_get_users);
2050 
2051 			// Execute ...
2052 			svc_ptr_->query(request, result);
2053 
2054 			// Parse results ...
2055 			char* p = const_cast<char*>(result.getBuff());
2056 			user_info info;
2057 
2058 			do
2059 			{
2060 				switch (*p++)
2061 				{
2062 				case isc_info_truncated:
2063 					throw DbExc("User list information was truncated.");
2064 					break;
2065 				case isc_info_svc_get_users:
2066 					loop = read_short(p);
2067 					while (*p != isc_info_end)
2068 					{
2069 						switch (*p++)
2070 						{
2071 						case isc_spb_sec_username:
2072 							if (!info.user_name.IsEmpty())
2073 							{
2074 								user_info_list_.push_back(info);
2075 								info = user_info();
2076 							}
2077 							info.user_name = read_string(p);
2078 							loop -= (info.user_name.GetCount() + sizeof(unsigned short) + 1);
2079 							break;
2080 						case isc_spb_sec_firstname:
2081 							info.first_name = read_string(p);
2082 							loop -= (info.first_name.GetCount() + sizeof(unsigned short) + 1);
2083 							break;
2084 						case isc_spb_sec_middlename:
2085 							info.middle_name = read_string(p);
2086 							loop -= (info.middle_name.GetCount() + sizeof(unsigned short) + 1);
2087 							break;
2088 						case isc_spb_sec_lastname:
2089 							info.last_name = read_string(p);
2090 							loop -= (info.last_name.GetCount() + sizeof(unsigned short) + 1);
2091 							break;
2092 						case isc_spb_sec_groupid:
2093 							info.group_id = read_long(p);
2094 							loop -= (sizeof(unsigned long) + 1);
2095 							break;
2096 						case isc_spb_sec_userid:
2097 							info.user_id = read_long(p);
2098 							loop -= (sizeof(unsigned long) + 1);
2099 							break;
2100 						}
2101 					}
2102 					break;
2103 				}
2104 			}
2105 			while (*p);
2106 
2107 			if (!info.user_name.IsEmpty())
2108 			{
2109 				user_info_list_.push_back(info);
2110 				info = user_info();
2111 			}
2112 		}
2113 
2114 		///////////////////////////////////////////////////////////////////////////
add_user(Service & svc)2115 		add_user::add_user(Service& svc) :
2116 				base(svc)
2117 		{
2118 			paramBuff_.addParam(isc_action_svc_add_user);
2119 		}
2120 
2121 		void
execute()2122 		add_user::execute()
2123 		{
2124 			svc_ptr_->executeCommand(paramBuff_);
2125 		}
2126 
2127 		void
set_username(const char * name)2128 		add_user::set_username(const char* name)
2129 		{
2130 			paramBuff_.addCluster(isc_spb_sec_username, name);
2131 		}
2132 
2133 		void
set_password(const char * pswd)2134 		add_user::set_password(const char* pswd)
2135 		{
2136 			paramBuff_.addCluster(isc_spb_sec_password, pswd);
2137 		}
2138 
2139 		void
set_firstname(const char * value)2140 		add_user::set_firstname(const char* value)
2141 		{
2142 			paramBuff_.addCluster(isc_spb_sec_firstname, value);
2143 		}
2144 
2145 		void
set_middlename(const char * value)2146 		add_user::set_middlename(const char* value)
2147 		{
2148 			paramBuff_.addCluster(isc_spb_sec_middlename, value);
2149 		}
2150 
2151 		void
set_lastname(const char * value)2152 		add_user::set_lastname(const char* value)
2153 		{
2154 			paramBuff_.addCluster(isc_spb_sec_lastname, value);
2155 		}
2156 
2157 		void
set_userid(unsigned long value)2158 		add_user::set_userid(unsigned long value)
2159 		{
2160 			paramBuff_.addCluster(isc_spb_sec_userid, value);
2161 		}
2162 
2163 		void
set_groupid(unsigned long value)2164 		add_user::set_groupid(unsigned long value)
2165 		{
2166 			paramBuff_.addCluster(isc_spb_sec_groupid, value);
2167 		}
2168 
2169 		void
set_groupname(const char * value)2170 		add_user::set_groupname(const char* value)
2171 		{
2172 			paramBuff_.addCluster(isc_spb_sec_groupname, value);
2173 		}
2174 
2175 		void
set_rolename(const char * value)2176 		add_user::set_rolename(const char* value)
2177 		{
2178 			paramBuff_.addCluster(isc_spb_sql_role_name, value);
2179 		}
2180 
2181 		///////////////////////////////////////////////////////////////////////////
delete_user(Service & svc)2182 		delete_user::delete_user(Service& svc) :
2183 				base(svc)
2184 		{
2185 			paramBuff_.addParam(isc_action_svc_delete_user);
2186 		}
2187 
2188 		void
execute()2189 		delete_user::execute()
2190 		{
2191 			svc_ptr_->executeCommand(paramBuff_);
2192 		}
2193 
2194 		void
set_username(const char * name)2195 		delete_user::set_username(const char* name)
2196 		{
2197 			paramBuff_.addCluster(isc_spb_sec_username, name);
2198 		}
2199 
2200 		void
set_rolename(const char * value)2201 		delete_user::set_rolename(const char* value)
2202 		{
2203 			paramBuff_.addCluster(isc_spb_sql_role_name, value);
2204 		}
2205 
2206 		///////////////////////////////////////////////////////////////////////////
update_user(Service & svc)2207 		update_user::update_user(Service& svc) :
2208 				base(svc)
2209 		{
2210 			paramBuff_.addParam(isc_action_svc_modify_user);
2211 		}
2212 
2213 		void
execute()2214 		update_user::execute()
2215 		{
2216 			svc_ptr_->executeCommand(paramBuff_);
2217 		}
2218 
2219 		void
set_username(const char * name)2220 		update_user::set_username(const char* name)
2221 		{
2222 			paramBuff_.addCluster(isc_spb_sec_username, name);
2223 		}
2224 
2225 		void
set_password(const char * pswd)2226 		update_user::set_password(const char* pswd)
2227 		{
2228 			paramBuff_.addCluster(isc_spb_sec_password, pswd);
2229 		}
2230 
2231 		void
set_firstname(const char * value)2232 		update_user::set_firstname(const char* value)
2233 		{
2234 			paramBuff_.addCluster(isc_spb_sec_firstname, value);
2235 		}
2236 
2237 		void
set_middlename(const char * value)2238 		update_user::set_middlename(const char* value)
2239 		{
2240 			paramBuff_.addCluster(isc_spb_sec_middlename, value);
2241 		}
2242 
2243 		void
set_lastname(const char * value)2244 		update_user::set_lastname(const char* value)
2245 		{
2246 			paramBuff_.addCluster(isc_spb_sec_lastname, value);
2247 		}
2248 
2249 		void
set_userid(unsigned long value)2250 		update_user::set_userid(unsigned long value)
2251 		{
2252 			paramBuff_.addCluster(isc_spb_sec_userid, value);
2253 		}
2254 
2255 		void
set_groupid(unsigned long value)2256 		update_user::set_groupid(unsigned long value)
2257 		{
2258 			paramBuff_.addCluster(isc_spb_sec_groupid, value);
2259 		}
2260 
2261 		void
set_groupname(const char * value)2262 		update_user::set_groupname(const char* value)
2263 		{
2264 			paramBuff_.addCluster(isc_spb_sec_groupname, value);
2265 		}
2266 
2267 		void
set_rolename(const char * value)2268 		update_user::set_rolename(const char* value)
2269 		{
2270 			paramBuff_.addCluster(isc_spb_sql_role_name, value);
2271 		}
2272 
2273 		///////////////////////////////////////////////////////////////////////////
add_license(Service & svc)2274 		add_license::add_license(Service& svc) :
2275 				base(svc)
2276 		{
2277 		}
2278 
2279 		///////////////////////////////////////////////////////////////////////////
remove_license(Service & svc)2280 		remove_license::remove_license(Service& svc) :
2281 				base(svc)
2282 		{
2283 		}
2284 
2285 	}
2286 
2287 	///////////////////////////////////////////////////////////////////////////
Array(const DataBase & db,const Transaction & tr)2288 	Array::Array(const DataBase& db, const Transaction& tr)
2289 	: pDBHandle_(db.getHandleP())
2290 	, pTRHandle_(tr.getHandleP())
2291 	{
2292 		id_.gds_quad_low = 0;
2293 		id_.gds_quad_high = 0;
2294 	}
2295 
2296 // ISC_STATUS  ISC_EXPORT isc_array_gen_sdl (ISC_STATUS ISC_FAR *,
2297 //                       ISC_ARRAY_DESC ISC_FAR *,
2298 //                       short ISC_FAR *,
2299 //                       char ISC_FAR *,
2300 //                       short ISC_FAR *);
2301 //
2302 // ISC_STATUS  ISC_EXPORT isc_array_get_slice (ISC_STATUS ISC_FAR *,
2303 //                         isc_db_handle ISC_FAR *,
2304 //                         isc_tr_handle ISC_FAR *,
2305 //                         ISC_QUAD ISC_FAR *,
2306 //                         ISC_ARRAY_DESC ISC_FAR *,
2307 //                         void ISC_FAR *,
2308 //                         ISC_LONG ISC_FAR *);
2309 //
2310 // ISC_STATUS  ISC_EXPORT isc_array_lookup_bounds (ISC_STATUS ISC_FAR *,
2311 //                         isc_db_handle ISC_FAR *,
2312 //                         isc_tr_handle ISC_FAR *,
2313 //                         char ISC_FAR *,
2314 //                         char ISC_FAR *,
2315 //                         ISC_ARRAY_DESC ISC_FAR *);
2316 //
2317 // ISC_STATUS  ISC_EXPORT isc_array_lookup_desc (ISC_STATUS ISC_FAR *,
2318 //                           isc_db_handle ISC_FAR *,
2319 //                           isc_tr_handle ISC_FAR *,
2320 //                           char ISC_FAR *,
2321 //                           char ISC_FAR *,
2322 //                           ISC_ARRAY_DESC ISC_FAR *);
2323 //
2324 // ISC_STATUS  ISC_EXPORT isc_array_set_desc (ISC_STATUS ISC_FAR *,
2325 //                        char ISC_FAR *,
2326 //                        char ISC_FAR *,
2327 //                        short ISC_FAR *,
2328 //                        short ISC_FAR *,
2329 //                        short ISC_FAR *,
2330 //                        ISC_ARRAY_DESC ISC_FAR *);
2331 //
2332 // ISC_STATUS  ISC_EXPORT isc_array_put_slice (ISC_STATUS ISC_FAR *,
2333 //                         isc_db_handle ISC_FAR *,
2334 //                         isc_tr_handle ISC_FAR *,
2335 //                         ISC_QUAD ISC_FAR *,
2336 //                         ISC_ARRAY_DESC ISC_FAR *,
2337 //                         void ISC_FAR *,
2338 //                         ISC_LONG ISC_FAR *);
2339 //
2340 // ISC_STATUS  ISC_EXPORT isc_get_slice (ISC_STATUS ISC_FAR *,
2341 //                       isc_db_handle ISC_FAR *,
2342 //                       isc_tr_handle ISC_FAR *,
2343 //                       ISC_QUAD ISC_FAR *,
2344 //                       short,
2345 //                       char ISC_FAR *,
2346 //                       short,
2347 //                       ISC_LONG ISC_FAR *,
2348 //                       ISC_LONG,
2349 //                       void ISC_FAR *,
2350 //                       ISC_LONG ISC_FAR *);
2351 //
2352 // ISC_STATUS  ISC_EXPORT isc_put_slice (ISC_STATUS ISC_FAR *,
2353 //                       isc_db_handle ISC_FAR *,
2354 //                       isc_tr_handle ISC_FAR *,
2355 //                       ISC_QUAD ISC_FAR *,
2356 //                       short,
2357 //                       char ISC_FAR *,
2358 //                       short,
2359 //                       ISC_LONG ISC_FAR *,
2360 //                       ISC_LONG,
2361 //                       void ISC_FAR *);
2362 //
2363 
2364 	///////////////////////////////////////////////////////////////////////////
Event()2365 	Event::Event()
2366 	{
2367 	}
2368 
2369 // ISC_STATUS  ISC_EXPORT isc_cancel_events (ISC_STATUS ISC_FAR *,
2370 //                       isc_db_handle ISC_FAR *,
2371 //                       ISC_LONG ISC_FAR *);
2372 //
2373 // ISC_LONG    ISC_EXPORT_VARARG isc_event_block (char ISC_FAR * ISC_FAR *,
2374 //                            char ISC_FAR * ISC_FAR *,
2375 //                            unsigned short, ...);
2376 //
2377 // void        ISC_EXPORT isc_event_counts (unsigned ISC_LONG ISC_FAR *,
2378 //                      short,
2379 //                      char ISC_FAR *,
2380 //                      char ISC_FAR *);
2381 //
2382 // ISC_STATUS  ISC_EXPORT isc_que_events (ISC_STATUS ISC_FAR *,
2383 //                        isc_db_handle ISC_FAR *,
2384 //                        ISC_LONG ISC_FAR *,
2385 //                        short,
2386 //                        char ISC_FAR *,
2387 //                        isc_callback,
2388 //                        void ISC_FAR *);
2389 //
2390 // ISC_STATUS  ISC_EXPORT isc_wait_for_event (ISC_STATUS ISC_FAR *,
2391 //                        isc_db_handle ISC_FAR *,
2392 //                        short,
2393 //                        char ISC_FAR *,
2394 //                        char ISC_FAR *);
2395 
2396 }
2397