| C++ Wrapper Library for Firebird Embedded SQL |
|
|
|
| Wednesday, 19 August 2009 14:11 | ||||||||||||||||||||||||||||||||||||||||||
|
This article is devoted to the Embedded Firebird database usage and also development of C++ wrapper of this database. Advantage of Embedded Firebird database is that it enables to save your application user’s time on database installation and also reduce requirements to his technical knowledge level.
Written by:
1. Embedded Firebird1.1. Limitations of Embedded FirebirdIf you want to use Embedded Firebird you should know about those limitations it applies to your work (version 2.0.5): - THERE IS NO SUPPORT OF UNICODE. If you want to store information in unicode then you will have to care about the strings to be twice shorter than the maximal string length, and also store them as the arrays of bytes. You will have to convert such array to the Unicode when you get it. - THERE IS NO SUPPORT OF UNICODE PATHS. Especially sad thing here is that library functions for creation and opening the Firebird databases do not support the Unicode paths. - SIZE OF THE STORED PROCEDURE NAMES IS LIMITED. Such limitation is present in each database; however, in Firebird this size is depressingly small - just 30 characters. Usually this size is enough, but if you use the automatically generated names of the stored procedures, which include the names of the module and class, functional meaning and possibly limitations, it can be not enough. Anyway you should remember about this. 1.2. Building fbclient.dllIn order to proceed to the use of Firebird possibilities, you need to build the source code into the library (source code can be taken from the site http://firebirdsql.org ). To build it you should go to the directory \builds\win32 and use .bat file make_all.bat. The result will be files with the generated base definitions, constants and descriptions of the functions which will be located in the \output directory. In your work you will need the libraries fbclient_ms.lib (\output\lib), icu*.dll (\output\bin) and fbclient.dll (\output\bin). However, it is necessary to remember that if you want to use Embedded Firebird then you should rename fbembed.dll in fbclient.dll and use this library. For our wrapper we chose the least of files from \output and \src sufficient to use Firebird. These chosen in experimental way files can be seen in the directory of our project \fbembed_provider_include. To work with the Firebird database you should link library fbclient_ms.lib (\fbembed_provider_include\lib) to your project and place all dll-s (\fbembed_provider_include\dll) in the system directory ( /windows/system32). 2. C++ WrapperOur wrapper allows to: - Put aside the details of FireBird database implementation 2.1. Work with the databaseThere are such functions to work with the database files: - It is also possible to specify login and password to access the base. If they are not specified then the standard login “SYSDBA” and password “MASTERKEY” are used. - - To execute firebird-SQL constructions in different transactions the Allowed constructions that can’t be used in one transaction are simultaneous table creation and using. Example. Creation and setting connection with the database. std::string db_name = "c:\defaultbase.fdb"; fb::CreateDatabase ( db_name ); fb::CFirebirdForge forge ( db_name ); // attach inside 2.2. Forge and Procedure
- The name of the procedure is passed to the constructor and also the pointer to the buffer where all obtained data will be saved. If the stored procedure has input parameters then it is necessary to add them in the same sequence and with the same names as they are used in this procedure (functions of If the procedure has output parameters then it is necessary to define them by means of the functions Example. Creation and execution of the procedure. fb::CFirebirdForge forge ( db_name );
std::auto_ptr pProc (forge.CreateProcedure
( "TEST_{id}", "INSERT", NULL) );
//this should be TEST_INSERT procedure
// add correct input arguments by type and sequence
pProc->AddStringIn( strVal );
pProc->AddWStringIn ( wstrVal );
pProc->AddDoubleIn ( dVal );
pProc->AddSingleIn ( fVal );
pProc->AddBinaryIn ( binVal );
pProc->AddInt8In ( int8Val );
pProc->AddInt16In ( int16Val );
pProc->AddInt32In( int32Val );
pProc->AddInt64In ( int64Val );
pProc->AddDateTimeIn ( timeVal );
pProc->AddGuidStringIn ( guidVal );
pProc->AddLongBinaryIn ( lbinValCpy );
pProc->AddLongWStringIn ( ltxtVal );
pProc->Execute();
- Example. fb::CFirebirdForge forge ( db_name );
std::auto_ptr pQueryTable ( forge.CreateQuery
("CREATE TABLE TBLTESTTYPES( \
STRING Varchar(255),}
_ WSTRING Varchar(512),}
_ DOUBLE_T Double precision NOT NULL,}
_ FLOAT_T Float NOT NULL,}
_ BINARY Varchar(1024),}
_ INT8 Char(1) NOT NULL,}
_ INT16 Smallint NOT NULL,}
_ INT32 Integer NOT NULL,}
_ INT64 Numeric(10,0) NOT NULL,}
_ DATETIME Timestamp NOT NULL,}
_ GUID Varchar(36) NOT NULL,}
_ BLOBBIN Blob sub_type 0,\
BLOBTEXT Blob sub_type 1\
);" ) );
pQueryTable->Execute ();
If it is necessary to execute a SQL-query which returns some parameters, simply create a stored procedure for it using 2.3. Work with typesTe behavior of different data types which the wrapper works with is described in the
Depending on the C++ data types you need to store the different functions of FirebirdProcedure class are used. Functions of this class allocate the memory for variables and convert their values to the format required for work with Firebird SQL. To put these problems aside from the wrapper users the format of Firebird SQL fields where the information will be stored is predefined. You can see the correspondence in the table:
For simple types (integer ones and types with a floating point) the general template format is used. For types which do not just allocate data or use difficult logic of converting there are specializations: - time ( In our realization the time is used as a double type and is a variant presentation of time (see functions of converting in fbutils.cpp - - string ( It is necessary to allocate memory dynamically in this type, and there is different volume for CHAR and VARYING. Also it is possible to add Unicode to them by - arrays of data ( Special group of functions is used to work with the BLOB type. Firebird does not enable to write or read the arrays of data directly. To work with them you should first get a handle, by means of which you can write or read information. Functions If you want to write NULL value in any field of any type then during the initialization of variables in procedure write -1 in the We didn’t implement such types as DATE, TIME in our code, but it’s not hard to add them if you want to use just these types. 2.4. BufferReader and BufferWriterAll data obtained from the stored procedures are serialized in the buffer by the The The special function of
Example. Obtaining results. std::vector arrOut;
std::auto_ptr pProc ( pAdoForge->CreateProcedure (
"TEST_{id}", "SELECT", &arrOut ) );
... // add out parameters
pProc->Execute();
cmn::BufferReader br;
br.ConnectTo ( &arrOut.front(), arrOut.size() );
for ( int I = 0, count = br.read_int32(); I != count; ++I )
{
// get the return values from buffer
//br.read_string () / br.read_wstring () / br.read_double ();
}
3. Structure of project filesSrc\FireBird.sln – solution file for Microsoft Visual Studio 2003 5. List of the recommended literature All information about Firebird SQL can be found in the official sources Download Wrapper Source Files. |






