1 // vi: noexpandtab:tabstop=4
2 #ifndef _firebird_fb_h_
3 #define _firebird_fb_h_
4 
5 /*
6 	Author: Sergey Sikorskiy (www.sikorskiy.net)
7 	License: BSD
8 */
9 
10 #include <Sql/Sql.h>
11 #include "lib/ibase.h"
12 
13 #ifdef PLATFORM_WIN32
14 	#define DLLFILENAME "fbclient.dll"
15 	#define DLLCALL     __stdcall
16 #else
17 	#define DLLFILENAME "libfbclient.so"
18 #endif
19 #define DLIMODULE   FB
20 #define DLIHEADER   <Firebird/Firebird.dli>
21 #include <Core/dli_header.h>
22 
23 namespace ibpp
24 {
25 	using namespace Upp;
26 
27 	class DbExc : public SqlExc
28 	{
29 	public:
30 	#ifndef NOAPPSQL
31 		DbExc();
32 	#endif
DbExc(const SqlSession & session)33 		DbExc(const SqlSession& session) : SqlExc(session), err_num(0) {}
DbExc(const Sql & sql)34 		DbExc(const Sql& sql) : SqlExc(sql), err_num(0) {}
SqlExc(desc)35 		DbExc(const String& desc, int en = 0) : SqlExc(desc), err_num(en) {}
SqlExc(desc)36 		DbExc(const char *desc, int en = 0) : SqlExc(desc), err_num(en) {}
37 
38 	public:
GetErrNum()39 		int GetErrNum() const { return err_num; }
40 
41 	private:
42 		int err_num;
43 	};
44 
45 	///////////////////////////////////////////////////////////////////////////
46 	// To do: parse the status vector by myself.
47 	class Error
48 	{
49 	public:
Error(T_FB & dll)50 		Error(T_FB& dll) : dll(dll) {}
51 
getErrorVector()52 		ISC_STATUS* getErrorVector()
53 		{
54 			return status_vector_;
55 		}
56 
57 	public:
58 		long getSQLCode();
59 		String getErrorText();
60 		void check();
61 
get_err_code()62 		long get_err_code() const
63 		{
64 			return status_vector_[1];
65 		}
66 
check(ISC_STATUS rc)67 		void check(ISC_STATUS rc)
68 		{
69 			if (rc)
70 				check();
71 		}
72 
73 	protected:
74 		T_FB&       dll;
75 
76 	private:
77 		long        sqlCode_;
78 		ISC_STATUS  status_vector_[20];
79 		char        msg_[1024];
80 	};
81 
82 	class dpb
83 	{
84 	public:
85 		dpb();
86 
87 	public:
getBuff()88 		const char* getBuff() const
89 		{
90 			return buff_;
91 		}
getBuffSize()92 		short getBuffSize() const
93 		{
94 			return pos_;
95 		}
96 
97 	public:
98 		void addParam(char value);
99 		void addCluster(char type, const char* value);
100 		void addCluster(char type, short value);
101 		void addCluster(char type, bool value);
102 		void addCluster(char type, char value);
103 		void addCluster(char type, unsigned long value);
104 
105 	private:
106 		char    buff_[1024];
107 		short   pos_;
108 	};
109 
110 	// ServiceParamBuff (SPB) differs in some ways from the DatabaseParamBuff (DPB) ...
111 	class spb
112 	{
113 	public:
114 		spb(size_t buff_size = 128);
115 		~spb();
116 
117 	public:
getBuff()118 		char* getBuff() const
119 		{
120 			return buff_ptr_;
121 		}
getBuffSize()122 		short getBuffSize() const
123 		{
124 			return pos_;
125 		}
getBuffMaxSize()126 		short getBuffMaxSize() const
127 		{
128 			return buff_size_;
129 		}
130 
131 	public:
132 		void addParam(char value);
133 		void addCluster(char type, const char* value);
134 		void addCluster(char type, unsigned long value);
135 
136 	public:
get_long()137 		unsigned long get_long()
138 		{
139 			return 0;
140 		}
141 
142 	private:
143 		char*           buff_ptr_;
144 		const size_t    buff_size_;
145 		unsigned short  pos_;
146 	};
147 
148 	class DBParamBuff : public dpb
149 	{
150 	public:
151 		DBParamBuff();
152 	};
153 
154 	class DataBase
155 	{
156 	public:
157 		DataBase(T_FB& dll, Error& ib_error);
158 
159 	public:
getHandleP()160 		isc_db_handle* getHandleP() const
161 		{
162 			return &handle_;
163 		}
getHandleRef()164 		isc_db_handle& getHandleRef()
165 		{
166 			return handle_;
167 		}
168 
169 	public:
170 		void attach(const char* name);
171 		void dettach();
172 
173 		void drop();
174 
175 		// This method will not create an attached handle. Use the "attach" method instead of this one.
176 		void execute_immediate(const String& stmt);
177 
178 		void expand_dpb() const;
179 		void modify_dpb() const;
180 		void getInfo() const;
181 
182 		void retrieveVersion();
183 
184 	public:
185 		// User validation
186 
187 		// String user name, up to 255 characters
setUserName(const char * value)188 		void setUserName(const char* value)
189 		{
190 			paramBuff_.addCluster(isc_dpb_user_name, value);
191 		}
192 		// String password, up to 255 characters
setPassword(const char * value)193 		void setPassword(const char* value)
194 		{
195 			paramBuff_.addCluster(isc_dpb_password, value);
196 		}
197 		// String encrypted password, up to 255 characters
setEncPassword(const char * value)198 		void setEncPassword(const char* value)
199 		{
200 			paramBuff_.addCluster(isc_dpb_password_enc, value);
201 		}
setRoleName(const char * value)202 		void setRoleName(const char* value)
203 		{
204 			paramBuff_.addCluster(isc_dpb_sql_role_name, value);
205 		}
206 		// String system DBA name, up to 255 characters
setSysUserName(const char * value)207 		void setSysUserName(const char* value)
208 		{
209 			paramBuff_.addCluster(isc_dpb_sys_user_name, value);
210 		}
setLicense(const char * value)211 		void setLicense(const char* value)
212 		{
213 			paramBuff_.addCluster(isc_dpb_license, value);
214 		}
setEncryptionKey(const char * value)215 		void setEncryptionKey(const char* value)
216 		{
217 			paramBuff_.addCluster(isc_dpb_encrypt_key, value);
218 		}
219 
220 	public:
221 		// Environmental control
222 
223 		// Number of database cache buffers to allocate for use with the database;
224 		void setNumBuffers(short value = 2048)
225 		{
226 			paramBuff_.addCluster(isc_dpb_num_buffers, value);
227 		}
228 		// Scope of dbkey context. 0 limits scope to the current transaction,
229 		// 1 extends scope to the database session
setDBKeyScope(char value)230 		void setDBKeyScope(char value)
231 		{
232 			paramBuff_.addCluster(isc_dpb_dbkey_scope, value);
233 		}
234 		// 1 - V5.x & V6 compatible; 2 - diagnostic; 3 - V6 only
setSQLDialect(char value)235 		void setSQLDialect(char value)
236 		{
237 			paramBuff_.addCluster(isc_dpb_sql_dialect, value);
238 		}
239 		// 1 - V5.x & V6 compatible; 2 - diagnostic; 3 - V6 only
setDBSQLDialect(char value)240 		void setDBSQLDialect(char value)
241 		{
242 			paramBuff_.addCluster(isc_dpb_set_db_sql_dialect, value);
243 		}
244 
245 	public:
246 		// System management
247 
248 		// Specifies whether database writes are synchronous or asynchronous.
setSynchWrites(bool value)249 		void setSynchWrites(bool value)
250 		{
251 			paramBuff_.addCluster(isc_dpb_force_write, value);
252 		}
253 		// Specify whether the database should reserves pace on each page for back versions of records when modifications are made
254 		void setReserveSpace(bool value = false)
255 		{
256 			paramBuff_.addCluster(isc_dpb_no_reserve, !value);
257 		}
258 
259 	public:
260 		// System management
setAsDamaged(bool value)261 		void setAsDamaged(bool value)
262 		{
263 			paramBuff_.addCluster(isc_dpb_damaged, value);
264 		}
setVerify(bool value)265 		void setVerify(bool value)
266 		{
267 			paramBuff_.addCluster(isc_dpb_verify, value);
268 		}
269 
270 	public:
271 		// Shadow control ( !!! Ignored by DB )
setActivateShadow(bool value)272 		void setActivateShadow(bool value)
273 		{
274 			paramBuff_.addCluster(isc_dpb_activate_shadow, value);
275 		}
setDeleteShadow(bool value)276 		void setDeleteShadow(bool value)
277 		{
278 			paramBuff_.addCluster(isc_dpb_delete_shadow, value);
279 		}
280 
281 	public:
282 		// Replay logging system control
setStartLog(bool value)283 		void setStartLog(bool value)
284 		{
285 			paramBuff_.addCluster(isc_dpb_begin_log, value);
286 		}
setEndLog(bool value)287 		void setEndLog(bool value)
288 		{
289 			paramBuff_.addCluster(isc_dpb_quit_log, value);
290 		}
291 
292 	public:
293 		// Character set and message file specification
294 
295 		// Language-specific message file
setMessageFile(const char * value)296 		void setMessageFile(const char* value)
297 		{
298 			paramBuff_.addCluster(isc_dpb_lc_messages, value);
299 		}
300 		// Character set to be utilized
setCharSet(const char * value)301 		void setCharSet(const char* value)
302 		{
303 			paramBuff_.addCluster(isc_dpb_lc_ctype, value);
304 		}
305 
306 	private:
307 		mutable isc_db_handle	handle_;
308 		DBParamBuff     		paramBuff_;
309 		T_FB& dll;
310 		Error& ib_error;
311 
312 	public:
313 		// Because I cannot make a friend function ...
314 		String     dbVersion_;
315 		String     odsVersion_;
316 	};
317 
318 	class Transaction
319 	{
320 	public:
321 		Transaction(T_FB& dll, Error& ib_error);
322 
323 	public:
getHandleP()324 		isc_tr_handle* getHandleP() const
325 		{
326 			return &handle_;
327 		}
getHandleRef()328 		isc_tr_handle& getHandleRef()
329 		{
330 			return handle_;
331 		}
332 
333 	public:
334 		// Starts a new transaction against one or more databases.; use a
335 		// previously declared and populated TPB
336 		void start(const DataBase& db);
337 
338 		void start_multiple();
339 		// Commits a transactions changes, and ends the transaction
340 
341 		void commit();
342 
343 		// Commits a transactions changes, and preserves the transaction
344 		// context for further transaction processing
345 		void commit_retaining();
346 
347 		// Rolls back a transactions changes, and ends the transaction
348 		void rollback();
349 		// Rolls back a transactions changes but maintains transaction context
350 
351 		void rollback_retaining();
352 
353 		// Performs the first phase of a two-phase commit, prior to calling
354 		// isc_commit_transaction(); used to coordinate a two-phase commit
355 		// with some external event
356 		void prepare();
357 
358 		// Performs the first phase of a two-phase commit, prior to calling
359 		// isc_commit_transaction(); used to coordinate a two-phase commit
360 		// with some external event. This call accepts a message describing the
361 		// external event
362 		void prepare2();
363 		// Returns information about the specified named transaction.
364 		void getInfo();
365 
366 	public:
367 		// InterBase version 3 transaction
setVersion3()368 		void setVersion3()
369 		{
370 			paramBuff_.addParam(isc_tpb_version3);
371 		}
372 		// Table-locking transaction model. This mode is serializable.
setConsistency()373 		void setConsistency()
374 		{
375 			paramBuff_.addParam(isc_tpb_consistency);
376 		}
377 		// High throughput, high concurrency transaction with repeat able read
378 		// consistency. This mode takes full advantage of the InterBase
379 		// multi-generational transaction model [Default].
setConcurrency()380 		void setConcurrency()
381 		{
382 			paramBuff_.addParam(isc_tpb_concurrency);
383 		}
384 		// Concurrent, shared access of a specified table among all transactions; use
385 		// in conjunction with isc_tpb_lock_read and isc_tpb_lock_write to
386 		// establish the lock option [Default].
setShared()387 		void setShared()
388 		{
389 			paramBuff_.addParam(isc_tpb_shared);
390 		}
391 		// Concurrent, restricted access of a specified table; use in conjunction with
392 		// isc_tpb_lock_read and isc_tpb_lock_write to establish the lock option.
setProtected()393 		void setProtected()
394 		{
395 			paramBuff_.addParam(isc_tpb_protected);
396 		}
397 		// isc_tpb_wait = Specifies that the transaction is to wait until the conflicting resource is
398 		// released before retrying an operation [Default].
399 		//
400 		// isc_tpb_nowait - Specifies that the transaction is not to wait for the resource to be released,
401 		// but instead, an update conflict error should be returned immediately
402 		void setWait(bool wait = true)
403 		{
404 			if (wait)
405 			{
406 				paramBuff_.addParam(isc_tpb_wait);
407 			}
408 			else
409 			{
410 				paramBuff_.addParam(isc_tpb_nowait);
411 			}
412 		}
413 		// Read-only access mode that allows a transaction only to select data from
414 		// tables
setReadOnly()415 		void setReadOnly()
416 		{
417 			paramBuff_.addParam(isc_tpb_read);
418 		}
419 		// Read-write access mode of that allows a transaction to select, insert,
420 		// update, and delete table data [Default].
setReadWrite()421 		void setReadWrite()
422 		{
423 			paramBuff_.addParam(isc_tpb_write);
424 		}
425 		// Read-only access of a specified table. Use in conjunction with
426 		// isc_tpb_shared, isc_tpb_protected, and isc_tpb_exclusive to establish the
427 		// lock option.
setLockReadOnly()428 		void setLockReadOnly()
429 		{
430 			paramBuff_.addParam(isc_tpb_lock_read);
431 		}
432 		// Read-write access of a specified table. Use in conjunction with
433 		// isc_tpb_shared, isc_tpb_protected, and isc_tpb_exclusive to establish the
434 		// lock option [Default].
setLockReadWrite()435 		void setLockReadWrite()
436 		{
437 			paramBuff_.addParam(isc_tpb_lock_write);
438 		}
439 		// High throughput, high concurrency transaction that can read changes
440 		// committed by other concurrent transactions. Transactions in this mode do
441 		// not provide repeatable read.
setReadCommitted()442 		void setReadCommitted()
443 		{
444 			paramBuff_.addParam(isc_tpb_read_committed);
445 		}
446 		// Enables an isc_tpb_read_committed transaction to read the most recently
447 		// committed version of a record even if other, uncommitted versions are
448 		// pending.
setRecVersion()449 		void setRecVersion()
450 		{
451 			paramBuff_.addParam(isc_tpb_rec_version);
452 		}
453 		// Enables an isc_tpb_read_committed transaction to read only the latest
454 		// committed version of a record. If an uncommitted version of a record is
455 		// pending and isc_tpb_wait is also specified, then the transaction waits for
456 		// the pending record to be committed or rolled back before proceeding.
457 		// Otherwise, a lock conflict error is reported at once.
setNoRecVersion()458 		void setNoRecVersion()
459 		{
460 			paramBuff_.addParam(isc_tpb_no_rec_version);
461 		}
462 
463 	private:
464 		mutable isc_tr_handle	handle_;
465 		dpb       				paramBuff_;
466 		T_FB&                   dll;
467 		Error&                  ib_error;
468 	};
469 
470 	class SQLDataArray
471 	{
472 	public:
473 		SQLDataArray(size_t size = 0);
474 		SQLDataArray(const SQLDataArray& theArray);
475 		~SQLDataArray();
476 
477 	public:
getBuffer()478 		XSQLDA* getBuffer() const
479 		{
480 			return pDA_;
481 		}
getSize()482 		size_t getSize() const
483 		{
484 			return size_;
485 		}
getRequredSize()486 		int getRequredSize() const
487 		{
488 			ASSERT(pDA_);
489 			return pDA_->sqld;
490 		}
491 
492 	public:
493 		// Pos is ZERO-based ...
494 		XSQLVAR& operator[](size_t pos)
495 		{
496 			XSQLVAR* first_ptr = pDA_->sqlvar;
497 			return first_ptr[pos];
498 		}
499 
500 	public:
501 		void setSize(size_t size);
502 
503 	private:
504 		XSQLDA* pDA_;
505 		size_t  size_;
506 	};
507 
508 	class DynamicSQL
509 	{
510 	public:
511 		DynamicSQL(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error);
512 		~DynamicSQL();
513 
514 	public:
515 		void execute_immediate(const String& stmt);
516 		void execute_immediate_no_trans(const String& stmt);
517 
518 		void execute_immediate_data(const String& stmt);
519 
520 		// define_da is a data array, which is used to describe output arguments.
521 		void prepare(const String& stmt, const SQLDataArray& define_da);
522 
523 		void execute();
524 
525 		void execute2();
526 
527 		// Retrieve "in" information.
528 		void describe_bind(const SQLDataArray& da);
529 
530 		// Retrieve "out" information.
531 		void describe_define(const SQLDataArray& da);
532 
533 		void setCursorName(const char* name);
534 
535 		bool fetch();
536 
537 		// Like isc_info_sql_stmt_select
538 		int getStmtType();
539 
540 		void close_cursor();
541 
542 	public:
setINSize(size_t size)543 		void setINSize(size_t size)
544 		{
545 			inDataArray_.setSize(size);
546 		}
getINVar(size_t pos)547 		XSQLVAR* getINVar(size_t pos) const
548 		{
549 			ASSERT(pos < inDataArray_.getSize());
550 			return &inDataArray_.getBuffer()->sqlvar[pos];
551 		}
setOUTSize(size_t size)552 		void setOUTSize(size_t size)
553 		{
554 			outDataArray_.setSize(size);
555 		}
getOUTVar(size_t pos)556 		XSQLVAR* getOUTVar(size_t pos) const
557 		{
558 			ASSERT(pos < outDataArray_.getSize());
559 			return &outDataArray_.getBuffer()->sqlvar[pos];
560 		}
561 
GetIn()562 		SQLDataArray& GetIn()
563 		{
564 			return inDataArray_;
565 		}
GetOut()566 		SQLDataArray& GetOut()
567 		{
568 			return outDataArray_;
569 		}
570 
571 	private:
572 		// Constructor-destructor
573 		void allocate_stmt();
574 		void allocate_stmt2();
575 
576 		void drop_statement();
577 
578 	private:
579 		unsigned short  dialect_;
580 
581 		isc_db_handle*  pDBHandle_;
582 		isc_tr_handle*  pTRHandle_;
583 
584 		T_FB&           dll;
585 		Error&          ib_error;
586 
587 		isc_stmt_handle handle_;        // It is a pointer, actualy.
588 
589 		SQLDataArray    inDataArray_;
590 		SQLDataArray    outDataArray_;
591 
592 		bool            all_data_fetched_; // A workaround for problems that were introduced in v1.5.2.
593 	};
594 
595 	class EmbededSQL
596 	{
597 	public:
598 		EmbededSQL();
599 
600 	private:
601 	};
602 
603 	class SegmentBlob;
604 	class BlobDescr
605 	{
606 	public:
BlobDescr(T_FB & dll,Error & ib_error)607 	    BlobDescr(T_FB& dll, Error& ib_error) : dll(dll), ib_error(ib_error) {}
608 
609 		// Determines the subtype, character set, and segment size of a SegmentBlob, given a table name
610 		// and SegmentBlob column name.
611 		void get(
612 			SegmentBlob& blob,
613 			const String& tbl_name,
614 			const String& clm_name
615 		);
616 		// Loads a data structure with default information about a SegmentBlob, including its subtype,
617 		// character set, and segment size.
618 		void getDefault();
619 		// Sets the subtype and character set for a SegmentBlob.
620 		void set();
621 
622 	protected:
623 	private:
624 		ISC_BLOB_DESC blobDescr_;
625 		T_FB&         dll;
626 		Error&        ib_error;
627 	};
628 
629 	class SegmentBlob
630 	{
631 		friend class BlobDescr;
632 
633 	public:
634 		class info
635 		{
636 			friend class SegmentBlob;
637 
638 		public:
639 			info();
640 
641 		public:
getLenght()642 			long getLenght() const
643 			{
644 				return lenght_;
645 			}
getMaxSegments()646 			long getMaxSegments() const
647 			{
648 				return maxSegments_;
649 			}
getNumSegments()650 			long getNumSegments() const
651 			{
652 				return numSegments_;
653 			}
654 
655 		private:
656 			long    lenght_;
657 			long    maxSegments_;
658 			long    numSegments_;
659 			bool    type_segmented;
660 		};
661 
662 	public:
663 		SegmentBlob(const DataBase& db, const Transaction& tr, T_FB& dll, Error& ib_error);
664 		~SegmentBlob();
665 
666 	public:
667 		void open();
668 		void create();
669 		void close();
670 
671 		bool getSegment(
672 			unsigned short& actualSegLen,
673 			unsigned short maxSegLen,
674 			char* pSegment
675 		);
676 		// void addSegment(const String& data);
677 		void addSegment(const char* pSegment, unsigned short seg_length);
678 
679 		void put_segment(const char* data, size_t data_len);
680 
681 		void cancel();
682 
683 		void retrieve_info();
684 
getInfo()685 		const info& getInfo() const { return info_; }
686 
687 	public:
getID()688 		const GDS_QUAD& getID() const
689 		{
690 			return id_;
691 		}
getID()692 		GDS_QUAD& getID()
693 		{
694 			return id_;
695 		}
696 
697 	private:
698 		// Not documented ...
699 		void open_internal();
700 		void open2_internal();
701 
702 		void setup_open();
703 		void setup_close();
704 
705 		// Not documented ...
706 		void create_internal();
707 
708 		// Creates and opens the SegmentBlob for write access, and optionally specifies the filters to be used
709 		// to translate the SegmentBlob from one subtype to another.
710 		void create2_internal();
711 
712 	private:
713 		isc_db_handle*  pDBHandle_;
714 		isc_tr_handle*  pTRHandle_;
715 		isc_blob_handle handle_;        // It is a pointer, actualy.
716 
717 		T_FB&           dll;
718 		Error&          ib_error;
719 
720 		GDS_QUAD        id_;    // SegmentBlob ID put into out_sqlda by isc_dsql_fetch()
721 		int             stat_;
722 		bool            isOpen_;
723 		GDS_QUAD        lastID_;
724 
725 		// Info ...
726 		bool            hasInfo_;
727 		info            info_;
728 	};
729 
730 	class Array
731 	{
732 	public:
733 		Array(const DataBase& db, const Transaction& tr);
734 
735 	public:
getID()736 		const ISC_QUAD& getID() const
737 		{
738 			return id_;
739 		}
getID()740 		ISC_QUAD& getID()
741 		{
742 			return id_;
743 		}
744 
745 	protected:
746 		// isc_array_gen_sdl
747 		// isc_array_get_slice
748 		// isc_array_lookup_bounds
749 		// isc_array_lookup_desc
750 		// isc_array_set_desc
751 		// isc_array_put_slice
752 	private:
753 		isc_db_handle*  pDBHandle_;
754 		isc_tr_handle*  pTRHandle_;
755 
756 		ISC_QUAD		id_;
757 		ISC_ARRAY_DESC	desc_;
758 	};
759 
760 	class Event
761 	{
762 	public:
763 		Event();
764 
765 	protected:
766 		// isc_event_block
767 		// isc_event_counts
768 		// isc_que_events
769 	private:
770 	};
771 
772     enum network_protocol_t {
773 		np_embedded,
774 		np_local,
775 		np_TCP_IP,
776 		np_NetBEUI,
777 		np_IPX_SPX
778 		};
779 
780 	class Service
781 	{
782 	public:
Service(T_FB & dll,Error & ib_error)783 		Service(T_FB& dll, Error& ib_error) : dll(dll), ib_error(ib_error) {}
784 
785 		void attach(
786 			const char* host = NULL,
787 			const char* user = NULL,
788 			const char* pswd = NULL,
789 			network_protocol_t protocol = np_local
790 		);
791 
792 		void detach();
793 
794 		void executeCommand(const spb& pb);
795 
796 		void query(const spb& request, const spb& result);
797 
get_dll()798 		T_FB& get_dll() { return dll; }
get_ib_error()799 		Error& get_ib_error() { return ib_error; }
800 
801 	private:
802 		isc_svc_handle      handle_;
803 		T_FB& dll;
804 		Error& ib_error;
805 	};
806 
807 	class user_info : Moveable<user_info>
808 	{
809 	public:
810 		user_info();
811 		user_info(const user_info& info);
812 
813 	public:
814 		unsigned long user_id;
815 		unsigned long group_id;
816 		String user_name;
817 		String first_name;
818 		String middle_name;
819 		String last_name;
820 
821 	private:
822 		void copy(const user_info& info);
823 	};
824 
825 	class server_info
826 	{
827 	public:
828 		server_info();
829 		server_info(const server_info& info);
830 
831 	public:
832 		unsigned long svc_version;
833 		unsigned long num_licensed_users;
834 		String server_version;
835 		String implementation_str;
836 		String env_ib_str;
837 		String env_lock_str;
838 		String env_msg_str;
839 		String user_db_path_str;
840 
841 	private:
842 		void copy(const server_info& info);
843 	};
844 
845 	namespace svc_cmd
846 	{
847 		class base
848 		{
849 		public:
850 			base(Service& svc);
851 
852 		protected:
853 			unsigned long read_long(char*& p) const;
854 			unsigned short read_short(char*& p) const;
855 			String read_string(char*& p) const;
856 
857 		protected:
858 			Service*    svc_ptr_;
859 			spb         paramBuff_;
860 		};
861 
862 		class backup : base
863 		{
864 		public:
865 			backup(Service& svc);
866 		};
867 
868 		class restore : base
869 		{
870 		public:
871 			restore(Service& svc);
872 		};
873 
874 		class set_properties : base
875 		{
876 		public:
877 			set_properties(Service& svc);
878 		};
879 
880 		class repair : base
881 		{
882 		public:
883 			repair(Service& svc);
884 		};
885 
886 		class get_db_stats : base
887 		{
888 		public:
889 			get_db_stats(Service& svc);
890 		};
891 
892 		class get_server_info : base
893 		{
894 		public:
895 			get_server_info(Service& svc);
896 
897 		public:
898 			void execute();
get_info()899 			const server_info& get_info() const
900 			{
901 				return info_;
902 			}
903 
904 		public:
905 			server_info info_;
906 		};
907 
908 		class get_log : base
909 		{
910 		public:
911 			get_log(Service& svc);
912 		};
913 
914 		class get_user_info : base
915 		{
916 		public:
917 			get_user_info(Service& svc, const String& user_name);
918 
919 		public:
920 			void execute();
get_info()921 			const user_info& get_info() const
922 			{
923 				return info_;
924 			}
925 
926 		public:
927 			user_info info_;
928 			const String user_name_;
929 		};
930 
931 		class get_users : base
932 		{
933 		public:
934 			get_users(Service& svc);
935 
936 		public:
937 			void execute();
get_info()938 			const Vector<user_info>& get_info() const
939 			{
940 				return user_info_list_;
941 			}
942 
943 		public:
944 			Vector<user_info> user_info_list_;
945 		};
946 
947 		class add_user : base
948 		{
949 		public:
950 			add_user(Service& svc);
951 
952 		public:
953 			void execute();
954 
955 		public:
956 			void set_username(const char* name);
957 			void set_password(const char* pswd);
958 			void set_firstname(const char* value);
959 			void set_middlename(const char* value);
960 			void set_lastname(const char* value);
961 			void set_userid(unsigned long value);
962 			void set_groupid(unsigned long value);
963 			void set_groupname(const char* value);
964 			void set_rolename(const char* value);
965 		};
966 
967 		class delete_user : base
968 		{
969 		public:
970 			delete_user(Service& svc);
971 
972 		public:
973 			void execute();
974 
975 		public:
976 			void set_username(const char* name);
977 			void set_rolename(const char* value);
978 		};
979 
980 		class update_user : base
981 		{
982 		public:
983 			update_user(Service& svc);
984 
985 		public:
986 			void execute();
987 
988 		public:
989 			void set_username(const char* name);
990 			void set_password(const char* pswd);
991 			void set_firstname(const char* value);
992 			void set_middlename(const char* value);
993 			void set_lastname(const char* value);
994 			void set_userid(unsigned long value);
995 			void set_groupid(unsigned long value);
996 			void set_groupname(const char* value);
997 			void set_rolename(const char* value);
998 		};
999 
1000 		class add_license : base
1001 		{
1002 		public:
1003 			add_license(Service& svc);
1004 		};
1005 
1006 		class remove_license : base
1007 		{
1008 		public:
1009 			remove_license(Service& svc);
1010 		};
1011 	}
1012 
1013 	class Install
1014 	{
1015 	};
1016 
1017 }
1018 
1019 #endif
1020